shared: add password quality check abstraction layer to support both pwquality and...
authorEgor Ignatov <egori@altlinux.org>
Fri, 6 Aug 2021 08:40:34 +0000 (11:40 +0300)
committerDmitry V. Levin <ldv@strace.io>
Thu, 6 Jul 2023 10:59:41 +0000 (10:59 +0000)
Co-authored-by: Dmitry V. Levin <ldv@altlinux.org>
16 files changed:
src/cryptenroll/cryptenroll-password.c
src/firstboot/firstboot.c
src/home/homectl.c
src/home/homed-home.c
src/home/meson.build
src/home/user-record-password-quality.c [new file with mode: 0644]
src/home/user-record-password-quality.h [new file with mode: 0644]
src/home/user-record-pwquality.c [deleted file]
src/home/user-record-pwquality.h [deleted file]
src/shared/meson.build
src/shared/password-quality-util-pwquality.c [new file with mode: 0644]
src/shared/password-quality-util-pwquality.h [new file with mode: 0644]
src/shared/password-quality-util.h [new file with mode: 0644]
src/shared/pwquality-util.c [deleted file]
src/shared/pwquality-util.h [deleted file]
src/test/test-dlopen-so.c

index 44e6f0b227b6f1715836d843d3fb3f3a61d668a5..499dbbc627a775c4d12f636c87e5031736bc5ec9 100644 (file)
@@ -6,7 +6,7 @@
 #include "errno-util.h"
 #include "escape.h"
 #include "memory-util.h"
-#include "pwquality-util.h"
+#include "password-quality-util.h"
 #include "strv.h"
 
 int load_volume_key_password(
@@ -156,7 +156,7 @@ int enroll_password(
                 }
         }
 
