Skip to content

Commit 0f6fee0

Browse files
committed
catch various extreme corner cases
1 parent 241753b commit 0f6fee0

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

src/modules/rlm_pap/rlm_pap.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -355,12 +355,14 @@ static unlang_action_t CC_HINT(nonnull) pap_auth_evp_md(unlang_result_t *p_resul
355355
unsigned int digest_len;
356356

357357
ctx = EVP_MD_CTX_create();
358+
if (!ctx) return UNLANG_ACTION_FAIL;
359+
358360
EVP_DigestInit_ex(ctx, md, NULL);
359361
EVP_DigestUpdate(ctx, password->vb_octets, password->vb_length);
360362
EVP_DigestFinal_ex(ctx, digest, &digest_len);
361363
EVP_MD_CTX_destroy(ctx);
362364

363-
fr_assert((size_t) digest_len == known_good->vp_length); /* This would be an OpenSSL bug... */
365+
if ((size_t) digest_len != known_good->vp_length) return UNLANG_ACTION_FAIL; /* This would be an OpenSSL bug... */
364366

365367
if (fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0) {
366368
REDEBUG("%s digest does not match \"known good\" digest", name);
@@ -385,13 +387,15 @@ static unlang_action_t CC_HINT(nonnull) pap_auth_evp_md_salted(unlang_result_t *
385387

386388
min_len = EVP_MD_size(md);
387389
ctx = EVP_MD_CTX_create();
390+
if (!ctx) return UNLANG_ACTION_FAIL;
391+
388392
EVP_DigestInit_ex(ctx, md, NULL);
389393
EVP_DigestUpdate(ctx, password->vb_octets, password->vb_length);
390394
EVP_DigestUpdate(ctx, known_good->vp_octets + min_len, known_good->vp_length - min_len);
391395
EVP_DigestFinal_ex(ctx, digest, &digest_len);
392396
EVP_MD_CTX_destroy(ctx);
393397

394-
fr_assert((size_t) digest_len == min_len); /* This would be an OpenSSL bug... */
398+
if ((size_t) digest_len != min_len) return UNLANG_ACTION_FAIL; /* This would be an OpenSSL bug... */
395399

396400
/*
397401
* Only compare digest_len bytes, the rest is salt.
@@ -545,28 +549,34 @@ static inline CC_HINT(nonnull) unlang_action_t pap_auth_pbkdf2_parse_digest(unla
545549
* If it's not base64 encoded, assume it's ascii
546550
*/
547551
if (!iter_is_base64) {
548-
char iterations_buff[sizeof("4294967295") + 1];
552+
unsigned long iterations_long;
549553
char *qq;
554+
char iterations_buff[sizeof("4294967295")];
550555

551556
/*
552557
* While passwords come from "trusted" sources, we don't trust them too much!
553558
*/
554559
if ((size_t) (q - p) >= sizeof(iterations_buff)) {
555560
REMARKER((char const *) p, q - p,
556561
"Password.PBKDF2 iterations field is too large");
557-
558562
goto finish;
559563
}
560564

561565
strlcpy(iterations_buff, (char const *)p, (q - p) + 1);
562566

563-
iterations = strtoul(iterations_buff, &qq, 10);
567+
iterations_long = strtoul(iterations_buff, &qq, 10);
564568
if (*qq != '\0') {
565569
REMARKER(iterations_buff, qq - iterations_buff,
566570
"Password.PBKDF2 iterations field contains an invalid character");
567-
568571
goto finish;
569572
}
573+
if (iterations_long > UINT32_MAX) {
574+
REMARKER(iterations_buff, qq - iterations_buff,
575+
"Password.PBKDF2 iterations field contains too large iteration count");
576+
goto finish;
577+
}
578+
iterations = iterations_long;
579+
570580
p = q + 1;
571581
/*
572582
* base64 encoded and big endian
@@ -640,6 +650,14 @@ static inline CC_HINT(nonnull) unlang_action_t pap_auth_pbkdf2_parse_digest(unla
640650
fr_table_str_by_value(pbkdf2_crypt_names, digest_type, "<UNKNOWN>"),
641651
iterations, salt_len, slen);
642652

653+
/*
654+
* Extreme corner case: prevent integer overflow when we change data types via a cast.
655+
*/
656+
if ((password->vb_length > INT_MAX) || (salt_len > INT_MAX) ||
657+
(iterations > INT_MAX) || (digest_len > INT_MAX)) {
658+
return UNLANG_ACTION_FAIL;
659+
}
660+
643661
/*
644662
* Hash and compare
645663
*/

0 commit comments

Comments
 (0)