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