-        r = quality_check_password(new_password, /* old */ NULL, /* user */ NULL, &error);
+        r = check_password_quality(new_password, /* old */ NULL, /* user */ NULL, &error);
         if (r < 0) {
                 if (ERRNO_IS_NOT_SUPPORTED(r))
                         log_warning("Password quality check is not supported, proceeding anyway.");
index 501f074c94f0776d1ee68e9cc0664280a0b7ad63..b993739083fa0b84f56ea28ef594882c34e70fc9 100644 (file)
 #include "os-util.h"
 #include "parse-argument.h"
 #include "parse-util.h"
+#include "password-quality-util.h"
 #include "path-util.h"
 #include "pretty-print.h"
 #include "proc-cmdline.h"
-#include "pwquality-util.h"
 #include "random-util.h"
 #include "smack-util.h"
 #include "string-util.h"
@@ -790,7 +790,7 @@ static int prompt_root_password(int rfd) {
                         break;
                 }
 
-                r = quality_check_password(*a, /* old */ NULL, "root", &error);
+                r = check_password_quality(*a, /* old */ NULL, "root", &error);
                 if (r < 0) {
                         if (ERRNO_IS_NOT_SUPPORTED(r))
                                 log_warning("Password quality check is not supported, proceeding anyway.");
index d6e6bd0855cd3ee4941561547287121e362aea43..55323b44e10c121eff61b355c9ca0784d734c35a 100644 (file)
 #include "pager.h"
 #include "parse-argument.h"
 #include "parse-util.h"
+#include "password-quality-util.h"
 #include "path-util.h"
 #include "percent-util.h"
 #include "pkcs11-util.h"
 #include "pretty-print.h"
 #include "process-util.h"
-#include "pwquality-util.h"
 #include "rlimit-util.h"
 #include "spawn-polkit-agent.h"
 #include "terminal-util.h"
 #include "uid-alloc-range.h"
 #include "user-record.h"
-#include "user-record-pwquality.h"
+#include "user-record-password-quality.h"
 #include "user-record-show.h"
 #include "user-record-util.h"
 #include "user-util.h"
@@ -1323,7 +1323,7 @@ static int create_home(int argc, char *argv[], void *userdata) {
 
                 /* If password quality enforcement is disabled, let's at least warn client side */
 
-                r = user_record_quality_check_password(hr, hr, &error);
+                r = user_record_check_password_quality(hr, hr, &error);
                 if (r < 0)
                         log_warning_errno(r, "Specified password does not pass quality checks (%s), proceeding anyway.", bus_error_message(&error, r));
         }
index a79a719383852a01b2cc5cd8dceb7a42028ba392..46d6fb589c16ddecd8a5dac207a0fd1cac0f9682 100644 (file)
@@ -31,7 +31,6 @@
 #include "mkdir.h"
 #include "path-util.h"
 #include "process-util.h"
-#include "pwquality-util.h"
 #include "quota-util.h"
 #include "resize-fs.h"
 #include "set.h"
@@ -40,7 +39,7 @@
 #include "string-table.h"
 #include "strv.h"
 #include "uid-alloc-range.h"
-#include "user-record-pwquality.h"
+#include "user-record-password-quality.h"
 #include "user-record-sign.h"
 #include "user-record-util.h"
 #include "user-record.h"
@@ -1513,7 +1512,7 @@ int home_create(Home *h, UserRecord *secret, sd_bus_error *error) {
         if (h->record->enforce_password_policy == false)
                 log_debug("Password quality check turned off for account, skipping.");
         else {
-                r = user_record_quality_check_password(h->record, secret, error);
+                r = user_record_check_password_quality(h->record, secret, error);
                 if (r < 0)
                         return r;
         }
@@ -1888,7 +1887,7 @@ int home_passwd(Home *h,
         if (c->enforce_password_policy == false)
                 log_debug("Password quality check turned off for account, skipping.");
         else {
-                r = user_record_quality_check_password(c, merged_secret, error);
+                r = user_record_check_password_quality(c, merged_secret, error);
                 if (r < 0)
                         return r;
         }
index 475faaefea9257acd315c5afef7bff64cf26e924..ff3cf411fedcb2cafd9bece1037c60911f1cbccf 100644 (file)
@@ -33,7 +33,7 @@ systemd_homed_sources = files(
         'homed-operation.c',
         'homed-varlink.c',
         'homed.c',
-        'user-record-pwquality.c',
+        'user-record-password-quality.c',
         'user-record-sign.c',
         'user-record-util.c',
 )
@@ -52,7 +52,7 @@ homectl_sources = files(
         'homectl-pkcs11.c',
         'homectl-recovery-key.c',
         'homectl.c',
-        'user-record-pwquality.c',
+        'user-record-password-quality.c',
         'user-record-util.c',
 )
 
diff --git a/src/home/user-record-password-quality.c b/src/home/user-record-password-quality.c
new file mode 100644 (file)
index 0000000..5c29096
--- /dev/null
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "bus-common-errors.h"
+#include "errno-util.h"
+#include "home-util.h"
+#include "libcrypt-util.h"
+#include "password-quality-util.h"
+#include "strv.h"
+#include "user-record-password-quality.h"
+#include "user-record-util.h"
+
+#if HAVE_PWQUALITY
+
+int user_record_check_password_quality(
+                UserRecord *hr,
+                UserRecord *secret,
+                sd_bus_error *error) {
+
+        _cleanup_free_ char *auxerror = NULL;
+        int r;
+
+        assert(hr);
+        assert(secret);
+
+        /* This is a bit more complex than one might think at first. check_password_quality() would like to know the
+         * old password to make security checks. We support arbitrary numbers of passwords however, hence we
+         * call the function once for each combination of old and new password. */
+
+        /* Iterate through all new passwords */
+        STRV_FOREACH(pp, secret->password) {
+                bool called = false;
+
+                r = test_password_many(hr->hashed_password, *pp);
+                if (r < 0)
+                        return r;
+                if (r == 0) /* This is an old password as it isn't listed in the hashedPassword field, skip it */
+                        continue;
+
+                /* Check this password against all old passwords */
+                STRV_FOREACH(old, secret->password) {
+
+                        if (streq(*pp, *old))
+                                continue;
+
+                        r = test_password_many(hr->hashed_password, *old);
+                        if (r < 0)
+                                return r;
+                        if (r > 0) /* This is a new password, not suitable as old password */
+                                continue;
+
+                        r = check_password_quality(*pp, *old, hr->user_name, &auxerror);
+                        if (r <= 0)
+                                goto error;
+
+                        called = true;
+                }
+
+                if (called)
+                        continue;
+
+                /* If there are no old passwords, let's call check_password_quality() without any. */
+                r = check_password_quality(*pp, /* old */ NULL, hr->user_name, &auxerror);
+                if (r <= 0)
+                        goto error;
+        }
+        return 1;
+
+error:
+        if (r == 0)
+                return sd_bus_error_setf(error, BUS_ERROR_LOW_PASSWORD_QUALITY,
+                                         "Password too weak: %s", auxerror);
+        if (ERRNO_IS_NOT_SUPPORTED(r))
+                return 0;
+        return log_debug_errno(r, "Failed to check password quality: %m");
+}
+
+#else
+
+int user_record_check_password_quality(
+                UserRecord *hr,
+                UserRecord *secret,
+                sd_bus_error *error) {
+
+        return 0;
+}
+
+#endif
diff --git a/src/home/user-record-password-quality.h b/src/home/user-record-password-quality.h
new file mode 100644 (file)
index 0000000..c7d6ec6
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "sd-bus.h"
+#include "user-record.h"
+
+int user_record_check_password_quality(UserRecord *hr, UserRecord *secret, sd_bus_error *error);
diff --git a/src/home/user-record-pwquality.c b/src/home/user-record-pwquality.c
deleted file mode 100644 (file)
index 7e18773..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include "bus-common-errors.h"
-#include "errno-util.h"
-#include "home-util.h"
-#include "libcrypt-util.h"
-#include "pwquality-util.h"
-#include "strv.h"
-#include "user-record-pwquality.h"
-#include "user-record-util.h"
-
-#if HAVE_PWQUALITY
-
-int user_record_quality_check_password(
-                UserRecord *hr,
-                UserRecord *secret,
-                sd_bus_error *error) {
-
-        _cleanup_free_ char *auxerror = NULL;
-        int r;
-
-        assert(hr);
-        assert(secret);
-
-        /* This is a bit more complex than one might think at first. quality_check_password() would like to know the
-         * old password to make security checks. We support arbitrary numbers of passwords however, hence we
-         * call the function once for each combination of old and new password. */
-
-        /* Iterate through all new passwords */
-        STRV_FOREACH(pp, secret->password) {
-                bool called = false;
-
-                r = test_password_many(hr->hashed_password, *pp);
-                if (r < 0)
-                        return r;
-                if (r == 0) /* This is an old password as it isn't listed in the hashedPassword field, skip it */
-                        continue;
-
-                /* Check this password against all old passwords */
-                STRV_FOREACH(old, secret->password) {
-
-                        if (streq(*pp, *old))
-                                continue;
-
-                        r = test_password_many(hr->hashed_password, *old);
-                        if (r < 0)
-                                return r;
-                        if (r > 0) /* This is a new password, not suitable as old password */
-                                continue;
-
-                        r = quality_check_password(*pp, *old, hr->user_name, &auxerror);
-                        if (r <= 0)
-                                goto error;
-
-                        called = true;
-                }
-
-                if (called)
-                        continue;
-
-                /* If there are no old passwords, let's call quality_check_password() without any. */
-                r = quality_check_password(*pp, /* old */ NULL, hr->user_name, &auxerror);
-                if (r <= 0)
-                        goto error;
-        }
-
-        return 1;
-
-error:
-        if (r == 0)
-                return sd_bus_error_setf(error, BUS_ERROR_LOW_PASSWORD_QUALITY,
-                                         "Password too weak: %s", auxerror);
-        if (ERRNO_IS_NOT_SUPPORTED(r))
-                return 0;
-        return log_debug_errno(r, "Failed to check password quality: %m");
-}
-
-#else
-
-int user_record_quality_check_password(
-                UserRecord *hr,
-                UserRecord *secret,
-                sd_bus_error *error) {
-
-        return 0;
-}
-
-#endif
diff --git a/src/home/user-record-pwquality.h b/src/home/user-record-pwquality.h
deleted file mode 100644 (file)
index b3b2690..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include "sd-bus.h"
-#include "user-record.h"
-
-int user_record_quality_check_password(UserRecord *hr, UserRecord *secret, sd_bus_error *error);
index d643b2bd09358a651e468a88ab3b51d5ce1709aa..fe88731c32f01c622d9cfecc4c2e898899db9aac 100644 (file)
@@ -128,11 +128,11 @@ shared_sources = files(
         'pager.c',
         'parse-argument.c',
         'parse-helpers.c',
+        'password-quality-util-pwquality.c',
         'pcre2-util.c',
         'pkcs11-util.c',
         'pretty-print.c',
         'ptyfwd.c',
-        'pwquality-util.c',
         'qrcode-util.c',
         'quota-util.c',
         'reboot-util.c',
diff --git a/src/shared/password-quality-util-pwquality.c b/src/shared/password-quality-util-pwquality.c
new file mode 100644 (file)
index 0000000..80f7d58
--- /dev/null
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <unistd.h>
+
+#include "dlfcn-util.h"
+#include "errno-util.h"
+#include "log.h"
+#include "macro.h"
+#include "memory-util.h"
+#include "password-quality-util.h"
+#include "strv.h"
+
+#if HAVE_PWQUALITY
+
+static void *pwquality_dl = NULL;
+
+int (*sym_pwquality_check)(pwquality_settings_t *pwq, const char *password, const char *oldpassword, const char *user, void **auxerror);
+pwquality_settings_t *(*sym_pwquality_default_settings)(void);
+void (*sym_pwquality_free_settings)(pwquality_settings_t *pwq);
+int (*sym_pwquality_generate)(pwquality_settings_t *pwq, int entropy_bits, char **password);
+int (*sym_pwquality_get_str_value)(pwquality_settings_t *pwq, int setting, const char **value);
+int (*sym_pwquality_read_config)(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror);
+int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int value);
+const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror);
+
+int dlopen_pwquality(void) {
+        return dlopen_many_sym_or_warn(
+                        &pwquality_dl, "libpwquality.so.1", LOG_DEBUG,
+                        DLSYM_ARG(pwquality_check),
+                        DLSYM_ARG(pwquality_default_settings),
+                        DLSYM_ARG(pwquality_free_settings),
+                        DLSYM_ARG(pwquality_generate),
+                        DLSYM_ARG(pwquality_get_str_value),
+                        DLSYM_ARG(pwquality_read_config),
+                        DLSYM_ARG(pwquality_set_int_value),
+                        DLSYM_ARG(pwquality_strerror));
+}
+
+static void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) {
+        char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
+        const char *path;
+        int r;
+
+        assert(pwq);
+
+        r = sym_pwquality_get_str_value(pwq, PWQ_SETTING_DICT_PATH, &path);
+        if (r < 0) {
+                log_debug("Failed to read libpwquality dictionary path, ignoring: %s",
+                          sym_pwquality_strerror(buf, sizeof(buf), r, NULL));
+                return;
+        }
+
+        if (isempty(path)) {
+                log_debug("Weird, no dictionary file configured, ignoring.");
+                return;
+        }
+
+        if (access(path, F_OK) >= 0)
+                return;
+
+        if (errno != ENOENT) {
+                log_debug_errno(errno, "Failed to check if dictionary file %s exists, ignoring: %m", path);
+                return;
+        }
+
+        r = sym_pwquality_set_int_value(pwq, PWQ_SETTING_DICT_CHECK, 0);
+        if (r < 0)
+                log_debug("Failed to disable libpwquality dictionary check, ignoring: %s",
+                          sym_pwquality_strerror(buf, sizeof(buf), r, NULL));
+}
+
+static int pwq_allocate_context(pwquality_settings_t **ret) {
+        _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL;
+        char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
+        void *auxerror;
+        int r;
+
+        assert(ret);
+
+        r = dlopen_pwquality();
+        if (r < 0)
+                return r;
+
+        pwq = sym_pwquality_default_settings();
+        if (!pwq)
+                return -ENOMEM;
+
+        r = sym_pwquality_read_config(pwq, NULL, &auxerror);
+        if (r < 0)
+                log_debug("Failed to read libpwquality configuration, ignoring: %s",
+                          sym_pwquality_strerror(buf, sizeof(buf), r, auxerror));
+
+        pwq_maybe_disable_dictionary(pwq);
+
+        *ret = TAKE_PTR(pwq);
+        return 0;
+}
+
+int suggest_passwords(void) {
+        _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL;
+        _cleanup_strv_free_erase_ char **suggestions = NULL;
+        _cleanup_(erase_and_freep) char *joined = NULL;
+        char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
+        size_t i;
+        int r;
+
+        r = pwq_allocate_context(&pwq);
+        if (r < 0) {
+                if (ERRNO_IS_NOT_SUPPORTED(r))
+                        return 0;
+                return log_error_errno(r, "Failed to allocate libpwquality context: %m");
+        }
+
+        suggestions = new0(char*, N_SUGGESTIONS+1);
+        if (!suggestions)
+                return log_oom();
+
+        for (i = 0; i < N_SUGGESTIONS; i++) {
+                r = sym_pwquality_generate(pwq, 64, suggestions + i);
+                if (r < 0)
+                        return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate password, ignoring: %s",
+                                               sym_pwquality_strerror(buf, sizeof(buf), r, NULL));
+        }
+
+        joined = strv_join(suggestions, " ");
+        if (!joined)
+                return log_oom();
+
+        printf("Password suggestions: %s\n", joined);
+        return 1;
+}
+
+int check_password_quality(const char *password, const char *old, const char *username, char **ret_error) {
+        _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL;
+        char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
+        void *auxerror;
+        int r;
+
+        assert(password);
+
+        r = pwq_allocate_context(&pwq);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to allocate libpwquality context: %m");
+
+        r = sym_pwquality_check(pwq, password, old, username, &auxerror);
+        if (r < 0) {
+                if (ret_error) {
+                        _cleanup_free_ char *e = NULL;
+
+                        e = strdup(sym_pwquality_strerror(buf, sizeof(buf), r, auxerror));
+                        if (!e)
+                                return -ENOMEM;
+
+                        *ret_error = TAKE_PTR(e);
+                }
+
+                return 0; /* all bad */
+        }
+
+        return 1; /* all good */
+}
+
+#endif
diff --git a/src/shared/password-quality-util-pwquality.h b/src/shared/password-quality-util-pwquality.h
new file mode 100644 (file)
index 0000000..a420b0d
--- /dev/null
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "macro.h"
+
+#if HAVE_PWQUALITY
+/* pwquality.h uses size_t but doesn't include sys/types.h on its own */
+#include <sys/types.h>
+#include <pwquality.h>
+
+extern int (*sym_pwquality_check)(pwquality_settings_t *pwq, const char *password, const char *oldpassword, const char *user, void **auxerror);
+extern pwquality_settings_t *(*sym_pwquality_default_settings)(void);
+extern void (*sym_pwquality_free_settings)(pwquality_settings_t *pwq);
+extern int (*sym_pwquality_generate)(pwquality_settings_t *pwq, int entropy_bits, char **password);
+extern int (*sym_pwquality_get_str_value)(pwquality_settings_t *pwq, int setting, const char **value);
+extern int (*sym_pwquality_read_config)(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror);
+extern int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int value);
+extern const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror);
+
+int dlopen_pwquality(void);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pwquality_settings_t*, sym_pwquality_free_settings, NULL);
+
+int suggest_passwords(void);
+int check_password_quality(const char *password, const char *old, const char *username, char **ret_error);
+
+#endif
diff --git a/src/shared/password-quality-util.h b/src/shared/password-quality-util.h
new file mode 100644 (file)
index 0000000..a55727d
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#define N_SUGGESTIONS 6
+
+#if HAVE_PWQUALITY
+
+#include "password-quality-util-pwquality.h"
+
+#else
+
+static inline int suggest_passwords(void) {
+        return 0;
+}
+
+static inline int check_password_quality(
+                const char *password,
+                const char *old,
+                const char *username,
+                char **ret_error) {
+        if (ret_error)
+                *ret_error = NULL;
+        return 1; /* all good */
+}
+
+#endif
diff --git a/src/shared/pwquality-util.c b/src/shared/pwquality-util.c
deleted file mode 100644 (file)
index 4502083..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include <unistd.h>
-
-#include "dlfcn-util.h"
-#include "errno-util.h"
-#include "log.h"
-#include "macro.h"
-#include "memory-util.h"
-#include "pwquality-util.h"
-#include "strv.h"
-
-#if HAVE_PWQUALITY
-
-static void *pwquality_dl = NULL;
-
-int (*sym_pwquality_check)(pwquality_settings_t *pwq, const char *password, const char *oldpassword, const char *user, void **auxerror);
-pwquality_settings_t *(*sym_pwquality_default_settings)(void);
-void (*sym_pwquality_free_settings)(pwquality_settings_t *pwq);
-int (*sym_pwquality_generate)(pwquality_settings_t *pwq, int entropy_bits, char **password);
-int (*sym_pwquality_get_str_value)(pwquality_settings_t *pwq, int setting, const char **value);
-int (*sym_pwquality_read_config)(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror);
-int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int value);
-const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror);
-
-int dlopen_pwquality(void) {
-        return dlopen_many_sym_or_warn(
-                        &pwquality_dl, "libpwquality.so.1", LOG_DEBUG,
-                        DLSYM_ARG(pwquality_check),
-                        DLSYM_ARG(pwquality_default_settings),
-                        DLSYM_ARG(pwquality_free_settings),
-                        DLSYM_ARG(pwquality_generate),
-                        DLSYM_ARG(pwquality_get_str_value),
-                        DLSYM_ARG(pwquality_read_config),
-                        DLSYM_ARG(pwquality_set_int_value),
-                        DLSYM_ARG(pwquality_strerror));
-}
-
-void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) {
-        char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
-        const char *path;
-        int r;
-
-        assert(pwq);
-
-        r = sym_pwquality_get_str_value(pwq, PWQ_SETTING_DICT_PATH, &path);
-        if (r < 0) {
-                log_debug("Failed to read libpwquality dictionary path, ignoring: %s",
-                          sym_pwquality_strerror(buf, sizeof(buf), r, NULL));
-                return;
-        }
-
-        if (isempty(path)) {
-                log_debug("Weird, no dictionary file configured, ignoring.");
-                return;
-        }
-
-        if (access(path, F_OK) >= 0)
-                return;
-
-        if (errno != ENOENT) {
-                log_debug_errno(errno, "Failed to check if dictionary file %s exists, ignoring: %m", path);
-                return;
-        }
-
-        r = sym_pwquality_set_int_value(pwq, PWQ_SETTING_DICT_CHECK, 0);
-        if (r < 0)
-                log_debug("Failed to disable libpwquality dictionary check, ignoring: %s",
-                          sym_pwquality_strerror(buf, sizeof(buf), r, NULL));
-}
-
-int pwq_allocate_context(pwquality_settings_t **ret) {
-        _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL;
-        char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
-        void *auxerror;
-        int r;
-
-        assert(ret);
-
-        r = dlopen_pwquality();
-        if (r < 0)
-                return r;
-
-        pwq = sym_pwquality_default_settings();
-        if (!pwq)
-                return -ENOMEM;
-
-        r = sym_pwquality_read_config(pwq, NULL, &auxerror);
-        if (r < 0)
-                log_debug("Failed to read libpwquality configuration, ignoring: %s",
-                          sym_pwquality_strerror(buf, sizeof(buf), r, auxerror));
-
-        pwq_maybe_disable_dictionary(pwq);
-
-        *ret = TAKE_PTR(pwq);
-        return 0;
-}
-
-#define N_SUGGESTIONS 6
-
-int suggest_passwords(void) {
-        _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL;
-        _cleanup_strv_free_erase_ char **suggestions = NULL;
-        _cleanup_(erase_and_freep) char *joined = NULL;
-        char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
-        size_t i;
-        int r;
-
-        r = pwq_allocate_context(&pwq);
-        if (r < 0) {
-                if (ERRNO_IS_NOT_SUPPORTED(r))
-                        return 0;
-                return log_error_errno(r, "Failed to allocate libpwquality context: %m");
-        }
-
-        suggestions = new0(char*, N_SUGGESTIONS+1);
-        if (!suggestions)
-                return log_oom();
-
-        for (i = 0; i < N_SUGGESTIONS; i++) {
-                r = sym_pwquality_generate(pwq, 64, suggestions + i);
-                if (r < 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate password, ignoring: %s",
-                                               sym_pwquality_strerror(buf, sizeof(buf), r, NULL));
-        }
-
-        joined = strv_join(suggestions, " ");
-        if (!joined)
-                return log_oom();
-
-        printf("Password suggestions: %s\n", joined);
-        return 1;
-}
-
-int quality_check_password(const char *password, const char *old, const char *username, char **ret_error) {
-        _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL;
-        char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
-        void *auxerror;
-        int r;
-
-        assert(password);
-
-        r = pwq_allocate_context(&pwq);
-        if (r < 0)
-                return log_debug_errno(r, "Failed to allocate libpwquality context: %m");
-
-        r = sym_pwquality_check(pwq, password, old, username, &auxerror);
-        if (r < 0) {
-
-                if (ret_error) {
-                        _cleanup_free_ char *e = NULL;
-
-                        e = strdup(sym_pwquality_strerror(buf, sizeof(buf), r, auxerror));
-                        if (!e)
-                                return -ENOMEM;
-
-                        *ret_error = TAKE_PTR(e);
-                }
-
-                return 0; /* all bad */
-        }
-
-        return 1; /* all good */
-}
-
-#endif
diff --git a/src/shared/pwquality-util.h b/src/shared/pwquality-util.h
deleted file mode 100644 (file)
index 4e18f39..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include "macro.h"
-
-#if HAVE_PWQUALITY
-/* pwquality.h uses size_t but doesn't include sys/types.h on its own */
-#include <sys/types.h>
-#include <pwquality.h>
-
-extern int (*sym_pwquality_check)(pwquality_settings_t *pwq, const char *password, const char *oldpassword, const char *user, void **auxerror);
-extern pwquality_settings_t *(*sym_pwquality_default_settings)(void);
-extern void (*sym_pwquality_free_settings)(pwquality_settings_t *pwq);
-extern int (*sym_pwquality_generate)(pwquality_settings_t *pwq, int entropy_bits, char **password);
-extern int (*sym_pwquality_get_str_value)(pwquality_settings_t *pwq, int setting, const char **value);
-extern int (*sym_pwquality_read_config)(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror);
-extern int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int value);
-extern const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror);
-
-int dlopen_pwquality(void);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pwquality_settings_t*, sym_pwquality_free_settings, NULL);
-
-void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq);
-int pwq_allocate_context(pwquality_settings_t **ret);
-int suggest_passwords(void);
-int quality_check_password(const char *password, const char *old, const char *username, char **ret_error);
-
-#else
-
-static inline int suggest_passwords(void) {
-        return 0;
-}
-
-static inline int quality_check_password(const char *password, const char *old, const char *username, char **ret_error) {
-        if (ret_error)
-                *ret_error = NULL;
-        return 1; /* all good */
-}
-
-#endif
index 55728c27c522444bd268362ec8673bc383a8629e..2d3b7744f68916ed22e588bf0d3d95da241aec0f 100644 (file)
@@ -10,9 +10,9 @@
 #include "libfido2-util.h"
 #include "macro.h"
 #include "main-func.h"
+#include "password-quality-util-pwquality.h"
 #include "pcre2-util.h"
 #include "pkcs11-util.h"
-#include "pwquality-util.h"
 #include "qrcode-util.h"
 #include "tests.h"
 #include "tpm2-util.h"