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:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -6,6 +6,5 @@ executables += [
|
||||
'public' : true,
|
||||
'conditions' : ['ENABLE_FIRSTBOOT'],
|
||||
'sources' : files('firstboot.c'),
|
||||
'dependencies' : libcrypt,
|
||||
},
|
||||
]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ libshared_deps = [threads,
|
||||
libaudit_cflags,
|
||||
libblkid_cflags,
|
||||
libbpf_cflags,
|
||||
libcrypt,
|
||||
libcrypt_cflags,
|
||||
libcryptsetup_cflags,
|
||||
libdl,
|
||||
libdw_cflags,
|
||||
|
||||
@@ -345,7 +345,6 @@ executables += [
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-libcrypt-util.c'),
|
||||
'dependencies' : libcrypt,
|
||||
'conditions' : ['HAVE_LIBCRYPT'],
|
||||
'timeout' : 120,
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user