]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/home/user-record-pwquality.c
7e18773232c567eaa66239a8882ee71d097f5872
[thirdparty/systemd.git] / src / home / user-record-pwquality.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "bus-common-errors.h"
4 #include "errno-util.h"
5 #include "home-util.h"
6 #include "libcrypt-util.h"
7 #include "pwquality-util.h"
8 #include "strv.h"
9 #include "user-record-pwquality.h"
10 #include "user-record-util.h"
11
12 #if HAVE_PWQUALITY
13
14 int user_record_quality_check_password(
15 UserRecord *hr,
16 UserRecord *secret,
17 sd_bus_error *error) {
18
19 _cleanup_free_ char *auxerror = NULL;
20 int r;
21
22 assert(hr);
23 assert(secret);
24
25 /* This is a bit more complex than one might think at first. quality_check_password() would like to know the
26 * old password to make security checks. We support arbitrary numbers of passwords however, hence we
27 * call the function once for each combination of old and new password. */
28
29 /* Iterate through all new passwords */
30 STRV_FOREACH(pp, secret->password) {
31 bool called = false;
32
33 r = test_password_many(hr->hashed_password, *pp);
34 if (r < 0)
35 return r;
36 if (r == 0) /* This is an old password as it isn't listed in the hashedPassword field, skip it */
37 continue;
38
39 /* Check this password against all old passwords */
40 STRV_FOREACH(old, secret->password) {
41
42 if (streq(*pp, *old))
43 continue;
44
45 r = test_password_many(hr->hashed_password, *old);
46 if (r < 0)
47 return r;
48 if (r > 0) /* This is a new password, not suitable as old password */
49 continue;
50
51 r = quality_check_password(*pp, *old, hr->user_name, &auxerror);
52 if (r <= 0)
53 goto error;
54
55 called = true;
56 }
57
58 if (called)
59 continue;
60
61 /* If there are no old passwords, let's call quality_check_password() without any. */
62 r = quality_check_password(*pp, /* old */ NULL, hr->user_name, &auxerror);
63 if (r <= 0)
64 goto error;
65 }
66
67 return 1;
68
69 error:
70 if (r == 0)
71 return sd_bus_error_setf(error, BUS_ERROR_LOW_PASSWORD_QUALITY,
72 "Password too weak: %s", auxerror);
73 if (ERRNO_IS_NOT_SUPPORTED(r))
74 return 0;
75 return log_debug_errno(r, "Failed to check password quality: %m");
76 }
77
78 #else
79
80 int user_record_quality_check_password(
81 UserRecord *hr,
82 UserRecord *secret,
83 sd_bus_error *error) {
84
85 return 0;
86 }
87
88 #endif