X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblutil%2Fpasswd.c;h=d5ab32617261f06e9f4a11ab9df444d3aae4b4f0;hb=8452b4ccde09a41c7e21cff66ec4f566b1a34e28;hp=5460b0376a9226050de5691404c1f206ca9df835;hpb=2da2336ac69afd7ca3605d74c07b5c5d5ae15700;p=openldap diff --git a/libraries/liblutil/passwd.c b/libraries/liblutil/passwd.c index 5460b0376a..d5ab326172 100644 --- a/libraries/liblutil/passwd.c +++ b/libraries/liblutil/passwd.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2005 The OpenLDAP Foundation. + * Copyright 1998-2012 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,32 @@ #include #if defined(SLAPD_LMHASH) +#if defined(HAVE_OPENSSL) # include + + +typedef des_cblock des_key; +typedef des_cblock des_data_block; +typedef des_key_schedule des_context; +#define des_failed(encrypted) 0 +#define des_finish(key, schedule) + +#elif defined(HAVE_MOZNSS) +/* + hack hack hack + We need to define this here so that nspr/obsolete/protypes.h will not be included + if that file is included, it will create a uint32 typedef that will cause the + one in lutil_sha1.h to blow up +*/ +#define PROTYPES_H 1 +# include +typedef PK11SymKey *des_key; +typedef unsigned char des_data_block[8]; +typedef PK11Context *des_context[1]; +#define DES_ENCRYPT CKA_ENCRYPT + +#endif + #endif /* SLAPD_LMHASH */ #include @@ -42,7 +67,7 @@ #ifdef SLAPD_CRYPT # include -# if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) +# if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) # ifdef HAVE_SHADOW_H # include # endif @@ -73,6 +98,10 @@ static lutil_cryptfunc lutil_crypt; lutil_cryptfunc *lutil_cryptptr = lutil_crypt; #endif +/* KLUDGE: + * chk_fn is NULL iff name is {CLEARTEXT} + * otherwise, things will break + */ struct pw_scheme { struct berval name; LUTIL_PASSWD_CHK_FUNC *chk_fn; @@ -110,7 +139,7 @@ static LUTIL_PASSWD_HASH_FUNC hash_lanman; static LUTIL_PASSWD_CHK_FUNC chk_crypt; static LUTIL_PASSWD_HASH_FUNC hash_crypt; -#if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) +#if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) static LUTIL_PASSWD_CHK_FUNC chk_unix; #endif #endif @@ -140,14 +169,14 @@ static const struct pw_scheme pw_schemes_default[] = #ifdef SLAPD_CRYPT { BER_BVC("{CRYPT}"), chk_crypt, hash_crypt }, -# if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) +# if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) { BER_BVC("{UNIX}"), chk_unix, NULL }, # endif #endif #ifdef SLAPD_CLEARTEXT /* pseudo scheme */ - { {0, "{CLEARTEXT}"}, NULL, hash_clear }, + { BER_BVC("{CLEARTEXT}"), NULL, hash_clear }, #endif { BER_BVNULL, NULL, NULL } @@ -197,11 +226,19 @@ static const struct pw_scheme *get_scheme( const char* scheme ) { struct pw_slist *pws; + struct berval bv; if (!pw_inited) lutil_passwd_init(); + bv.bv_val = strchr( scheme, '}' ); + if ( !bv.bv_val ) + return NULL; + + bv.bv_len = bv.bv_val - scheme + 1; + bv.bv_val = (char *) scheme; + for( pws=pw_schemes; pws; pws=pws->next ) { - if( strcasecmp(scheme, pws->s.name.bv_val ) == 0 ) { + if ( ber_bvstrcasecmp(&bv, &pws->s.name ) == 0 ) { return &(pws->s); } } @@ -293,10 +330,17 @@ lutil_passwd( } #ifdef SLAPD_CLEARTEXT + /* Do we think there is a scheme specifier here that we + * didn't recognize? Assume a scheme name is at least 1 character. + */ + if (( passwd->bv_val[0] == '{' ) && + ( ber_bvchr( passwd, '}' ) > passwd->bv_val+1 )) + { + return 1; + } if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) { - return (( passwd->bv_len == cred->bv_len ) && - ( passwd->bv_val[0] != '{' /*'}'*/ )) - ? memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len ) + return ( passwd->bv_len == cred->bv_len ) ? + memcmp( passwd->bv_val, cred->bv_val, passwd->bv_len ) : 1; } #endif @@ -380,7 +424,7 @@ static int pw_string( } #endif /* SLAPD_LMHASH || SLAPD_CRYPT */ -static int pw_string64( +int lutil_passwd_string64( const struct berval *sc, const struct berval *hash, struct berval *b64, @@ -613,6 +657,106 @@ static int chk_md5( } #ifdef SLAPD_LMHASH + +#if defined(HAVE_OPENSSL) + +/* + * abstract away setting the parity. + */ +static void +des_set_key_and_parity( des_key *key, unsigned char *keyData) +{ + memcpy(key, keyData, 8); + des_set_odd_parity( key ); +} + + +#elif defined(HAVE_MOZNSS) + +/* + * implement MozNSS wrappers for the openSSL calls + */ +static void +des_set_key_and_parity( des_key *key, unsigned char *keyData) +{ + SECItem keyDataItem; + PK11SlotInfo *slot; + *key = NULL; + + keyDataItem.data = keyData; + keyDataItem.len = 8; + + slot = PK11_GetBestSlot(CKM_DES_ECB, NULL); + if (slot == NULL) { + return; + } + + /* NOTE: this will not work in FIPS mode. In order to make lmhash + * work in fips mode we need to define a LMHASH pbe mechanism and + * do the fulll key derivation inside the token */ + *key = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginGenerated, + CKA_ENCRYPT, &keyDataItem, NULL); +} + +static void +des_set_key_unchecked( des_key *key, des_context ctxt ) +{ + ctxt[0] = NULL; + + /* handle error conditions from previous call */ + if (!*key) { + return; + } + + ctxt[0] = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT, *key, NULL); +} + +static void +des_ecb_encrypt( des_data_block *plain, des_data_block *encrypted, + des_context ctxt, int op) +{ + SECStatus rv; + int size; + + if (ctxt[0] == NULL) { + /* need to fail here... */ + memset(encrypted, 0, sizeof(des_data_block)); + return; + } + rv = PK11_CipherOp(ctxt[0], (unsigned char *)&encrypted[0], + &size, sizeof(des_data_block), + (unsigned char *)&plain[0], sizeof(des_data_block)); + if (rv != SECSuccess) { + /* signal failure */ + memset(encrypted, 0, sizeof(des_data_block)); + return; + } + return; +} + +static int +des_failed(des_data_block *encrypted) +{ + static const des_data_block zero = { 0 }; + return memcmp(encrypted, zero, sizeof(zero)) == 0; +} + +static void +des_finish(des_key *key, des_context ctxt) +{ + if (*key) { + PK11_FreeSymKey(*key); + *key = NULL; + } + if (ctxt[0]) { + PK11_Finalize(ctxt[0]); + PK11_DestroyContext(ctxt[0], PR_TRUE); + ctxt[0] = NULL; + } +} + +#endif + /* pseudocode from RFC2433 * A.2 LmPasswordHash() * @@ -672,20 +816,23 @@ static int chk_md5( */ static void lmPasswd_to_key( - const unsigned char *lmPasswd, - des_cblock *key) + const char *lmPasswd, + des_key *key) { + const unsigned char *lpw = (const unsigned char *) lmPasswd; + unsigned char k[8]; + /* make room for parity bits */ - ((char *)key)[0] = lmPasswd[0]; - ((char *)key)[1] = ((lmPasswd[0]&0x01)<<7) | (lmPasswd[1]>>1); - ((char *)key)[2] = ((lmPasswd[1]&0x03)<<6) | (lmPasswd[2]>>2); - ((char *)key)[3] = ((lmPasswd[2]&0x07)<<5) | (lmPasswd[3]>>3); - ((char *)key)[4] = ((lmPasswd[3]&0x0F)<<4) | (lmPasswd[4]>>4); - ((char *)key)[5] = ((lmPasswd[4]&0x1F)<<3) | (lmPasswd[5]>>5); - ((char *)key)[6] = ((lmPasswd[5]&0x3F)<<2) | (lmPasswd[6]>>6); - ((char *)key)[7] = ((lmPasswd[6]&0x7F)<<1); + k[0] = lpw[0]; + k[1] = ((lpw[0] & 0x01) << 7) | (lpw[1] >> 1); + k[2] = ((lpw[1] & 0x03) << 6) | (lpw[2] >> 2); + k[3] = ((lpw[2] & 0x07) << 5) | (lpw[3] >> 3); + k[4] = ((lpw[3] & 0x0F) << 4) | (lpw[4] >> 4); + k[5] = ((lpw[4] & 0x1F) << 3) | (lpw[5] >> 5); + k[6] = ((lpw[5] & 0x3F) << 2) | (lpw[6] >> 6); + k[7] = ((lpw[6] & 0x7F) << 1); - des_set_odd_parity( key ); + des_set_key_and_parity( key, k ); } static int chk_lanman( @@ -694,12 +841,12 @@ static int chk_lanman( const struct berval *cred, const char **text ) { - int i; + ber_len_t i; char UcasePassword[15]; - des_cblock key; - des_key_schedule schedule; - des_cblock StdText = "KGS!@#$%"; - des_cblock PasswordHash1, PasswordHash2; + des_key key; + des_context schedule; + des_data_block StdText = "KGS!@#$%"; + des_data_block PasswordHash1, PasswordHash2; char PasswordHash[33], storedPasswordHash[33]; for( i=0; ibv_len; i++) { @@ -719,10 +866,19 @@ static int chk_lanman( lmPasswd_to_key( UcasePassword, &key ); des_set_key_unchecked( &key, schedule ); des_ecb_encrypt( &StdText, &PasswordHash1, schedule , DES_ENCRYPT ); + + if (des_failed(&PasswordHash1)) { + return LUTIL_PASSWD_ERR; + } lmPasswd_to_key( &UcasePassword[7], &key ); des_set_key_unchecked( &key, schedule ); des_ecb_encrypt( &StdText, &PasswordHash2, schedule , DES_ENCRYPT ); + if (des_failed(&PasswordHash2)) { + return LUTIL_PASSWD_ERR; + } + + des_finish( &key, schedule ); sprintf( PasswordHash, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", PasswordHash1[0],PasswordHash1[1],PasswordHash1[2],PasswordHash1[3], @@ -768,9 +924,7 @@ static int chk_crypt( const struct berval * cred, const char **text ) { - char *cr; unsigned int i; - int rc; for( i=0; ibv_len; i++) { if(cred->bv_val[i] == '\0') { @@ -799,7 +953,7 @@ static int chk_crypt( return lutil_cryptptr( cred->bv_val, passwd->bv_val, NULL ); } -# if defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) +# if defined( HAVE_GETPWNAM ) && defined( HAVE_STRUCT_PASSWD_PW_PASSWD ) static int chk_unix( const struct berval *sc, const struct berval * passwd, @@ -807,7 +961,7 @@ static int chk_unix( const char **text ) { unsigned int i; - char *pw,*cr; + char *pw; for( i=0; ibv_len; i++) { if(cred->bv_val[i] == '\0') { @@ -897,7 +1051,7 @@ static int hash_ssha1( (const unsigned char *)salt.bv_val, salt.bv_len ); lutil_SHA1Final( SHA1digest, &SHA1context ); - return pw_string64( scheme, &digest, hash, &salt); + return lutil_passwd_string64( scheme, &digest, hash, &salt); } static int hash_sha1( @@ -917,7 +1071,7 @@ static int hash_sha1( (const unsigned char *)passwd->bv_val, passwd->bv_len ); lutil_SHA1Final( SHA1digest, &SHA1context ); - return pw_string64( scheme, &digest, hash, NULL); + return lutil_passwd_string64( scheme, &digest, hash, NULL); } #endif @@ -949,7 +1103,7 @@ static int hash_smd5( (const unsigned char *) salt.bv_val, salt.bv_len ); lutil_MD5Final( MD5digest, &MD5context ); - return pw_string64( scheme, &digest, hash, &salt ); + return lutil_passwd_string64( scheme, &digest, hash, &salt ); } static int hash_md5( @@ -971,7 +1125,7 @@ static int hash_md5( (const unsigned char *) passwd->bv_val, passwd->bv_len ); lutil_MD5Final( MD5digest, &MD5context ); - return pw_string64( scheme, &digest, hash, NULL ); + return lutil_passwd_string64( scheme, &digest, hash, NULL ); ; } @@ -983,12 +1137,12 @@ static int hash_lanman( const char **text ) { - int i; + ber_len_t i; char UcasePassword[15]; - des_cblock key; - des_key_schedule schedule; - des_cblock StdText = "KGS!@#$%"; - des_cblock PasswordHash1, PasswordHash2; + des_key key; + des_context schedule; + des_data_block StdText = "KGS!@#$%"; + des_data_block PasswordHash1, PasswordHash2; char PasswordHash[33]; for( i=0; ibv_len; i++) { @@ -1087,7 +1241,7 @@ static int hash_crypt( int lutil_salt_format(const char *format) { #ifdef SLAPD_CRYPT - free( salt_format ); + ber_memfree( salt_format ); salt_format = format != NULL ? ber_strdup( format ) : NULL; #endif