1 /* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "array.h"
5 #include "hash.h"
6 #include "base64.h"
7 #include "hex-binary.h"
8 #include "md4.h"
9 #include "md5.h"
10 #include "hmac.h"
11 #include "hmac-cram-md5.h"
12 #include "mycrypt.h"
13 #include "randgen.h"
14 #include "sha1.h"
15 #include "sha2.h"
16 #include "otp.h"
17 #include "str.h"
18 #include "password-scheme.h"
19
20 static const char salt_chars[] =
21 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
22
23 static HASH_TABLE(const char*, const struct password_scheme *) password_schemes;
24
25 static const struct password_scheme *
password_scheme_lookup_name(const char * name)26 password_scheme_lookup_name(const char *name)
27 {
28 return hash_table_lookup(password_schemes, name);
29 }
30
31 /* Lookup scheme and encoding by given name. The encoding is taken from
32 ".base64", ".b64" or ".hex" suffix if it exists, otherwise the default
33 encoding is used. */
34 static const struct password_scheme *
password_scheme_lookup(const char * name,enum password_encoding * encoding_r)35 password_scheme_lookup(const char *name, enum password_encoding *encoding_r)
36 {
37 const struct password_scheme *scheme;
38 const char *encoding = NULL;
39
40 *encoding_r = PW_ENCODING_NONE;
41 if ((encoding = strchr(name, '.')) != NULL) {
42 name = t_strdup_until(name, encoding);
43 encoding++;
44 }
45
46 scheme = password_scheme_lookup_name(name);
47 if (scheme == NULL)
48 return NULL;
49
50 if (encoding == NULL)
51 *encoding_r = scheme->default_encoding;
52 else if (strcasecmp(encoding, "b64") == 0 ||
53 strcasecmp(encoding, "base64") == 0)
54 *encoding_r = PW_ENCODING_BASE64;
55 else if (strcasecmp(encoding, "hex") == 0)
56 *encoding_r = PW_ENCODING_HEX;
57 else {
58 /* unknown encoding. treat as invalid scheme. */
59 return NULL;
60 }
61 return scheme;
62 }
63
password_verify(const char * plaintext,const struct password_generate_params * params,const char * scheme,const unsigned char * raw_password,size_t size,const char ** error_r)64 int password_verify(const char *plaintext,
65 const struct password_generate_params *params,
66 const char *scheme, const unsigned char *raw_password,
67 size_t size, const char **error_r)
68 {
69 const struct password_scheme *s;
70 enum password_encoding encoding;
71 const unsigned char *generated;
72 size_t generated_size;
73 int ret;
74
75 s = password_scheme_lookup(scheme, &encoding);
76 if (s == NULL) {
77 *error_r = "Unknown password scheme";
78 return -1;
79 }
80
81 if (s->password_verify != NULL) {
82 ret = s->password_verify(plaintext, params, raw_password, size,
83 error_r);
84 } else {
85 /* generic verification handler: generate the password and
86 compare it to the one in database */
87 s->password_generate(plaintext, params,
88 &generated, &generated_size);
89 ret = size != generated_size ? 0 :
90 mem_equals_timing_safe(generated, raw_password, size) ? 1 : 0;
91 }
92
93 if (ret == 0)
94 *error_r = AUTH_LOG_MSG_PASSWORD_MISMATCH;
95 return ret;
96 }
97
password_get_scheme(const char ** password)98 const char *password_get_scheme(const char **password)
99 {
100 const char *p, *scheme;
101
102 if (*password == NULL)
103 return NULL;
104
105 if (str_begins(*password, "$1$")) {
106 /* $1$<salt>$<password>[$<ignored>] */
107 p = strchr(*password + 3, '$');
108 if (p != NULL) {
109 /* stop at next '$' after password */
110 p = strchr(p+1, '$');
111 if (p != NULL)
112 *password = t_strdup_until(*password, p);
113 return "MD5-CRYPT";
114 }
115 }
116
117 if (**password != '{')
118 return NULL;
119
120 p = strchr(*password, '}');
121 if (p == NULL)
122 return NULL;
123
124 scheme = t_strdup_until(*password + 1, p);
125 *password = p + 1;
126 return scheme;
127 }
128
password_decode(const char * password,const char * scheme,const unsigned char ** raw_password_r,size_t * size_r,const char ** error_r)129 int password_decode(const char *password, const char *scheme,
130 const unsigned char **raw_password_r, size_t *size_r,
131 const char **error_r)
132 {
133 const struct password_scheme *s;
134 enum password_encoding encoding;
135 buffer_t *buf;
136 size_t len;
137 bool guessed_encoding;
138
139 *error_r = NULL;
140
141 s = password_scheme_lookup(scheme, &encoding);
142 if (s == NULL) {
143 *error_r = "Unknown scheme";
144 return 0;
145 }
146
147 len = strlen(password);
148 if (encoding != PW_ENCODING_NONE && s->raw_password_len != 0 &&
149 strchr(scheme, '.') == NULL) {
150 /* encoding not specified. we can guess quite well between
151 base64 and hex encodings. the only problem is distinguishing
152 2 character strings, but there shouldn't be any that short
153 raw_password_lens. */
154 encoding = len == s->raw_password_len * 2 ?
155 PW_ENCODING_HEX : PW_ENCODING_BASE64;
156 guessed_encoding = TRUE;
157 } else {
158 guessed_encoding = FALSE;
159 }
160
161 switch (encoding) {
162 case PW_ENCODING_NONE:
163 *raw_password_r = (const unsigned char *)password;
164 *size_r = len;
165 break;
166 case PW_ENCODING_HEX:
167 buf = t_buffer_create(len / 2 + 1);
168 if (hex_to_binary(password, buf) == 0) {
169 *raw_password_r = buf->data;
170 *size_r = buf->used;
171 break;
172 }
173 if (!guessed_encoding) {
174 *error_r = "Input isn't valid HEX encoded data";
175 return -1;
176 }
177 /* check if it's base64-encoded after all. some input lengths
178 produce matching hex and base64 encoded lengths. */
179 /* fall through */
180 case PW_ENCODING_BASE64:
181 buf = t_buffer_create(MAX_BASE64_DECODED_SIZE(len));
182 if (base64_decode(password, len, NULL, buf) < 0) {
183 *error_r = "Input isn't valid base64 encoded data";
184 return -1;
185 }
186
187 *raw_password_r = buf->data;
188 *size_r = buf->used;
189 break;
190 }
191 if (s->raw_password_len != *size_r && s->raw_password_len != 0) {
192 /* password has invalid length */
193 *error_r = t_strdup_printf(
194 "Input length isn't valid (%u instead of %u)",
195 (unsigned int)*size_r, s->raw_password_len);
196 return -1;
197 }
198 return 1;
199 }
200
password_generate(const char * plaintext,const struct password_generate_params * params,const char * scheme,const unsigned char ** raw_password_r,size_t * size_r)201 bool password_generate(const char *plaintext, const struct password_generate_params *params,
202 const char *scheme,
203 const unsigned char **raw_password_r, size_t *size_r)
204 {
205 const struct password_scheme *s;
206 enum password_encoding encoding;
207
208 s = password_scheme_lookup(scheme, &encoding);
209 if (s == NULL)
210 return FALSE;
211
212 s->password_generate(plaintext, params, raw_password_r, size_r);
213 return TRUE;
214 }
215
password_generate_encoded(const char * plaintext,const struct password_generate_params * params,const char * scheme,const char ** password_r)216 bool password_generate_encoded(const char *plaintext, const struct password_generate_params *params,
217 const char *scheme, const char **password_r)
218 {
219 const struct password_scheme *s;
220 const unsigned char *raw_password;
221 enum password_encoding encoding;
222 string_t *str;
223 size_t size;
224
225 s = password_scheme_lookup(scheme, &encoding);
226 if (s == NULL)
227 return FALSE;
228
229 s->password_generate(plaintext, params, &raw_password, &size);
230 switch (encoding) {
231 case PW_ENCODING_NONE:
232 *password_r = t_strndup(raw_password, size);
233 break;
234 case PW_ENCODING_BASE64:
235 str = t_str_new(MAX_BASE64_ENCODED_SIZE(size) + 1);
236 base64_encode(raw_password, size, str);
237 *password_r = str_c(str);
238 break;
239 case PW_ENCODING_HEX:
240 *password_r = binary_to_hex(raw_password, size);
241 break;
242 }
243 return TRUE;
244 }
245
password_generate_salt(size_t len)246 const char *password_generate_salt(size_t len)
247 {
248 char *salt;
249 salt = t_malloc_no0(len + 1);
250 for (size_t i = 0; i < len; i++)
251 salt[i] = salt_chars[i_rand_limit(sizeof(salt_chars) - 1)];
252 salt[len] = '\0';
253 return salt;
254 }
255
password_scheme_is_alias(const char * scheme1,const char * scheme2)256 bool password_scheme_is_alias(const char *scheme1, const char *scheme2)
257 {
258 const struct password_scheme *s1 = NULL, *s2 = NULL;
259
260 if (*scheme1 == '\0' || *scheme2 == '\0')
261 return FALSE;
262
263 scheme1 = t_strcut(scheme1, '.');
264 scheme2 = t_strcut(scheme2, '.');
265
266 if (strcasecmp(scheme1, scheme2) == 0)
267 return TRUE;
268
269 s1 = hash_table_lookup(password_schemes, scheme1);
270 s2 = hash_table_lookup(password_schemes, scheme2);
271
272 /* if they've the same generate function, they're equivalent */
273 return s1 != NULL && s2 != NULL &&
274 s1->password_generate == s2->password_generate;
275 }
276
277 const char *
password_scheme_detect(const char * plain_password,const char * crypted_password,const struct password_generate_params * params)278 password_scheme_detect(const char *plain_password, const char *crypted_password,
279 const struct password_generate_params *params)
280 {
281 struct hash_iterate_context *ctx;
282 const char *key;
283 const struct password_scheme *scheme;
284 const unsigned char *raw_password;
285 size_t raw_password_size;
286 const char *error;
287
288 ctx = hash_table_iterate_init(password_schemes);
289 while (hash_table_iterate(ctx, password_schemes, &key, &scheme)) {
290 if (password_decode(crypted_password, scheme->name,
291 &raw_password, &raw_password_size,
292 &error) <= 0)
293 continue;
294
295 if (password_verify(plain_password, params, scheme->name,
296 raw_password, raw_password_size,
297 &error) > 0)
298 break;
299 key = NULL;
300 }
301 hash_table_iterate_deinit(&ctx);
302 return key;
303 }
304
crypt_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r)305 int crypt_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
306 const unsigned char *raw_password, size_t size,
307 const char **error_r)
308 {
309 const char *password, *crypted;
310
311 if (size > 4 && raw_password[0] == '$' && raw_password[1] == '2' &&
312 raw_password[3] == '$')
313 return password_verify(plaintext, params, "BLF-CRYPT",
314 raw_password, size, error_r);
315
316 if (size == 0) {
317 /* the default mycrypt() handler would return match */
318 return 0;
319 }
320
321 password = t_strndup(raw_password, size);
322 crypted = mycrypt(plaintext, password);
323 if (crypted == NULL) {
324 /* really shouldn't happen unless the system is broken */
325 *error_r = t_strdup_printf("crypt() failed: %m");
326 return -1;
327 }
328
329 return str_equals_timing_almost_safe(crypted, password) ? 1 : 0;
330 }
331
332 static int
md5_verify(const char * plaintext,const struct password_generate_params * params,const unsigned char * raw_password,size_t size,const char ** error_r)333 md5_verify(const char *plaintext, const struct password_generate_params *params,
334 const unsigned char *raw_password, size_t size, const char **error_r)
335 {
336 const char *password, *str, *error;
337 const unsigned char *md5_password;
338 size_t md5_size;
339
340 password = t_strndup(raw_password, size);
341 if (str_begins(password, "$1$")) {
342 /* MD5-CRYPT */
343 str = password_generate_md5_crypt(plaintext, password);
344 return str_equals_timing_almost_safe(str, password) ? 1 : 0;
345 } else if (password_decode(password, "PLAIN-MD5",
346 &md5_password, &md5_size, &error) <= 0) {
347 *error_r = "Not a valid MD5-CRYPT or PLAIN-MD5 password";
348 return -1;
349 } else {
350 return password_verify(plaintext, params, "PLAIN-MD5",
351 md5_password, md5_size, error_r);
352 }
353 }
354
355 static int
md5_crypt_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r ATTR_UNUSED)356 md5_crypt_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
357 const unsigned char *raw_password, size_t size,
358 const char **error_r ATTR_UNUSED)
359 {
360 const char *password, *str;
361
362 password = t_strndup(raw_password, size);
363 str = password_generate_md5_crypt(plaintext, password);
364 return str_equals_timing_almost_safe(str, password) ? 1 : 0;
365 }
366
367 static void
md5_crypt_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)368 md5_crypt_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
369 const unsigned char **raw_password_r, size_t *size_r)
370 {
371 const char *password;
372 const char *salt;
373
374 salt = password_generate_salt(8);
375
376 password = password_generate_md5_crypt(plaintext, salt);
377 *raw_password_r = (const unsigned char *)password;
378 *size_r = strlen(password);
379 }
380
381 static void
sha1_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)382 sha1_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
383 const unsigned char **raw_password_r, size_t *size_r)
384 {
385 unsigned char *digest;
386
387 digest = t_malloc_no0(SHA1_RESULTLEN);
388 sha1_get_digest(plaintext, strlen(plaintext), digest);
389
390 *raw_password_r = digest;
391 *size_r = SHA1_RESULTLEN;
392 }
393
394 static void
sha256_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)395 sha256_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
396 const unsigned char **raw_password_r, size_t *size_r)
397 {
398 unsigned char *digest;
399
400 digest = t_malloc_no0(SHA256_RESULTLEN);
401 sha256_get_digest(plaintext, strlen(plaintext), digest);
402
403 *raw_password_r = digest;
404 *size_r = SHA256_RESULTLEN;
405 }
406
407 static void
sha512_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)408 sha512_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
409 const unsigned char **raw_password_r, size_t *size_r)
410 {
411 unsigned char *digest;
412
413 digest = t_malloc_no0(SHA512_RESULTLEN);
414 sha512_get_digest(plaintext, strlen(plaintext), digest);
415
416 *raw_password_r = digest;
417 *size_r = SHA512_RESULTLEN;
418 }
419
420 static void
ssha_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)421 ssha_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
422 const unsigned char **raw_password_r, size_t *size_r)
423 {
424 #define SSHA_SALT_LEN 4
425 unsigned char *digest, *salt;
426 struct sha1_ctxt ctx;
427
428 digest = t_malloc_no0(SHA1_RESULTLEN + SSHA_SALT_LEN);
429 salt = digest + SHA1_RESULTLEN;
430 random_fill(salt, SSHA_SALT_LEN);
431
432 sha1_init(&ctx);
433 sha1_loop(&ctx, plaintext, strlen(plaintext));
434 sha1_loop(&ctx, salt, SSHA_SALT_LEN);
435 sha1_result(&ctx, digest);
436
437 *raw_password_r = digest;
438 *size_r = SHA1_RESULTLEN + SSHA_SALT_LEN;
439 }
440
ssha_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r)441 static int ssha_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
442 const unsigned char *raw_password, size_t size,
443 const char **error_r)
444 {
445 unsigned char sha1_digest[SHA1_RESULTLEN];
446 struct sha1_ctxt ctx;
447
448 /* format: <SHA1 hash><salt> */
449 if (size <= SHA1_RESULTLEN) {
450 *error_r = "SSHA password is too short";
451 return -1;
452 }
453
454 sha1_init(&ctx);
455 sha1_loop(&ctx, plaintext, strlen(plaintext));
456 sha1_loop(&ctx, raw_password + SHA1_RESULTLEN, size - SHA1_RESULTLEN);
457 sha1_result(&ctx, sha1_digest);
458 return mem_equals_timing_safe(sha1_digest, raw_password, SHA1_RESULTLEN) ? 1 : 0;
459 }
460
461 static void
ssha256_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)462 ssha256_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
463 const unsigned char **raw_password_r, size_t *size_r)
464 {
465 #define SSHA256_SALT_LEN 4
466 unsigned char *digest, *salt;
467 struct sha256_ctx ctx;
468
469 digest = t_malloc_no0(SHA256_RESULTLEN + SSHA256_SALT_LEN);
470 salt = digest + SHA256_RESULTLEN;
471 random_fill(salt, SSHA256_SALT_LEN);
472
473 sha256_init(&ctx);
474 sha256_loop(&ctx, plaintext, strlen(plaintext));
475 sha256_loop(&ctx, salt, SSHA256_SALT_LEN);
476 sha256_result(&ctx, digest);
477
478 *raw_password_r = digest;
479 *size_r = SHA256_RESULTLEN + SSHA256_SALT_LEN;
480 }
481
ssha256_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r)482 static int ssha256_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
483 const unsigned char *raw_password, size_t size,
484 const char **error_r)
485 {
486 unsigned char sha256_digest[SHA256_RESULTLEN];
487 struct sha256_ctx ctx;
488
489 /* format: <SHA256 hash><salt> */
490 if (size <= SHA256_RESULTLEN) {
491 *error_r = "SSHA256 password is too short";
492 return -1;
493 }
494
495 sha256_init(&ctx);
496 sha256_loop(&ctx, plaintext, strlen(plaintext));
497 sha256_loop(&ctx, raw_password + SHA256_RESULTLEN,
498 size - SHA256_RESULTLEN);
499 sha256_result(&ctx, sha256_digest);
500 return mem_equals_timing_safe(sha256_digest, raw_password,
501 SHA256_RESULTLEN) ? 1 : 0;
502 }
503
504 static void
ssha512_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)505 ssha512_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
506 const unsigned char **raw_password_r, size_t *size_r)
507 {
508 #define SSHA512_SALT_LEN 4
509 unsigned char *digest, *salt;
510 struct sha512_ctx ctx;
511
512 digest = t_malloc_no0(SHA512_RESULTLEN + SSHA512_SALT_LEN);
513 salt = digest + SHA512_RESULTLEN;
514 random_fill(salt, SSHA512_SALT_LEN);
515
516 sha512_init(&ctx);
517 sha512_loop(&ctx, plaintext, strlen(plaintext));
518 sha512_loop(&ctx, salt, SSHA512_SALT_LEN);
519 sha512_result(&ctx, digest);
520
521 *raw_password_r = digest;
522 *size_r = SHA512_RESULTLEN + SSHA512_SALT_LEN;
523 }
524
ssha512_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r)525 static int ssha512_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
526 const unsigned char *raw_password, size_t size,
527 const char **error_r)
528 {
529 unsigned char sha512_digest[SHA512_RESULTLEN];
530 struct sha512_ctx ctx;
531
532 /* format: <SHA512 hash><salt> */
533 if (size <= SHA512_RESULTLEN) {
534 *error_r = "SSHA512 password is too short";
535 return -1;
536 }
537
538 sha512_init(&ctx);
539 sha512_loop(&ctx, plaintext, strlen(plaintext));
540 sha512_loop(&ctx, raw_password + SHA512_RESULTLEN,
541 size - SHA512_RESULTLEN);
542 sha512_result(&ctx, sha512_digest);
543 return mem_equals_timing_safe(sha512_digest, raw_password,
544 SHA512_RESULTLEN) ? 1 : 0;
545 }
546
547 static void
smd5_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)548 smd5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
549 const unsigned char **raw_password_r, size_t *size_r)
550 {
551 #define SMD5_SALT_LEN 4
552 unsigned char *digest, *salt;
553 struct md5_context ctx;
554
555 digest = t_malloc_no0(MD5_RESULTLEN + SMD5_SALT_LEN);
556 salt = digest + MD5_RESULTLEN;
557 random_fill(salt, SMD5_SALT_LEN);
558
559 md5_init(&ctx);
560 md5_update(&ctx, plaintext, strlen(plaintext));
561 md5_update(&ctx, salt, SMD5_SALT_LEN);
562 md5_final(&ctx, digest);
563
564 *raw_password_r = digest;
565 *size_r = MD5_RESULTLEN + SMD5_SALT_LEN;
566 }
567
smd5_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r)568 static int smd5_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
569 const unsigned char *raw_password, size_t size,
570 const char **error_r)
571 {
572 unsigned char md5_digest[MD5_RESULTLEN];
573 struct md5_context ctx;
574
575 /* format: <MD5 hash><salt> */
576 if (size <= MD5_RESULTLEN) {
577 *error_r = "SMD5 password is too short";
578 return -1;
579 }
580
581 md5_init(&ctx);
582 md5_update(&ctx, plaintext, strlen(plaintext));
583 md5_update(&ctx, raw_password + MD5_RESULTLEN, size - MD5_RESULTLEN);
584 md5_final(&ctx, md5_digest);
585 return mem_equals_timing_safe(md5_digest, raw_password, MD5_RESULTLEN) ? 1 : 0;
586 }
587
588 static void
plain_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)589 plain_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
590 const unsigned char **raw_password_r, size_t *size_r)
591 {
592 *raw_password_r = (const unsigned char *)plaintext,
593 *size_r = strlen(plaintext);
594 }
595
596 static int
plain_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r ATTR_UNUSED)597 plain_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
598 const unsigned char *raw_password, size_t size,
599 const char **error_r ATTR_UNUSED)
600 {
601 size_t plaintext_len = strlen(plaintext);
602
603 if (plaintext_len != size)
604 return 0;
605 return mem_equals_timing_safe(plaintext, raw_password, size) ? 1 : 0;
606 }
607
608 static int
plain_trunc_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r)609 plain_trunc_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
610 const unsigned char *raw_password, size_t size,
611 const char **error_r)
612 {
613 size_t i, plaintext_len, trunc_len = 0;
614
615 /* format: <length>-<password> */
616 for (i = 0; i < size; i++) {
617 if (raw_password[i] >= '0' && raw_password[i] <= '9')
618 trunc_len = trunc_len*10 + raw_password[i]-'0';
619 else
620 break;
621 }
622 if (i == size || raw_password[i] != '-') {
623 *error_r = "PLAIN-TRUNC missing length: prefix";
624 return -1;
625 }
626 i++;
627
628 plaintext_len = strlen(plaintext);
629 if (size-i == trunc_len && plaintext_len >= trunc_len) {
630 /* possibly truncated password. allow the given password as
631 long as the prefix matches. */
632 return mem_equals_timing_safe(raw_password+i, plaintext, trunc_len) ? 1 : 0;
633 }
634 return plaintext_len == size-i &&
635 mem_equals_timing_safe(raw_password+i, plaintext, plaintext_len) ? 1 : 0;
636 }
637
638 static void
cram_md5_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)639 cram_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
640 const unsigned char **raw_password_r, size_t *size_r)
641 {
642 struct hmac_context ctx;
643 unsigned char *context_digest;
644
645 context_digest = t_malloc_no0(CRAM_MD5_CONTEXTLEN);
646 hmac_init(&ctx, (const unsigned char *)plaintext,
647 strlen(plaintext), &hash_method_md5);
648 hmac_md5_get_cram_context(&ctx, context_digest);
649
650 *raw_password_r = context_digest;
651 *size_r = CRAM_MD5_CONTEXTLEN;
652 }
653
654 static void
digest_md5_generate(const char * plaintext,const struct password_generate_params * params,const unsigned char ** raw_password_r,size_t * size_r)655 digest_md5_generate(const char *plaintext, const struct password_generate_params *params,
656 const unsigned char **raw_password_r, size_t *size_r)
657 {
658 const char *realm, *str, *user;
659 unsigned char *digest;
660
661 if (params->user == NULL)
662 i_fatal("digest_md5_generate(): username not given");
663
664 user = params->user;
665
666
667 /* assume user@realm format for username. If user@domain is wanted
668 in the username, allow also user@domain@realm. */
669 realm = strrchr(user, '@');
670 if (realm != NULL) {
671 user = t_strdup_until(user, realm);
672 realm++;
673 } else {
674 realm = "";
675 }
676
677 /* user:realm:passwd */
678 digest = t_malloc_no0(MD5_RESULTLEN);
679 str = t_strdup_printf("%s:%s:%s", user, realm, plaintext);
680 md5_get_digest(str, strlen(str), digest);
681
682 *raw_password_r = digest;
683 *size_r = MD5_RESULTLEN;
684 }
685
686 static void
plain_md4_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)687 plain_md4_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
688 const unsigned char **raw_password_r, size_t *size_r)
689 {
690 unsigned char *digest;
691
692 digest = t_malloc_no0(MD4_RESULTLEN);
693 md4_get_digest(plaintext, strlen(plaintext), digest);
694
695 *raw_password_r = digest;
696 *size_r = MD4_RESULTLEN;
697 }
698
699 static void
plain_md5_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)700 plain_md5_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
701 const unsigned char **raw_password_r, size_t *size_r)
702 {
703 unsigned char *digest;
704
705 digest = t_malloc_no0(MD5_RESULTLEN);
706 md5_get_digest(plaintext, strlen(plaintext), digest);
707
708 *raw_password_r = digest;
709 *size_r = MD5_RESULTLEN;
710 }
711
otp_verify(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char * raw_password,size_t size,const char ** error_r)712 static int otp_verify(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
713 const unsigned char *raw_password, size_t size,
714 const char **error_r)
715 {
716 const char *password, *generated;
717
718 password = t_strndup(raw_password, size);
719 if (password_generate_otp(plaintext, password, UINT_MAX, &generated) < 0) {
720 *error_r = "Invalid OTP data in passdb";
721 return -1;
722 }
723
724 return strcasecmp(password, generated) == 0 ? 1 : 0;
725 }
726
727 static void
otp_generate(const char * plaintext,const struct password_generate_params * params ATTR_UNUSED,const unsigned char ** raw_password_r,size_t * size_r)728 otp_generate(const char *plaintext, const struct password_generate_params *params ATTR_UNUSED,
729 const unsigned char **raw_password_r, size_t *size_r)
730 {
731 const char *password;
732
733 if (password_generate_otp(plaintext, NULL, OTP_HASH_SHA1, &password) < 0)
734 i_unreached();
735 *raw_password_r = (const unsigned char *)password;
736 *size_r = strlen(password);
737 }
738
739 static const struct password_scheme builtin_schemes[] = {
740 { "MD5", PW_ENCODING_NONE, 0, md5_verify, md5_crypt_generate },
741 { "MD5-CRYPT", PW_ENCODING_NONE, 0,
742 md5_crypt_verify, md5_crypt_generate },
743 { "SHA", PW_ENCODING_BASE64, SHA1_RESULTLEN, NULL, sha1_generate },
744 { "SHA1", PW_ENCODING_BASE64, SHA1_RESULTLEN, NULL, sha1_generate },
745 { "SHA256", PW_ENCODING_BASE64, SHA256_RESULTLEN,
746 NULL, sha256_generate },
747 { "SHA512", PW_ENCODING_BASE64, SHA512_RESULTLEN,
748 NULL, sha512_generate },
749 { "SMD5", PW_ENCODING_BASE64, 0, smd5_verify, smd5_generate },
750 { "SSHA", PW_ENCODING_BASE64, 0, ssha_verify, ssha_generate },
751 { "SSHA256", PW_ENCODING_BASE64, 0, ssha256_verify, ssha256_generate },
752 { "SSHA512", PW_ENCODING_BASE64, 0, ssha512_verify, ssha512_generate },
753 { "PLAIN", PW_ENCODING_NONE, 0, plain_verify, plain_generate },
754 { "CLEAR", PW_ENCODING_NONE, 0, plain_verify, plain_generate },
755 { "CLEARTEXT", PW_ENCODING_NONE, 0, plain_verify, plain_generate },
756 { "PLAIN-TRUNC", PW_ENCODING_NONE, 0, plain_trunc_verify, plain_generate },
757 { "CRAM-MD5", PW_ENCODING_HEX, CRAM_MD5_CONTEXTLEN,
758 NULL, cram_md5_generate },
759 { "SCRAM-SHA-1", PW_ENCODING_NONE, 0, scram_sha1_verify,
760 scram_sha1_generate},
761 { "SCRAM-SHA-256", PW_ENCODING_NONE, 0, scram_sha256_verify,
762 scram_sha256_generate},
763 { "HMAC-MD5", PW_ENCODING_HEX, CRAM_MD5_CONTEXTLEN,
764 NULL, cram_md5_generate },
765 { "DIGEST-MD5", PW_ENCODING_HEX, MD5_RESULTLEN,
766 NULL, digest_md5_generate },
767 { "PLAIN-MD4", PW_ENCODING_HEX, MD4_RESULTLEN,
768 NULL, plain_md4_generate },
769 { "PLAIN-MD5", PW_ENCODING_HEX, MD5_RESULTLEN,
770 NULL, plain_md5_generate },
771 { "LDAP-MD5", PW_ENCODING_BASE64, MD5_RESULTLEN,
772 NULL, plain_md5_generate },
773 { "OTP", PW_ENCODING_NONE, 0, otp_verify, otp_generate },
774 { "PBKDF2", PW_ENCODING_NONE, 0, pbkdf2_verify, pbkdf2_generate },
775 };
776
password_scheme_register(const struct password_scheme * scheme)777 void password_scheme_register(const struct password_scheme *scheme)
778 {
779 if (password_scheme_lookup_name(scheme->name) != NULL) {
780 i_panic("password_scheme_register(%s): Already registered",
781 scheme->name);
782 }
783 hash_table_insert(password_schemes, scheme->name, scheme);
784 }
785
password_scheme_unregister(const struct password_scheme * scheme)786 void password_scheme_unregister(const struct password_scheme *scheme)
787 {
788 if (!hash_table_try_remove(password_schemes, scheme->name))
789 i_panic("password_scheme_unregister(%s): Not registered", scheme->name);
790 }
791
password_schemes_get(ARRAY_TYPE (password_scheme_p)* schemes_r)792 void password_schemes_get(ARRAY_TYPE(password_scheme_p) *schemes_r)
793 {
794 struct hash_iterate_context *ctx;
795 const char *key;
796 const struct password_scheme *scheme;
797 ctx = hash_table_iterate_init(password_schemes);
798 while(hash_table_iterate(ctx, password_schemes, &key, &scheme)) {
799 array_push_back(schemes_r, &scheme);
800 }
801 hash_table_iterate_deinit(&ctx);
802 }
803
password_schemes_init(void)804 void password_schemes_init(void)
805 {
806 unsigned int i;
807
808 hash_table_create(&password_schemes, default_pool,
809 N_ELEMENTS(builtin_schemes)*2, strfastcase_hash,
810 strcasecmp);
811 for (i = 0; i < N_ELEMENTS(builtin_schemes); i++)
812 password_scheme_register(&builtin_schemes[i]);
813 password_scheme_register_crypt();
814 #ifdef HAVE_LIBSODIUM
815 password_scheme_register_sodium();
816 #endif
817 }
818
password_schemes_deinit(void)819 void password_schemes_deinit(void)
820 {
821 hash_table_destroy(&password_schemes);
822 }
823