make cram() sane

- don't silently fail in release mode (expression with side effects
  inside assert())
- save some redundand strlen()s by not throwing away known lengths
- reorganize the code for legibility
This commit is contained in:
Oswald Buddenhagen 2011-01-23 13:35:56 +01:00
parent 058d01f179
commit 7e1c16ae02

View File

@ -1223,49 +1223,45 @@ hexchar( unsigned int b )
return 'a' + (b - 10); return 'a' + (b - 10);
} }
/* XXX merge into do_cram_auth? */ static void
static char * cram( const char *challenge, const char *user, const char *pass, char **_final, int *_finallen )
cram( const char *challenge, const char *user, const char *pass )
{ {
unsigned char *response, *final;
unsigned hashlen;
int i, clen, rlen, blen, flen, olen;
unsigned char hash[16];
char buf[256], hex[33];
HMAC_CTX hmac; HMAC_CTX hmac;
char hash[16];
char hex[33];
int i;
unsigned int hashlen = sizeof(hash);
char buf[256];
int len = strlen( challenge );
char *response = nfcalloc( 1 + len );
char *final;
/* response will always be smaller than challenge because we are
* decoding.
*/
len = EVP_DecodeBlock( (unsigned char *)response, (unsigned char *)challenge, strlen( challenge ) );
HMAC_Init( &hmac, (unsigned char *)pass, strlen( pass ), EVP_md5() ); HMAC_Init( &hmac, (unsigned char *)pass, strlen( pass ), EVP_md5() );
HMAC_Update( &hmac, (unsigned char *)response, strlen( response ) );
HMAC_Final( &hmac, (unsigned char *)hash, &hashlen );
assert( hashlen == sizeof(hash) );
clen = strlen( challenge );
/* response will always be smaller than challenge because we are decoding. */
response = nfcalloc( 1 + clen );
rlen = EVP_DecodeBlock( response, (unsigned char *)challenge, clen );
HMAC_Update( &hmac, response, rlen );
free( response ); free( response );
hashlen = sizeof(hash);
HMAC_Final( &hmac, hash, &hashlen );
assert( hashlen == sizeof(hash) );
hex[32] = 0; hex[32] = 0;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
hex[2 * i] = hexchar( (hash[i] >> 4) & 0xf ); hex[2 * i] = hexchar( (hash[i] >> 4) & 0xf );
hex[2 * i + 1] = hexchar( hash[i] & 0xf ); hex[2 * i + 1] = hexchar( hash[i] & 0xf );
} }
nfsnprintf( buf, sizeof(buf), "%s %s", user, hex ); blen = nfsnprintf( buf, sizeof(buf), "%s %s", user, hex );
len = strlen( buf ); flen = ENCODED_SIZE( blen );
len = ENCODED_SIZE( len ) + 1; final = nfmalloc( flen + 1 );
final = nfmalloc( len ); final[flen] = 0;
final[len - 1] = 0; olen = EVP_EncodeBlock( (unsigned char *)final, (unsigned char *)buf, blen );
assert( olen == flen );
assert( EVP_EncodeBlock( (unsigned char *)final, (unsigned char *)buf, strlen( buf ) ) == len - 1 ); *_final = (char *)final;
*_finallen = flen;
return final;
} }
static int static int
@ -1275,11 +1271,10 @@ do_cram_auth( imap_store_t *ctx, struct imap_cmd *cmdp, const char *prompt )
char *resp; char *resp;
int n, l; int n, l;
resp = cram( prompt, srvc->user, srvc->pass ); cram( prompt, srvc->user, srvc->pass, &resp, &l );
if (DFlags & VERBOSE) if (DFlags & VERBOSE)
printf( ">+> %s\n", resp ); printf( ">+> %s\n", resp );
l = strlen( resp );
n = socket_write( &ctx->buf.sock, resp, l ); n = socket_write( &ctx->buf.sock, resp, l );
free( resp ); free( resp );
if (n != l) if (n != l)