]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
a937ce2d | 2 | |
83764f8d ZJS |
3 | #if HAVE_CRYPT_H |
4 | # include <crypt.h> | |
5 | #else | |
6 | # include <unistd.h> | |
7 | #endif | |
8 | ||
a937ce2d ZJS |
9 | #include "strv.h" |
10 | #include "tests.h" | |
11 | #include "libcrypt-util.h" | |
12 | ||
7ff9d99e ZJS |
13 | static void test_crypt_preferred_method(void) { |
14 | log_info("/* %s */", __func__); | |
15 | ||
16 | log_info("crypt_preferred_method: %s", | |
17 | #if HAVE_CRYPT_PREFERRED_METHOD | |
18 | crypt_preferred_method() | |
19 | #else | |
20 | "(not available)" | |
21 | #endif | |
22 | ); | |
23 | } | |
24 | ||
25 | static void test_make_salt(void) { | |
26 | log_info("/* %s */", __func__); | |
27 | ||
28 | for (int i = 0; i < 10; i++) { | |
29 | _cleanup_free_ char *t; | |
30 | ||
31 | assert_se(make_salt(&t) == 0); | |
32 | log_info("%s", t); | |
33 | } | |
34 | } | |
35 | ||
5d3fe6f7 ZJS |
36 | static int test_hash_password(void) { |
37 | log_info("/* %s */", __func__); | |
38 | ||
a3f5f4a5 | 39 | /* As a warm-up exercise, check if we can hash passwords. */ |
5d3fe6f7 ZJS |
40 | |
41 | bool have_sane_hash = false; | |
5d3fe6f7 ZJS |
42 | |
43 | FOREACH_STRING(hash, | |
44 | "ew3bU1.hoKk4o", | |
45 | "$1$gc5rWpTB$wK1aul1PyBn9AX1z93stk1", | |
46 | "$2b$12$BlqcGkB/7BFvNMXKGxDea.5/8D6FTny.cbNcHW/tqcrcyo6ZJd8u2", | |
47 | "$5$lGhDrcrao9zb5oIK$05KlOVG3ocknx/ThreqXE/gk.XzFFBMTksc4t2CPDUD", | |
48 | "$6$c7wB/3GiRk0VHf7e$zXJ7hN0aLZapE.iO4mn/oHu6.prsXTUG/5k1AxpgR85ELolyAcaIGRgzfwJs3isTChMDBjnthZyaMCfCNxo9I.", | |
49 | "$y$j9T$$9cKOWsAm4m97WiYk61lPPibZpy3oaGPIbsL4koRe/XD") { | |
50 | int b; | |
51 | ||
52 | b = test_password_one(hash, "ppp"); | |
53 | log_info("%s: %s", hash, yes_no(b)); | |
54 | #if defined(XCRYPT_VERSION_MAJOR) | |
55 | /* xcrypt is supposed to always implement all methods. */ | |
56 | assert_se(b); | |
57 | #endif | |
58 | ||
59 | if (b && IN_SET(hash[1], '6', 'y')) | |
60 | have_sane_hash = true; | |
61 | } | |
62 | ||
63 | return have_sane_hash; | |
64 | } | |
65 | ||
a937ce2d ZJS |
66 | static void test_hash_password_full(void) { |
67 | log_info("/* %s */", __func__); | |
68 | ||
69 | _cleanup_free_ void *cd_data = NULL; | |
a937ce2d ZJS |
70 | int cd_size = 0; |
71 | ||
72 | log_info("sizeof(struct crypt_data): %zu bytes", sizeof(struct crypt_data)); | |
73 | ||
74 | for (unsigned c = 0; c < 2; c++) | |
6016b4b0 | 75 | FOREACH_STRING(i, "abc123", "h⸿sło") { |
a937ce2d ZJS |
76 | _cleanup_free_ char *hashed; |
77 | ||
78 | if (c == 0) | |
79 | assert_se(hash_password_full(i, &cd_data, &cd_size, &hashed) == 0); | |
80 | else | |
81 | assert_se(hash_password_full(i, NULL, NULL, &hashed) == 0); | |
82 | log_debug("\"%s\" → \"%s\"", i, hashed); | |
83 | log_info("crypt_r[a] buffer size: %i bytes", cd_size); | |
6016b4b0 ZJS |
84 | |
85 | assert_se(test_password_one(hashed, i) == true); | |
86 | assert_se(test_password_one(i, hashed) <= 0); /* We get an error for non-utf8 */ | |
87 | assert_se(test_password_one(hashed, "foobar") == false); | |
88 | assert_se(test_password_many(STRV_MAKE(hashed), i) == true); | |
89 | assert_se(test_password_many(STRV_MAKE(hashed), "foobar") == false); | |
90 | assert_se(test_password_many(STRV_MAKE(hashed, hashed, hashed), "foobar") == false); | |
91 | assert_se(test_password_many(STRV_MAKE("$y$j9T$dlCXwkX0GC5L6B8Gf.4PN/$VCyEH", | |
92 | hashed, | |
93 | "$y$j9T$SAayASazWZIQeJd9AS02m/$"), | |
94 | i) == true); | |
35e22827 ZJS |
95 | assert_se(test_password_many(STRV_MAKE("$W$j9T$dlCXwkX0GC5L6B8Gf.4PN/$VCyEH", /* no such method exists... */ |
96 | hashed, | |
97 | "$y$j9T$SAayASazWZIQeJd9AS02m/$"), | |
98 | i) == true); | |
6016b4b0 ZJS |
99 | assert_se(test_password_many(STRV_MAKE("$y$j9T$dlCXwkX0GC5L6B8Gf.4PN/$VCyEH", |
100 | hashed, | |
101 | "$y$j9T$SAayASazWZIQeJd9AS02m/$"), | |
102 | "") == false); | |
35e22827 ZJS |
103 | assert_se(test_password_many(STRV_MAKE("$W$j9T$dlCXwkX0GC5L6B8Gf.4PN/$VCyEH", /* no such method exists... */ |
104 | hashed, | |
105 | "$y$j9T$SAayASazWZIQeJd9AS02m/$"), | |
106 | "") == false); | |
a937ce2d ZJS |
107 | } |
108 | } | |
109 | ||
110 | int main(int argc, char *argv[]) { | |
111 | test_setup_logging(LOG_DEBUG); | |
112 | ||
bd99297b ZJS |
113 | #if defined(__powerpc__) && !defined(XCRYPT_VERSION_MAJOR) |
114 | return log_tests_skipped("crypt_r() causes a buffer overflow on ppc64el, see https://github.com/systemd/systemd/pull/16981#issuecomment-691203787"); | |
115 | #endif | |
116 | ||
7ff9d99e ZJS |
117 | test_crypt_preferred_method(); |
118 | test_make_salt(); | |
119 | ||
5d3fe6f7 ZJS |
120 | if (!test_hash_password()) |
121 | return log_tests_skipped("crypt doesn't support yescrypt or sha512crypt"); | |
122 | ||
a937ce2d ZJS |
123 | test_hash_password_full(); |
124 | ||
125 | return 0; | |
126 | } |