@@ -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