]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
679badd7 LP |
2 | |
3 | #include <unistd.h> | |
4 | ||
5 | #include "dlfcn-util.h" | |
6 | #include "errno-util.h" | |
7 | #include "log.h" | |
8 | #include "macro.h" | |
9 | #include "memory-util.h" | |
d34b1823 | 10 | #include "password-quality-util.h" |
679badd7 LP |
11 | #include "strv.h" |
12 | ||
13 | #if HAVE_PWQUALITY | |
14 | ||
15 | static void *pwquality_dl = NULL; | |
16 | ||
17 | int (*sym_pwquality_check)(pwquality_settings_t *pwq, const char *password, const char *oldpassword, const char *user, void **auxerror); | |
18 | pwquality_settings_t *(*sym_pwquality_default_settings)(void); | |
19 | void (*sym_pwquality_free_settings)(pwquality_settings_t *pwq); | |
20 | int (*sym_pwquality_generate)(pwquality_settings_t *pwq, int entropy_bits, char **password); | |
21 | int (*sym_pwquality_get_str_value)(pwquality_settings_t *pwq, int setting, const char **value); | |
22 | int (*sym_pwquality_read_config)(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror); | |
23 | int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int value); | |
24 | const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror); | |
25 | ||
26 | int dlopen_pwquality(void) { | |
1622ef77 ZJS |
27 | return dlopen_many_sym_or_warn( |
28 | &pwquality_dl, "libpwquality.so.1", LOG_DEBUG, | |
5517e214 LP |
29 | DLSYM_ARG(pwquality_check), |
30 | DLSYM_ARG(pwquality_default_settings), | |
31 | DLSYM_ARG(pwquality_free_settings), | |
32 | DLSYM_ARG(pwquality_generate), | |
33 | DLSYM_ARG(pwquality_get_str_value), | |
34 | DLSYM_ARG(pwquality_read_config), | |
35 | DLSYM_ARG(pwquality_set_int_value), | |
1622ef77 | 36 | DLSYM_ARG(pwquality_strerror)); |
679badd7 LP |
37 | } |
38 | ||
d34b1823 | 39 | static void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) { |
679badd7 LP |
40 | char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; |
41 | const char *path; | |
42 | int r; | |
43 | ||
44 | assert(pwq); | |
45 | ||
46 | r = sym_pwquality_get_str_value(pwq, PWQ_SETTING_DICT_PATH, &path); | |
47 | if (r < 0) { | |
48 | log_debug("Failed to read libpwquality dictionary path, ignoring: %s", | |
49 | sym_pwquality_strerror(buf, sizeof(buf), r, NULL)); | |
50 | return; | |
51 | } | |
52 | ||
679badd7 LP |
53 | if (isempty(path)) { |
54 | log_debug("Weird, no dictionary file configured, ignoring."); | |
55 | return; | |
56 | } | |
57 | ||
58 | if (access(path, F_OK) >= 0) | |
59 | return; | |
60 | ||
61 | if (errno != ENOENT) { | |
62 | log_debug_errno(errno, "Failed to check if dictionary file %s exists, ignoring: %m", path); | |
63 | return; | |
64 | } | |
65 | ||
66 | r = sym_pwquality_set_int_value(pwq, PWQ_SETTING_DICT_CHECK, 0); | |
67 | if (r < 0) | |
68 | log_debug("Failed to disable libpwquality dictionary check, ignoring: %s", | |
69 | sym_pwquality_strerror(buf, sizeof(buf), r, NULL)); | |
70 | } | |
71 | ||
d34b1823 | 72 | static int pwq_allocate_context(pwquality_settings_t **ret) { |
679badd7 LP |
73 | _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; |
74 | char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; | |
75 | void *auxerror; | |
76 | int r; | |
77 | ||
78 | assert(ret); | |
79 | ||
80 | r = dlopen_pwquality(); | |
81 | if (r < 0) | |
82 | return r; | |
83 | ||
84 | pwq = sym_pwquality_default_settings(); | |
85 | if (!pwq) | |
86 | return -ENOMEM; | |
87 | ||
88 | r = sym_pwquality_read_config(pwq, NULL, &auxerror); | |
89 | if (r < 0) | |
90 | log_debug("Failed to read libpwquality configuration, ignoring: %s", | |
91 | sym_pwquality_strerror(buf, sizeof(buf), r, auxerror)); | |
92 | ||
93 | pwq_maybe_disable_dictionary(pwq); | |
94 | ||
95 | *ret = TAKE_PTR(pwq); | |
96 | return 0; | |
97 | } | |
98 | ||
679badd7 LP |
99 | int suggest_passwords(void) { |
100 | _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; | |
101 | _cleanup_strv_free_erase_ char **suggestions = NULL; | |
102 | _cleanup_(erase_and_freep) char *joined = NULL; | |
103 | char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; | |
104 | size_t i; | |
105 | int r; | |
106 | ||
107 | r = pwq_allocate_context(&pwq); | |
29dd2e25 DL |
108 | if (r < 0) { |
109 | if (ERRNO_IS_NOT_SUPPORTED(r)) | |
110 | return 0; | |
679badd7 | 111 | return log_error_errno(r, "Failed to allocate libpwquality context: %m"); |
29dd2e25 | 112 | } |
679badd7 LP |
113 | |
114 | suggestions = new0(char*, N_SUGGESTIONS+1); | |
115 | if (!suggestions) | |
116 | return log_oom(); | |
117 | ||
118 | for (i = 0; i < N_SUGGESTIONS; i++) { | |
119 | r = sym_pwquality_generate(pwq, 64, suggestions + i); | |
120 | if (r < 0) | |
121 | return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate password, ignoring: %s", | |
122 | sym_pwquality_strerror(buf, sizeof(buf), r, NULL)); | |
123 | } | |
124 | ||
125 | joined = strv_join(suggestions, " "); | |
126 | if (!joined) | |
127 | return log_oom(); | |
128 | ||
0351d560 | 129 | printf("Password suggestions: %s\n", joined); |
679badd7 LP |
130 | return 1; |
131 | } | |
132 | ||
d34b1823 | 133 | int check_password_quality(const char *password, const char *old, const char *username, char **ret_error) { |
7baf10a7 LP |
134 | _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; |
135 | char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; | |
136 | void *auxerror; | |
137 | int r; | |
138 | ||
139 | assert(password); | |
140 | ||
141 | r = pwq_allocate_context(&pwq); | |
7fc3f9c0 | 142 | if (r < 0) |
7baf10a7 LP |
143 | return log_debug_errno(r, "Failed to allocate libpwquality context: %m"); |
144 | ||
bc0ef0e2 | 145 | r = sym_pwquality_check(pwq, password, old, username, &auxerror); |
7baf10a7 | 146 | if (r < 0) { |
7baf10a7 LP |
147 | if (ret_error) { |
148 | _cleanup_free_ char *e = NULL; | |
149 | ||
150 | e = strdup(sym_pwquality_strerror(buf, sizeof(buf), r, auxerror)); | |
151 | if (!e) | |
152 | return -ENOMEM; | |
153 | ||
154 | *ret_error = TAKE_PTR(e); | |
155 | } | |
156 | ||
157 | return 0; /* all bad */ | |
158 | } | |
159 | ||
160 | return 1; /* all good */ | |
161 | } | |
162 | ||
679badd7 | 163 | #endif |