]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/libcrypt-util.c
Merge pull request #16112 from poettering/nss-systemd-block-fix
[thirdparty/systemd.git] / src / shared / libcrypt-util.c
CommitLineData
42f3b2f9
LP
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno.h>
4#include <stdlib.h>
5
6#include "alloc-util.h"
7#include "libcrypt-util.h"
8#include "log.h"
9#include "macro.h"
10#include "missing_stdlib.h"
11#include "random-util.h"
12#include "string-util.h"
13#include "strv.h"
14
15int make_salt(char **ret) {
16
17#ifdef XCRYPT_VERSION_MAJOR
18 const char *e;
19 char *salt;
20
21 /* If we have libxcrypt we default to the "preferred method" (i.e. usually yescrypt), and generate it
22 * with crypt_gensalt_ra(). */
23
24 e = secure_getenv("SYSTEMD_CRYPT_PREFIX");
25 if (!e)
26 e = crypt_preferred_method();
27
28 log_debug("Generating salt for hash prefix: %s", e);
29
30 salt = crypt_gensalt_ra(e, 0, NULL, 0);
31 if (!salt)
32 return -errno;
33
34 *ret = salt;
35 return 0;
36#else
37 /* If libxcrypt is not used, we use SHA512 and generate the salt on our own since crypt_gensalt_ra()
38 * is not available. */
39
40 static const char table[] =
41 "abcdefghijklmnopqrstuvwxyz"
42 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
43 "0123456789"
44 "./";
45
46 uint8_t raw[16];
47 char *salt, *j;
48 size_t i;
49 int r;
50
51 /* This is a bit like crypt_gensalt_ra(), but doesn't require libcrypt, and doesn't do anything but
52 * SHA512, i.e. is legacy-free and minimizes our deps. */
53
54 assert_cc(sizeof(table) == 64U + 1U);
55
56 /* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */
57 r = genuine_random_bytes(raw, sizeof(raw), RANDOM_BLOCK);
58 if (r < 0)
59 return r;
60
61 salt = new(char, 3+sizeof(raw)+1+1);
62 if (!salt)
63 return -ENOMEM;
64
65 /* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */
66 j = stpcpy(salt, "$6$");
67 for (i = 0; i < sizeof(raw); i++)
68 j[i] = table[raw[i] & 63];
69 j[i++] = '$';
70 j[i] = 0;
71
72 *ret = salt;
73 return 0;
74#endif
75}
64aa2622
LP
76
77bool hashed_password_valid(const char *s) {
78
79 /* Returns true if the specified string is a 'valid' hashed UNIX password, i.e. if starts with '$' or
80 * with '!$' (the latter being a valid, yet locked password). */
81
82 if (isempty(s))
83 return false;
84
85 return STARTSWITH_SET(s, "$", "!$");
86}