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