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