]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/libcrypt-util.c
aa41cd4458e31421ac38e693bb55c05d56764553
[thirdparty/systemd.git] / src / shared / libcrypt-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #if HAVE_CRYPT_H
4 /* libxcrypt is a replacement for glibc's libcrypt, and libcrypt might be
5 * removed from glibc at some point. As part of the removal, defines for
6 * crypt(3) are dropped from unistd.h, and we must include crypt.h instead.
7 *
8 * Newer versions of glibc (v2.0+) already ship crypt.h with a definition
9 * of crypt(3) as well, so we simply include it if it is present. MariaDB,
10 * MySQL, PostgreSQL, Perl and some other wide-spread packages do it the
11 * same way since ages without any problems.
12 */
13 # include <crypt.h>
14 #else
15 # include <unistd.h>
16 #endif
17
18 #include <stdlib.h>
19
20 #include "alloc-util.h"
21 #include "errno-util.h"
22 #include "libcrypt-util.h"
23 #include "log.h"
24 #include "random-util.h"
25 #include "string-util.h"
26 #include "strv.h"
27
28 int make_salt(char **ret) {
29
30 #if HAVE_CRYPT_GENSALT_RA
31 const char *e;
32 char *salt;
33
34 /* If we have crypt_gensalt_ra() we default to the "preferred method" (i.e. usually yescrypt).
35 * crypt_gensalt_ra() is usually provided by libxcrypt. */
36
37 e = secure_getenv("SYSTEMD_CRYPT_PREFIX");
38 if (!e)
39 #if HAVE_CRYPT_PREFERRED_METHOD
40 e = crypt_preferred_method();
41 #else
42 e = "$6$";
43 #endif
44
45 log_debug("Generating salt for hash prefix: %s", e);
46
47 salt = crypt_gensalt_ra(e, 0, NULL, 0);
48 if (!salt)
49 return -errno;
50
51 *ret = salt;
52 return 0;
53 #else
54 /* If crypt_gensalt_ra() is not available, we use SHA512 and generate the salt on our own. */
55
56 static const char table[] =
57 "abcdefghijklmnopqrstuvwxyz"
58 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
59 "0123456789"
60 "./";
61
62 uint8_t raw[16];
63 char *salt, *j;
64 size_t i;
65 int r;
66
67 /* This is a bit like crypt_gensalt_ra(), but doesn't require libcrypt, and doesn't do anything but
68 * SHA512, i.e. is legacy-free and minimizes our deps. */
69
70 assert_cc(sizeof(table) == 64U + 1U);
71
72 log_debug("Generating fallback salt for hash prefix: $6$");
73
74 /* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */
75 r = crypto_random_bytes(raw, sizeof(raw));
76 if (r < 0)
77 return r;
78
79 salt = new(char, 3+sizeof(raw)+1+1);
80 if (!salt)
81 return -ENOMEM;
82
83 /* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */
84 j = stpcpy(salt, "$6$");
85 for (i = 0; i < sizeof(raw); i++)
86 j[i] = table[raw[i] & 63];
87 j[i++] = '$';
88 j[i] = 0;
89
90 *ret = salt;
91 return 0;
92 #endif
93 }
94
95 #if HAVE_CRYPT_RA
96 # define CRYPT_RA_NAME "crypt_ra"
97 #else
98 # define CRYPT_RA_NAME "crypt_r"
99
100 /* Provide a poor man's fallback that uses a fixed size buffer. */
101
102 static char* systemd_crypt_ra(const char *phrase, const char *setting, void **data, int *size) {
103 assert(data);
104 assert(size);
105
106 /* We allocate the buffer because crypt(3) says: struct crypt_data may be quite large (32kB in this
107 * implementation of libcrypt; over 128kB in some other implementations). This is large enough that
108 * it may be unwise to allocate it on the stack. */
109
110 if (!*data) {
111 *data = new0(struct crypt_data, 1);
112 if (!*data) {
113 errno = ENOMEM;
114 return NULL;
115 }
116
117 *size = (int) (sizeof(struct crypt_data));
118 }
119
120 char *t = crypt_r(phrase, setting, *data);
121 if (!t)
122 return NULL;
123
124 /* crypt_r may return a pointer to an invalid hashed password on error. Our callers expect NULL on
125 * error, so let's just return that. */
126 if (t[0] == '*')
127 return NULL;
128
129 return t;
130 }
131
132 #define crypt_ra systemd_crypt_ra
133
134 #endif
135
136 int hash_password_full(const char *password, void **cd_data, int *cd_size, char **ret) {
137 _cleanup_free_ char *salt = NULL;
138 _cleanup_(erase_and_freep) void *_cd_data = NULL;
139 const char *p;
140 int r, _cd_size = 0;
141
142 assert(!!cd_data == !!cd_size);
143
144 r = make_salt(&salt);
145 if (r < 0)
146 return log_debug_errno(r, "Failed to generate salt: %m");
147
148 errno = 0;
149 p = crypt_ra(password, salt, cd_data ?: &_cd_data, cd_size ?: &_cd_size);
150 if (!p)
151 return log_debug_errno(errno_or_else(SYNTHETIC_ERRNO(EINVAL)),
152 CRYPT_RA_NAME "() failed: %m");
153
154 return strdup_to(ret, p);
155 }
156
157 bool looks_like_hashed_password(const char *s) {
158 /* Returns false if the specified string is certainly not a hashed UNIX password. crypt(5) lists
159 * various hashing methods. We only reject (return false) strings which are documented to have
160 * different meanings.
161 *
162 * In particular, we allow locked passwords, i.e. strings starting with "!", including just "!",
163 * i.e. the locked empty password. See also fc58c0c7bf7e4f525b916e3e5be0de2307fef04e.
164 */
165 if (!s)
166 return false;
167
168 s += strspn(s, "!"); /* Skip (possibly duplicated) locking prefix */
169
170 return !STR_IN_SET(s, "x", "*");
171 }
172
173 int test_password_one(const char *hashed_password, const char *password) {
174 _cleanup_(erase_and_freep) void *cd_data = NULL;
175 int cd_size = 0;
176 const char *k;
177
178 errno = 0;
179 k = crypt_ra(password, hashed_password, &cd_data, &cd_size);
180 if (!k) {
181 if (errno == ENOMEM)
182 return -ENOMEM;
183 /* Unknown or unavailable hashing method or string too short */
184 return 0;
185 }
186
187 return streq(k, hashed_password);
188 }
189
190 int test_password_many(char **hashed_password, const char *password) {
191 int r;
192
193 STRV_FOREACH(hpw, hashed_password) {
194 r = test_password_one(*hpw, password);
195 if (r < 0)
196 return r;
197 if (r > 0)
198 return true;
199 }
200
201 return false;
202 }