libcrypt-util: turn into dlopen() dependency

Note, this drops logging only test case for crypt_preferred_method(),
as that requires explicitly dlopen() the library. But, we should test
that make_salt() and friends automatically dlopen() it.
This commit is contained in:
Yu Watanabe
2026-01-02 13:06:14 +09:00
parent 8de783a288
commit d0b224f845
10 changed files with 80 additions and 19 deletions
+1 -1
View File
@@ -212,7 +212,7 @@ REQUIREMENTS:
newer though. TL;DR: turn audit off, still.
glibc >= 2.31
libxcrypt >= 4.4.0
libxcrypt >= 4.4.0 (optional)
libmount >= 2.30 (from util-linux)
(util-linux *must* be built without --enable-libmount-support-mtab)
libseccomp >= 2.4.0 (optional)
+2
View File
@@ -1039,11 +1039,13 @@ endif
if get_option('libc') == 'musl'
libcrypt = []
libcrypt_cflags = []
have = get_option('libcrypt').allowed()
else
libcrypt = dependency('libcrypt', 'libxcrypt',
required : get_option('libcrypt'),
version : '>=4.4.0')
libcrypt_cflags = libcrypt.partial_dependency(includes: true, compile_args: true)
have = libcrypt.found()
endif
conf.set10('HAVE_LIBCRYPT', have)
-1
View File
@@ -6,6 +6,5 @@ executables += [
'public' : true,
'conditions' : ['ENABLE_FIRSTBOOT'],
'sources' : files('firstboot.c'),
'dependencies' : libcrypt,
},
]
-4
View File
@@ -64,7 +64,6 @@ executables += [
'sources' : systemd_homed_sources,
'extract' : systemd_homed_extract_sources,
'dependencies' : [
libcrypt,
libm,
libopenssl,
threads,
@@ -80,7 +79,6 @@ executables += [
],
'dependencies' : [
libblkid_cflags,
libcrypt,
libfdisk,
libopenssl,
libp11kit_cflags,
@@ -93,7 +91,6 @@ executables += [
'sources' : homectl_sources,
'objects' : ['systemd-homed'],
'dependencies' : [
libcrypt,
libdl,
libopenssl,
libp11kit_cflags,
@@ -112,7 +109,6 @@ modules += [
'conditions' : ['HAVE_PAM'],
'sources' : pam_systemd_home_sources,
'dependencies' : [
libcrypt,
libintl,
libpam_misc,
libpam,
+70 -5
View File
@@ -5,6 +5,7 @@
#endif
#include "alloc-util.h"
#include "dlfcn-util.h"
#include "errno-util.h"
#include "libcrypt-util.h"
#include "log.h"
@@ -12,19 +13,79 @@
#include "strv.h"
#if HAVE_LIBCRYPT
static void *libcrypt_dl = NULL;
static DLSYM_PROTOTYPE(crypt_gensalt_ra) = NULL;
static DLSYM_PROTOTYPE(crypt_preferred_method) = NULL;
static DLSYM_PROTOTYPE(crypt_ra) = NULL;
int dlopen_libcrypt(void) {
#ifdef __GLIBC__
static int cached = 0;
int r;
if (libcrypt_dl)
return 0; /* Already loaded */
if (cached < 0)
return cached; /* Already tried, and failed. */
/* Several distributions like Debian/Ubuntu and OpenSUSE provide libxcrypt as libcrypt.so.1,
* while others like Fedora/CentOS and Arch provide it as libcrypt.so.2. */
ELF_NOTE_DLOPEN("crypt",
"Support for hashing passwords",
ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
"libcrypt.so.2", "libcrypt.so.1");
_cleanup_(dlclosep) void *dl = NULL;
r = dlopen_safe("libcrypt.so.2", &dl, /* reterr_dlerror= */ NULL);
if (r < 0) {
const char *dle = NULL;
r = dlopen_safe("libcrypt.so.1", &dl, &dle);
if (r < 0) {
log_debug_errno(r, "libcrypt.so.2/libcrypt.so.1 is not available: %s", dle ?: STRERROR(r));
return (cached = -EOPNOTSUPP); /* turn into recognizable error */
}
log_debug("Loaded 'libcrypt.so.1' via dlopen()");
} else
log_debug("Loaded 'libcrypt.so.2' via dlopen()");
r = dlsym_many_or_warn(
dl, LOG_DEBUG,
DLSYM_ARG(crypt_gensalt_ra),
DLSYM_ARG(crypt_preferred_method),
DLSYM_ARG(crypt_ra));
if (r < 0)
return (cached = r);
libcrypt_dl = TAKE_PTR(dl);
#else
libcrypt_dl = NULL;
sym_crypt_gensalt_ra = missing_crypt_gensalt_ra;
sym_crypt_preferred_method = missing_crypt_preferred_method;
sym_crypt_ra = missing_crypt_ra;
#endif
return 0;
}
int make_salt(char **ret) {
const char *e;
char *salt;
int r;
assert(ret);
r = dlopen_libcrypt();
if (r < 0)
return r;
e = secure_getenv("SYSTEMD_CRYPT_PREFIX");
if (!e)
e = crypt_preferred_method();
e = sym_crypt_preferred_method();
log_debug("Generating salt for hash prefix: %s", e);
salt = crypt_gensalt_ra(e, 0, NULL, 0);
salt = sym_crypt_gensalt_ra(e, 0, NULL, 0);
if (!salt)
return -errno;
@@ -46,7 +107,7 @@ int hash_password(const char *password, char **ret) {
return log_debug_errno(r, "Failed to generate salt: %m");
errno = 0;
p = crypt_ra(password, salt, &cd_data, &cd_size);
p = sym_crypt_ra(password, salt, &cd_data, &cd_size);
if (!p)
return log_debug_errno(errno_or_else(SYNTHETIC_ERRNO(EINVAL)), "crypt_ra() failed: %m");
@@ -55,14 +116,18 @@ int hash_password(const char *password, char **ret) {
int test_password_one(const char *hashed_password, const char *password) {
_cleanup_(erase_and_freep) void *cd_data = NULL;
int cd_size = 0;
int r, cd_size = 0;
const char *k;
assert(hashed_password);
assert(password);
r = dlopen_libcrypt();
if (r < 0)
return r;
errno = 0;
k = crypt_ra(password, hashed_password, &cd_data, &cd_size);
k = sym_crypt_ra(password, hashed_password, &cd_data, &cd_size);
if (!k) {
if (errno == ENOMEM)
return -ENOMEM;
+4
View File
@@ -4,6 +4,7 @@
#include "shared-forward.h"
#if HAVE_LIBCRYPT
int dlopen_libcrypt(void);
int make_salt(char **ret);
int hash_password(const char *password, char **ret);
int test_password_one(const char *hashed_password, const char *password);
@@ -11,6 +12,9 @@ int test_password_many(char **hashed_password, const char *password);
#else
static inline int dlopen_libcrypt(void) {
return -EOPNOTSUPP;
}
static inline int hash_password(const char *password, char **ret) {
return -EOPNOTSUPP;
}
+1 -1
View File
@@ -367,7 +367,7 @@ libshared_deps = [threads,
libaudit_cflags,
libblkid_cflags,
libbpf_cflags,
libcrypt,
libcrypt_cflags,
libcryptsetup_cflags,
libdl,
libdw_cflags,
-1
View File
@@ -345,7 +345,6 @@ executables += [
},
test_template + {
'sources' : files('test-libcrypt-util.c'),
'dependencies' : libcrypt,
'conditions' : ['HAVE_LIBCRYPT'],
'timeout' : 120,
},
+2
View File
@@ -11,6 +11,7 @@
#include "idn-util.h"
#include "libarchive-util.h"
#include "libaudit-util.h"
#include "libcrypt-util.h"
#include "libfido2-util.h"
#include "libmount-util.h"
#include "main-func.h"
@@ -52,6 +53,7 @@ static int run(int argc, char **argv) {
ASSERT_DLOPEN(dlopen_libarchive, HAVE_LIBARCHIVE);
ASSERT_DLOPEN(dlopen_libaudit, HAVE_AUDIT);
ASSERT_DLOPEN(dlopen_libblkid, HAVE_BLKID);
ASSERT_DLOPEN(dlopen_libcrypt, HAVE_LIBCRYPT);
ASSERT_DLOPEN(dlopen_libfido2, HAVE_LIBFIDO2);
ASSERT_DLOPEN(dlopen_libkmod, HAVE_KMOD);
ASSERT_DLOPEN(dlopen_libmount, HAVE_LIBMOUNT);
-6
View File
@@ -1,15 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <crypt.h>
#include "libcrypt-util.h"
#include "strv.h"
#include "tests.h"
TEST(crypt_preferred_method) {
log_info("crypt_preferred_method: %s", crypt_preferred_method());
}
TEST(make_salt) {
_cleanup_strv_free_ char **l = NULL;