@ -166,57 +166,27 @@ SETDEFAULTS_FUNC(mod_authn_file_set_defaults) {
# ifdef USE_LIB_CRYPTO
static void mod_authn_file_digest_sha256 ( http_auth_info_t * ai , const char * pw , size_t pwlen ) {
SHA256_CTX ctx ;
SHA256_Init ( & ctx ) ;
SHA256_Update ( & ctx , ( const unsigned char * ) ai - > username , ai - > ulen ) ;
SHA256_Update ( & ctx , CONST_STR_LEN ( " : " ) ) ;
SHA256_Update ( & ctx , ( const unsigned char * ) ai - > realm , ai - > rlen ) ;
SHA256_Update ( & ctx , CONST_STR_LEN ( " : " ) ) ;
SHA256_Update ( & ctx , ( const unsigned char * ) pw , pwlen ) ;
SHA256_Final ( ai - > digest , & ctx ) ;
}
# ifdef USE_LIB_CRYPTO_SHA512_256
static void mod_authn_file_digest_sha512_256 ( http_auth_info_t * ai , const char * pw , size_t pwlen ) {
SHA512_CTX ctx ;
SHA512_256_Init ( & ctx ) ;
SHA512_256_Update ( & ctx , ( const unsigned char * ) ai - > username , ai - > ulen ) ;
SHA512_256_Update ( & ctx , CONST_STR_LEN ( " : " ) ) ;
SHA512_256_Update ( & ctx , ( const unsigned char * ) ai - > realm , ai - > rlen ) ;
SHA512_256_Update ( & ctx , CONST_STR_LEN ( " : " ) ) ;
SHA512_256_Update ( & ctx , ( const unsigned char * ) pw , pwlen ) ;
SHA512_256_Final ( ai - > digest , & ctx ) ;
}
# endif
# endif
static void mod_authn_file_digest_md5 ( http_auth_info_t * ai , const char * pw , size_t pwlen ) {
li_MD5_CTX ctx ;
li_MD5_Init ( & ctx ) ;
li_MD5_Update ( & ctx , ( const unsigned char * ) ai - > username , ai - > ulen ) ;
li_MD5_Update ( & ctx , CONST_STR_LEN ( " : " ) ) ;
li_MD5_Update ( & ctx , ( const unsigned char * ) ai - > realm , ai - > rlen ) ;
li_MD5_Update ( & ctx , CONST_STR_LEN ( " : " ) ) ;
li_MD5_Update ( & ctx , ( const unsigned char * ) pw , pwlen ) ;
li_MD5_Final ( ai - > digest , & ctx ) ;
}
static void mod_authn_file_digest ( http_auth_info_t * ai , const char * pw , size_t pwlen ) {
if ( ai - > dalgo & HTTP_AUTH_DIGEST_MD5 )
mod_authn_file_digest_md5 ( ai , pw , pwlen ) ;
li_md_iov_fn digest_iov = MD5_iov ;
/* (ai->dalgo & HTTP_AUTH_DIGEST_MD5) default */
# ifdef USE_LIB_CRYPTO
else if ( ai - > dalgo & HTTP_AUTH_DIGEST_SHA256 )
mod_authn_file_digest_sha256 ( ai , pw , pwlen ) ;
if ( ai - > dalgo & HTTP_AUTH_DIGEST_SHA256 )
digest_iov = SHA256_iov ;
# ifdef USE_LIB_CRYPTO_SHA512_256
else if ( ai - > dalgo & HTTP_AUTH_DIGEST_SHA512_256 )
mod_authn_file_digest_sha512_256 ( ai , pw , pwlen ) ;
digest_iov = SHA512_256_iov ;
# endif
# endif
struct const_iovec iov [ ] = {
{ ai - > username , ai - > ulen }
, { " : " , 1 }
, { ai - > realm , ai - > rlen }
, { " : " , 1 }
, { pw , pwlen }
} ;
digest_iov ( ai - > digest , iov , sizeof ( iov ) / sizeof ( * iov ) ) ;
}
@ -390,32 +360,34 @@ static int mod_authn_file_htpasswd_get(const buffer *auth_fn, const char *userna
static handler_t mod_authn_file_plain_digest ( request_st * const r , void * p_d , http_auth_info_t * const ai ) {
plugin_data * p = ( plugin_data * ) p_d ;
buffer * password_buf = buffer_init ( ) ; /* password-string from auth-backend */
int rc ;
mod_authn_file_patch_config ( r , p ) ;
rc = mod_authn_file_htpasswd_get ( p - > conf . auth_plain_userfile , ai - > username , ai - > ulen , password_buf , r - > conf . errh ) ;
if ( 0 = = rc ) {
/* generate password from plain-text */
mod_authn_file_digest ( ai , BUF_PTR_LEN ( password_buf ) ) ;
}
ck_memzero ( password_buf - > ptr , password_buf - > size ) ;
buffer_free ( password_buf ) ;
return ( 0 = = rc ) ? HANDLER_GO_ON : HANDLER_ERROR ;
buffer * const tb = r - > tmp_buf ; /* password-string from auth-backend */
int rc = mod_authn_file_htpasswd_get ( p - > conf . auth_plain_userfile ,
ai - > username , ai - > ulen , tb ,
r - > conf . errh ) ;
if ( 0 ! = rc ) return HANDLER_ERROR ;
/* generate password digest from plain-text */
mod_authn_file_digest ( ai , BUF_PTR_LEN ( tb ) ) ;
size_t tblen = ( buffer_clen ( tb ) + 63 ) & ~ 63u ;
buffer_clear ( tb ) ;
ck_memzero ( tb - > ptr , tblen < tb - > size ? tblen : tb - > size ) ;
return HANDLER_GO_ON ;
}
static handler_t mod_authn_file_plain_basic ( request_st * const r , void * p_d , const http_auth_require_t * const require , const buffer * const username , const char * const pw ) {
plugin_data * p = ( plugin_data * ) p_d ;
buffer * password_buf = buffer_init ( ) ; /* password-string from auth-backend */
int rc ;
mod_authn_file_patch_config ( r , p ) ;
rc = mod_authn_file_htpasswd_get ( p - > conf . auth_plain_userfile , BUF_PTR_LEN ( username ) , password_buf , r - > conf . errh ) ;
buffer * const tb = r - > tmp_buf ; /* password-string from auth-backend */
int rc = mod_authn_file_htpasswd_get ( p - > conf . auth_plain_userfile ,
BUF_PTR_LEN ( username ) , tb ,
r - > conf . errh ) ;
if ( 0 = = rc ) {
rc = ck_memeq_const_time ( BUF_PTR_LEN ( password_buf ) , pw , strlen ( pw ) )
? 0
: - 1 ;
rc = ck_memeq_const_time ( BUF_PTR_LEN ( tb ) , pw , strlen ( pw ) ) ? 0 : - 1 ;
size_t tblen = ( buffer_clen ( tb ) + 63 ) & ~ 63u ;
buffer_clear ( tb ) ;
ck_memzero ( tb - > ptr , tblen < tb - > size ? tblen : tb - > size ) ;
}
ck_memzero ( password_buf - > ptr , password_buf - > size ) ;
buffer_free ( password_buf ) ;
return 0 = = rc & & http_auth_match_rules ( require , username - > ptr , NULL , NULL )
? HANDLER_GO_ON
: HANDLER_ERROR ;
@ -426,6 +398,7 @@ static handler_t mod_authn_file_plain_basic(request_st * const r, void *p_d, con
/**
* the $ apr1 $ handling is taken from apache 1.3 . x
* XXX : code has since been modified for slightly better performance
*/
/*
@ -459,201 +432,151 @@ static void to64(char *s, unsigned long v, int n)
}
}
static void apr_md5_encode ( const char * pw , const char * salt , char * result , size_t nbytes ) {
/*
* Minimum size is 8 bytes for salt , plus 1 for the trailing NUL ,
* plus 4 for the ' $ ' separators , plus the password hash itself .
* Let ' s leave a goodly amount of leeway .
*/
static size_t apr_md5_encode ( const char * pw , const char * salt , char * result , size_t nbytes ) {
force_assert ( nbytes > = 37 ) ; /*(nbytes should be >= 37)*/
char passwd [ 120 ] , * p ;
const char * sp , * ep ;
unsigned char final [ APR_MD5_DIGESTSIZE ] ;
ssize_t sl , pl , i ;
li_MD5_CTX ctx , ctx1 ;
unsigned long l ;
const size_t pwlen = strlen ( pw ) ;
ssize_t sl ;
/*
* Refine the salt first . It ' s possible we were given an already - hashed
* string as the salt argument , so extract the actual salt value from it
* if so . Otherwise just use the string up to the first ' $ ' as the salt .
*/
sp = salt ;
#if 0 /*(already checked and stepped-over in caller)*/
/*
* If it starts with the magic string , then skip that .
*/
if ( ! strncmp ( s p, APR1_ID , strlen ( APR1_ID ) ) ) {
s p + = strlen ( APR1_ID ) ;
if ( ! strncmp ( s alt, APR1_ID , sizeof ( APR1_ID ) - 1 ) ) {
s alt + = sizeof ( APR1_ID ) - 1 ;
}
# endif
/*
* It stops at the first ' $ ' or 8 chars , whichever comes firs t
* Get the length of the true sal t
*/
for ( ep = sp ; ( * ep ! = ' \0 ' ) & & ( * ep ! = ' $ ' ) & & ( ep < ( sp + 8 ) ) ; ep + + ) {
continue ;
}
/*
* Get the length of the true sal t
* It stops at the first ' $ ' or 8 chars , whichever comes first
*/
sl = ep - sp ;
for ( sl = 0 ; sl < 8 & & salt [ sl ] ! = ' $ ' & & salt [ sl ] ! = ' \0 ' ; + + sl ) ;
/* result begins with "$apr1$salt$" */
memcpy ( result , APR1_ID , sizeof ( APR1_ID ) - 1 ) ;
memcpy ( result + sizeof ( APR1_ID ) - 1 , salt , sl ) ;
result [ sizeof ( APR1_ID ) - 1 + sl ] = ' $ ' ;
MD5_CTX ctx ;
unsigned char final [ APR_MD5_DIGESTSIZE ] ;
MD5_Init ( & ctx ) ;
MD5_Update ( & ctx , pw , pwlen ) ;
MD5_Update ( & ctx , salt , sl ) ;
MD5_Update ( & ctx , pw , pwlen ) ;
MD5_Final ( final , & ctx ) ;
/*
* ' Time to make the doughnuts . . '
*/
li_MD5_Init ( & ctx ) ;
MD5_Init( & ctx ) ;
/*
* The password first , since that is what is most unknown
*/
li_MD5_Update ( & ctx , pw , strlen ( pw ) ) ;
MD5_Update( & ctx , pw , pwlen ) ;
#if 0
/*
* Then our magic string
*/
li_ MD5_Update( & ctx , APR1_ID , strlen ( APR1_ID ) ) ;
MD5_Update( & ctx , APR1_ID , sizeof ( APR1_ID ) - 1 ) ;
/*
* Then the raw salt
*/
li_MD5_Update ( & ctx , sp , sl ) ;
MD5_Update ( & ctx , salt , sl ) ;
# else
MD5_Update ( & ctx , result , sizeof ( APR1_ID ) - 1 + sl ) ;
# endif
/*
* Then just as many characters of the MD5 ( pw , salt , pw )
*/
li_MD5_Init ( & ctx1 ) ;
li_MD5_Update ( & ctx1 , pw , strlen ( pw ) ) ;
li_MD5_Update ( & ctx1 , sp , sl ) ;
li_MD5_Update ( & ctx1 , pw , strlen ( pw ) ) ;
li_MD5_Final ( final , & ctx1 ) ;
for ( pl = strlen ( pw ) ; pl > 0 ; pl - = APR_MD5_DIGESTSIZE ) {
li_MD5_Update ( & ctx , final ,
( pl > APR_MD5_DIGESTSIZE ) ? APR_MD5_DIGESTSIZE : pl ) ;
for ( ssize_t pl = pwlen ; pl > 0 ; pl - = APR_MD5_DIGESTSIZE ) {
MD5_Update ( & ctx , final ,
( pl > APR_MD5_DIGESTSIZE ) ? APR_MD5_DIGESTSIZE : pl ) ;
}
/*
* Don ' t leave anything around in vm they could use .
*/
memset ( final , 0 , sizeof ( final ) ) ;
/*ck_memzero(final, sizeof(final));*/
final [ 0 ] = 0 ; /*(preserve behavior for loop below)*/
/*
* Then something really weird . . .
*/
for ( i = strlen ( pw ) ; i ! = 0 ; i > > = 1 ) {
if ( i & 1 ) {
li_MD5_Update ( & ctx , final , 1 ) ;
}
else {
li_MD5_Update ( & ctx , pw , 1 ) ;
}
for ( size_t i = pwlen ; i ! = 0 ; i > > = 1 ) {
MD5_Update ( & ctx , ( i & 1 ) ? ( char * ) final : pw , 1 ) ;
}
/*
* Now make the output string . We know our limitations , so we
* can use the string routines without bounds checking .
*/
strcpy ( passwd , APR1_ID ) ;
strncat ( passwd , sp , sl ) ;
strcat ( passwd , " $ " ) ;
li_MD5_Final ( final , & ctx ) ;
MD5_Final ( final , & ctx ) ;
/*
* And now , just to make sure things don ' t run too fast . .
* On a 60 Mhz Pentium this takes 34 msec , so you would
* need 30 seconds to build a 1000 entry dictionary . . .
*/
for ( i = 0 ; i < 1000 ; i + + ) {
li_ MD5_Init( & ctx 1 ) ;
for ( int i = 0 ; i < 1000 ; + + i ) {
MD5_Init ( & ctx ) ;
if ( i & 1 ) {
li_MD5_Update( & ctx1 , pw , strlen ( pw ) ) ;
MD5_Update( & ctx , pw , pwlen ) ;
}
else {
li_ MD5_Update( & ctx 1 , final , APR_MD5_DIGESTSIZE ) ;
MD5_Update( & ctx , final , APR_MD5_DIGESTSIZE ) ;
}
if ( i % 3 ) {
li_MD5_Update( & ctx1 , sp , sl ) ;
MD5_Update( & ctx , salt , sl ) ;
}
if ( i % 7 ) {
li_MD5_Update( & ctx1 , pw , strlen ( pw ) ) ;
MD5_Update( & ctx , pw , pwlen ) ;
}
if ( i & 1 ) {
li_ MD5_Update( & ctx 1 , final , APR_MD5_DIGESTSIZE ) ;
MD5_Update( & ctx , final , APR_MD5_DIGESTSIZE ) ;
}
else {
li_MD5_Update( & ctx1 , pw , strlen ( pw ) ) ;
MD5_Update( & ctx , pw , pwlen ) ;
}
li_ MD5_Final( final , & ctx 1 ) ;
MD5_Final( final , & ctx ) ;
}
p = passwd + strlen ( passwd ) ;
/*
* Now make the output string . ( nbytes checked at top of func )
* Maximum result size below is 37 :
* 6 for APR_ID , < = 8 for salt , 1 for ' $ ' , 22 for password hash
*/
l = ( final [ 0 ] < < 16 ) | ( final [ 6 ] < < 8 ) | final [ 12 ] ; to64 ( p , l , 4 ) ; p + = 4 ;
l = ( final [ 1 ] < < 16 ) | ( final [ 7 ] < < 8 ) | final [ 13 ] ; to64 ( p , l , 4 ) ; p + = 4 ;
l = ( final [ 2 ] < < 16 ) | ( final [ 8 ] < < 8 ) | final [ 14 ] ; to64 ( p , l , 4 ) ; p + = 4 ;
l = ( final [ 3 ] < < 16 ) | ( final [ 9] < < 8 ) | final [ 15 ] ; to64 ( p , l , 4 ) ; p + = 4 ;
l = ( final [ 4 ] < < 16 ) | ( final [ 10 ] < < 8 ) | final [ 5] ; to64 ( p , l , 4 ) ; p + = 4 ;
l = final [ 11 ] ; to64 ( p , l , 2 ) ; p + = 2 ;
* p = ' \0 ' ;
result + = sizeof ( APR1_ID ) - 1 + sl + 1 ;
to64 ( result , ( final [ 0 ] < < 16 ) | ( final [ 6] < < 8 ) | final [ 12 ] , 4 ) ;
to64 ( result + 4 , ( final [ 1 ] < < 16 ) | ( final [ 7] < < 8 ) | final [ 13 ] , 4 ) ;
to64 ( result + 8 , ( final [ 2 ] < < 16 ) | ( final [ 8] < < 8 ) | final [ 14 ] , 4 ) ;
to64 ( result + 12 , ( final [ 3 ] < < 16 ) | ( final [ 9 ] < < 8 ) | final [ 1 5] , 4 ) ;
to64 ( result + 16 , ( final [ 4 ] < < 16 ) | ( final [ 10 ] < < 8 ) | final [ 5 ] , 4 ) ;
to64 ( result + 20 , final [ 11 ] , 2 ) ;
/*
* Don ' t leave anything around in vm they could use .
*/
ck_memzero ( final , sizeof ( final ) ) ;
/* FIXME
*/
# define apr_cpystrn strncpy
apr_cpystrn ( result , passwd , nbytes - 1 ) ;
}
static void apr_sha_encode ( const char * pw , char * result , size_t nbytes ) {
unsigned char digest [ 20 ] ;
size_t base64_written ;
SHA_CTX sha1 ;
SHA1_Init ( & sha1 ) ;
SHA1_Update ( & sha1 , ( const unsigned char * ) pw , strlen ( pw ) ) ;
SHA1_Final ( digest , & sha1 ) ;
memset ( result , 0 , nbytes ) ;
/* need 5 bytes for "{SHA}", 28 for base64 (3 bytes -> 4 bytes) of SHA1 (20 bytes), 1 terminating */
if ( nbytes < 5 + 28 + 1 ) return ;
memcpy ( result , " {SHA} " , 5 ) ;
base64_written = li_to_base64 ( result + 5 , nbytes - 5 , digest , 20 , BASE64_STANDARD ) ;
force_assert ( base64_written = = 28 ) ;
result [ 5 + base64_written ] = ' \0 ' ; /* terminate string */
return ( sizeof ( APR1_ID ) - 1 + sl + 1 + 22 ) ;
}
static handler_t mod_authn_file_htpasswd_basic ( request_st * const r , void * p_d , const http_auth_require_t * const require , const buffer * const username , const char * const pw ) {
plugin_data * p = ( plugin_data * ) p_d ;
buffer * password = buffer_init ( ) ; /* password-string from auth-backend */
int rc ;
mod_authn_file_patch_config ( r , p ) ;
rc = mod_authn_file_htpasswd_get ( p - > conf . auth_htpasswd_userfile , BUF_PTR_LEN ( username ) , password , r - > conf . errh ) ;
if ( 0 = = rc ) {
char sample [ 256 ] ;
rc = - 1 ;
if ( ! strncmp ( password - > ptr , APR1_ID , strlen ( APR1_ID ) ) ) {
/*
* The hash was created using $ apr1 $ custom algorithm .
*/
apr_md5_encode ( pw , password - > ptr , sample , sizeof ( sample ) ) ;
rc = strcmp ( sample , password - > ptr ) ;
}
else if ( 0 = = strncmp ( password - > ptr , " {SHA} " , 5 ) ) {
apr_sha_encode ( pw , sample , sizeof ( sample ) ) ;
rc = strcmp ( sample , password - > ptr ) ;
}
# if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)
/* a simple DES password is 2 + 11 characters. everything else should be longer. */
else if ( buffer_clen ( password ) > = 13 ) {
# if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)
static int mod_authn_file_crypt_cmp ( const buffer * const password , const char * const pw ) {
int rc = - 1 ;
char * crypted ;
char sample [ 256 ] ;
#if 0 && defined(HAVE_CRYPT_R)
struct crypt_data crypt_tmp_data ;
# ifdef _AIX
@ -663,9 +586,10 @@ static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d,
# endif
# endif
# ifdef USE_LIB_CRYPTO_MD4 /*(for MD4_*() (e.g. MD4_Update()))*/
/*(caller checked buffer_clen(passwd) >= 13)*/
if ( 0 = = memcmp ( password - > ptr , CONST_STR_LEN ( " $1+ntlm$ " ) ) ) {
/* CRYPT-MD5-NTLM algorithm
* This algorithm allows for the construction of ( slight more )
* This algorithm allows for the construction of ( slight ly more )
* secure , salted password hashes from an environment where only
* legacy NTLM hashes are available and where it is not feasible
* to re - hash all the passwords with the MD5 - based crypt ( ) . */
@ -681,10 +605,6 @@ static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d,
& & pwlen < sizeof ( sample ) ) {
/* compute NTLM hash and convert to lowercase hex chars
* ( require lc hex chars from li_tohex ( ) ) */
char ntlmhash [ 16 ] ;
char ntlmhex [ 33 ] ; /*(sizeof(ntlmhash)*2 + 1)*/
MD4_CTX c ;
MD4_Init ( & c ) ;
if ( pwlen ) {
/*(reuse sample buffer to encode pw into UCS-2LE)
* ( Note : assumes pw input in ISO - 8859 - 1 ) */
@ -693,9 +613,10 @@ static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d,
sample [ i ] = pw [ ( i > > 1 ) ] ;
sample [ i + 1 ] = 0 ;
}
MD4_Update ( & c , ( unsigned char * ) sample , pwlen ) ;
}
MD4_Final ( ( unsigned char * ) ntlmhash , & c ) ;
char ntlmhash [ MD4_DIGEST_LENGTH ] ;
char ntlmhex [ MD4_DIGEST_LENGTH * 2 + 1 ] ;
MD4_once ( ( unsigned char * ) ntlmhash , sample , pwlen ) ;
li_tohex ( ntlmhex , sizeof ( ntlmhex ) , ntlmhash , sizeof ( ntlmhash ) ) ;
/*(reuse sample buffer for salt (FYI: expect slen == 8))*/
@ -725,11 +646,51 @@ static handler_t mod_authn_file_htpasswd_basic(request_st * const r, void *p_d,
rc = strcmp ( password - > ptr , crypted ) ;
}
}
}
# endif
ck_memzero ( sample , sizeof ( sample ) ) ;
return rc ;
}
# endif
static handler_t mod_authn_file_htpasswd_basic ( request_st * const r , void * p_d , const http_auth_require_t * const require , const buffer * const username , const char * const pw ) {
plugin_data * p = ( plugin_data * ) p_d ;
mod_authn_file_patch_config ( r , p ) ;
buffer * const tb = r - > tmp_buf ; /* password-string from auth-backend */
int rc = mod_authn_file_htpasswd_get ( p - > conf . auth_htpasswd_userfile ,
BUF_PTR_LEN ( username ) , tb ,
r - > conf . errh ) ;
if ( 0 ! = rc ) return HANDLER_ERROR ;
uint32_t tblen = buffer_clen ( tb ) ;
rc = - 1 ;
if ( tblen > = 5 & & 0 = = memcmp ( tb - > ptr , " {SHA} " , 5 ) ) {
/* 32 == (5 for "{SHA}" + 28 for base64 of SHA1 (20 bytes)) */
unsigned char digest [ SHA_DIGEST_LENGTH * 2 ] ;
SHA1_once ( digest + SHA_DIGEST_LENGTH , pw , strlen ( pw ) ) ;
rc = SHA_DIGEST_LENGTH
= = li_base64_dec ( digest , sizeof ( digest ) ,
tb - > ptr + 5 , tblen - 5 , BASE64_STANDARD )
& & ck_memeq_const_time_fixed_len ( digest , digest + SHA_DIGEST_LENGTH ,
SHA_DIGEST_LENGTH ) ;
rc = ! rc ; /* (0 == rc) for match */
ck_memzero ( digest , sizeof ( digest ) ) ;
}
ck_memzero ( password - > ptr , password - > size ) ;
buffer_free ( password ) ;
else if ( tblen > = 6 & & 0 = = memcmp ( tb - > ptr , " $apr1$ " , 6 ) ) {
char sample [ 40 ] ; /*(see comments at end of apr_md5_encode())*/
rc = tblen = = apr_md5_encode ( pw , tb - > ptr + 6 , sample , sizeof ( sample ) )
& & ck_memeq_const_time_fixed_len ( sample , tb - > ptr , tblen ) ;
rc = ! rc ; /* (0 == rc) for match */
ck_memzero ( sample , sizeof ( sample ) ) ;
}
# if defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)
/* simple DES password is 2 + 11 characters;
* everything else should be longer */
else if ( tblen > = 13 ) {
rc = mod_authn_file_crypt_cmp ( tb , pw ) ;
}
# endif
tblen = ( tblen + 63 ) & ~ 63u ;
buffer_clear ( tb ) ;
ck_memzero ( tb - > ptr , tblen < tb - > size ? tblen : tb - > size ) ;
return 0 = = rc & & http_auth_match_rules ( require , username - > ptr , NULL , NULL )
? HANDLER_GO_ON
: HANDLER_ERROR ;