Remove generation and handling of LM hashes

https://fedorahosted.org/freeipa/ticket/3795
This commit is contained in:
Sumit Bose 2013-10-29 12:19:01 +01:00 committed by Martin Kosek
parent b5e60c2020
commit d876a22732
7 changed files with 75 additions and 251 deletions

View File

@ -2637,10 +2637,9 @@ static bool init_sam_from_td(struct samu *user, struct pdb_trusted_domain *td,
char *name; char *name;
char *trustpw = NULL; char *trustpw = NULL;
char *trustpw_utf8 = NULL; char *trustpw_utf8 = NULL;
char *trustpw_utf8_uc = NULL;
char *tmp_str = NULL; char *tmp_str = NULL;
int ret; int ret;
struct ntlm_keys ntlm_keys; uint8_t nt_key[16];
size_t converted_size; size_t converted_size;
bool res; bool res;
char *sid_str; char *sid_str;
@ -2706,23 +2705,13 @@ static bool init_sam_from_td(struct samu *user, struct pdb_trusted_domain *td,
goto done; goto done;
} }
if (!push_utf8_talloc(user, &trustpw_utf8_uc, tmp_str, &converted_size)) { ret = encode_nt_key(trustpw_utf8, nt_key);
res = false;
goto done;
}
ret = encode_ntlm_keys(trustpw_utf8, trustpw_utf8_uc, true, true,
&ntlm_keys);
if (ret != 0) { if (ret != 0) {
res = false; res = false;
goto done; goto done;
} }
if (!pdb_set_lanman_passwd(user, ntlm_keys.lm, PDB_SET)) { if (!pdb_set_nt_passwd(user, nt_key, PDB_SET)) {
res = false;
goto done;
}
if (!pdb_set_nt_passwd(user, ntlm_keys.nt, PDB_SET)) {
res = false; res = false;
goto done; goto done;
} }
@ -2741,10 +2730,6 @@ done:
memset(tmp_str, 0, strlen(tmp_str)); memset(tmp_str, 0, strlen(tmp_str));
talloc_free(tmp_str); talloc_free(tmp_str);
} }
if (trustpw_utf8_uc != NULL) {
memset(trustpw_utf8_uc, 0, strlen(trustpw_utf8_uc));
talloc_free(trustpw_utf8_uc);
}
return res; return res;
} }

View File

@ -366,7 +366,6 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
slapi_entry_free(config_entry); slapi_entry_free(config_entry);
/* get the ipa etc/ipaConfig entry */ /* get the ipa etc/ipaConfig entry */
config->allow_lm_hash = false;
config->allow_nt_hash = false; config->allow_nt_hash = false;
ret = ipapwd_getEntry(ipa_etc_config_dn, &config_entry, NULL); ret = ipapwd_getEntry(ipa_etc_config_dn, &config_entry, NULL);
if (ret != LDAP_SUCCESS) { if (ret != LDAP_SUCCESS) {
@ -376,10 +375,6 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
tmparray = slapi_entry_attr_get_charray(config_entry, tmparray = slapi_entry_attr_get_charray(config_entry,
"ipaConfigString"); "ipaConfigString");
for (i = 0; tmparray && tmparray[i]; i++) { for (i = 0; tmparray && tmparray[i]; i++) {
if (strcasecmp(tmparray[i], "AllowLMhash") == 0) {
config->allow_lm_hash = true;
continue;
}
if (strcasecmp(tmparray[i], "AllowNThash") == 0) { if (strcasecmp(tmparray[i], "AllowNThash") == 0) {
config->allow_nt_hash = true; config->allow_nt_hash = true;
continue; continue;
@ -928,7 +923,6 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
Slapi_Value **pwvals = NULL; Slapi_Value **pwvals = NULL;
struct tm utctime; struct tm utctime;
char timestr[GENERALIZED_TIME_LENGTH+1]; char timestr[GENERALIZED_TIME_LENGTH+1];
char *lm = NULL;
char *nt = NULL; char *nt = NULL;
int is_smb = 0; int is_smb = 0;
int is_ipant = 0; int is_ipant = 0;
@ -965,7 +959,7 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
ret = ipapwd_gen_hashes(krbcfg, data, ret = ipapwd_gen_hashes(krbcfg, data,
data->password, data->password,
is_krb, is_smb, is_ipant, is_krb, is_smb, is_ipant,
&svals, &nt, &lm, &ntvals, &errMesg); &svals, &nt, &ntvals, &errMesg);
if (ret) { if (ret) {
goto free_and_return; goto free_and_return;
} }
@ -1004,11 +998,6 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
} }
} }
if (lm && is_smb) {
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"sambaLMPassword", lm);
}
if (nt && is_smb) { if (nt && is_smb) {
slapi_mods_add_string(smods, LDAP_MOD_REPLACE, slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"sambaNTPassword", nt); "sambaNTPassword", nt);
@ -1069,7 +1058,6 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
LOG_TRACE("<= result: %d\n", ret); LOG_TRACE("<= result: %d\n", ret);
free_and_return: free_and_return:
if (lm) slapi_ch_free((void **)&lm);
if (nt) slapi_ch_free((void **)&nt); if (nt) slapi_ch_free((void **)&nt);
if (modtime) slapi_ch_free((void **)&modtime); if (modtime) slapi_ch_free((void **)&modtime);
slapi_mods_free(&smods); slapi_mods_free(&smods);

View File

@ -201,15 +201,13 @@ enc_error:
int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg, int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
struct ipapwd_data *data, char *userpw, struct ipapwd_data *data, char *userpw,
int is_krb, int is_smb, int is_ipant, Slapi_Value ***svals, int is_krb, int is_smb, int is_ipant, Slapi_Value ***svals,
char **nthash, char **lmhash, Slapi_Value ***ntvals, char **nthash, Slapi_Value ***ntvals,
char **errMesg) char **errMesg)
{ {
int rc; int rc;
char *userpw_uc = NULL;
*svals = NULL; *svals = NULL;
*nthash = NULL; *nthash = NULL;
*lmhash = NULL;
*errMesg = NULL; *errMesg = NULL;
if (is_krb) { if (is_krb) {
@ -225,40 +223,24 @@ int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
} }
if (is_smb || is_ipant) { if (is_smb || is_ipant) {
char lm[33], nt[33]; char nt[33];
struct ntlm_keys ntlm; uint8_t nt_key[16];
int ret; int ret;
userpw_uc = (char *) slapi_utf8StrToUpper((unsigned char *) userpw);
if (!userpw_uc) {
*errMesg = "Failed to generate upper case password\n";
LOG_FATAL("%s", *errMesg);
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
ret = encode_ntlm_keys(userpw,
userpw_uc,
krbcfg->allow_lm_hash,
krbcfg->allow_nt_hash,
&ntlm);
memset(userpw_uc, 0, strlen(userpw_uc));
slapi_ch_free_string(&userpw_uc);
if (ret) {
*errMesg = "Failed to generate NT/LM hashes\n";
LOG_FATAL("%s", *errMesg);
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
if (krbcfg->allow_lm_hash) {
hexbuf(lm, ntlm.lm);
lm[32] = '\0';
*lmhash = slapi_ch_strdup(lm);
}
if (krbcfg->allow_nt_hash) { if (krbcfg->allow_nt_hash) {
hexbuf(nt, ntlm.nt); ret = encode_nt_key(userpw, nt_key);
if (ret) {
*errMesg = "Failed to generate NT/LM hashes\n";
LOG_FATAL("%s", *errMesg);
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
hexbuf(nt, nt_key);
nt[32] = '\0'; nt[32] = '\0';
*nthash = slapi_ch_strdup(nt); *nthash = slapi_ch_strdup(nt);
} else {
memset(nt_key, 0, 16);
} }
if (is_ipant) { if (is_ipant) {
@ -269,7 +251,7 @@ int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
goto done; goto done;
} }
(*ntvals)[0] = slapi_value_new(); (*ntvals)[0] = slapi_value_new();
if (slapi_value_set((*ntvals)[0], ntlm.nt, 16) == NULL) { if (slapi_value_set((*ntvals)[0], nt_key, 16) == NULL) {
rc = LDAP_OPERATIONS_ERROR; rc = LDAP_OPERATIONS_ERROR;
goto done; goto done;
} }

View File

@ -132,7 +132,6 @@ struct ipapwd_krbcfg {
krb5_key_salt_tuple *pref_encsalts; krb5_key_salt_tuple *pref_encsalts;
char **passsync_mgrs; char **passsync_mgrs;
int num_passsync_mgrs; int num_passsync_mgrs;
bool allow_lm_hash;
bool allow_nt_hash; bool allow_nt_hash;
}; };
@ -172,7 +171,7 @@ void ipapwd_keyset_free(struct ipapwd_keyset **pkset);
int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg, int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
struct ipapwd_data *data, char *userpw, struct ipapwd_data *data, char *userpw,
int is_krb, int is_smb, int is_ipant, int is_krb, int is_smb, int is_ipant,
Slapi_Value ***svals, char **nthash, char **lmhash, Slapi_Value ***svals, char **nthash,
Slapi_Value ***ntvals, char **errMesg); Slapi_Value ***ntvals, char **errMesg);
/* from prepost.c */ /* from prepost.c */

View File

@ -325,13 +325,12 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
Slapi_Value **svals = NULL; Slapi_Value **svals = NULL;
Slapi_Value **ntvals = NULL; Slapi_Value **ntvals = NULL;
char *nt = NULL; char *nt = NULL;
char *lm = NULL;
pwdop->is_krb = is_krb; pwdop->is_krb = is_krb;
rc = ipapwd_gen_hashes(krbcfg, &pwdop->pwdata, rc = ipapwd_gen_hashes(krbcfg, &pwdop->pwdata,
userpw, is_krb, is_smb, is_ipant, userpw, is_krb, is_smb, is_ipant,
&svals, &nt, &lm, &ntvals, &errMesg); &svals, &nt, &ntvals, &errMesg);
if (rc != LDAP_SUCCESS) { if (rc != LDAP_SUCCESS) {
goto done; goto done;
} }
@ -349,11 +348,6 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
ipapwd_free_slapi_value_array(&svals); ipapwd_free_slapi_value_array(&svals);
} }
if (lm && is_smb) {
/* set value */
slapi_entry_attr_set_charptr(e, "sambaLMPassword", lm);
slapi_ch_free_string(&lm);
}
if (nt && is_smb) { if (nt && is_smb) {
/* set value */ /* set value */
slapi_entry_attr_set_charptr(e, "sambaNTPassword", nt); slapi_entry_attr_set_charptr(e, "sambaNTPassword", nt);
@ -814,11 +808,10 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
Slapi_Value **svals = NULL; Slapi_Value **svals = NULL;
Slapi_Value **ntvals = NULL; Slapi_Value **ntvals = NULL;
char *nt = NULL; char *nt = NULL;
char *lm = NULL;
rc = ipapwd_gen_hashes(krbcfg, &pwdop->pwdata, unhashedpw, rc = ipapwd_gen_hashes(krbcfg, &pwdop->pwdata, unhashedpw,
gen_krb_keys, is_smb, is_ipant, gen_krb_keys, is_smb, is_ipant,
&svals, &nt, &lm, &ntvals, &errMesg); &svals, &nt, &ntvals, &errMesg);
if (rc) { if (rc) {
goto done; goto done;
} }
@ -830,12 +823,6 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
ipapwd_free_slapi_value_array(&svals); ipapwd_free_slapi_value_array(&svals);
} }
if (lm && is_smb) {
/* replace value */
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"sambaLMPassword", lm);
slapi_ch_free_string(&lm);
}
if (nt && is_smb) { if (nt && is_smb) {
/* replace value */ /* replace value */
slapi_mods_add_string(smods, LDAP_MOD_REPLACE, slapi_mods_add_string(smods, LDAP_MOD_REPLACE,

View File

@ -74,15 +74,6 @@ int ipapwd_generate_new_history(char *password,
char ***new_pwd_history, char ***new_pwd_history,
int *new_pwd_hlen); int *new_pwd_hlen);
struct ntlm_keys { int encode_nt_key(char *newPasswd, uint8_t *nt_key);
uint8_t lm[16];
uint8_t nt[16];
};
int encode_ntlm_keys(char *newPasswd,
char *upperPasswd,
bool do_lm_hash,
bool do_nt_hash,
struct ntlm_keys *keys);
#endif #endif

View File

@ -32,178 +32,70 @@
#define KTF_UTF8 "UTF-8" #define KTF_UTF8 "UTF-8"
#define KTF_UCS2 "UCS-2LE" #define KTF_UCS2 "UCS-2LE"
static const uint8_t parity_table[128] = { /* create the nt hash
1, 2, 4, 7, 8, 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31,
32, 35, 37, 38, 41, 42, 44, 47, 49, 50, 52, 55, 56, 59, 61, 62,
64, 67, 69, 70, 73, 74, 76, 79, 81, 82, 84, 87, 88, 91, 93, 94,
97, 98,100,103,104,107,109,110,112,115,117,118,121,122,124,127,
128,131,133,134,137,138,140,143,145,146,148,151,152,155,157,158,
161,162,164,167,168,171,173,174,176,179,181,182,185,186,188,191,
193,194,196,199,200,203,205,206,208,211,213,214,217,218,220,223,
224,227,229,230,233,234,236,239,241,242,244,247,248,251,253,254
};
static void lm_shuffle(uint8_t *out, uint8_t *in)
{
out[0] = parity_table[in[0]>>1];
out[1] = parity_table[((in[0]<<6)|(in[1]>>2)) & 0x7F];
out[2] = parity_table[((in[1]<<5)|(in[2]>>3)) & 0x7F];
out[3] = parity_table[((in[2]<<4)|(in[3]>>4)) & 0x7F];
out[4] = parity_table[((in[3]<<3)|(in[4]>>5)) & 0x7F];
out[5] = parity_table[((in[4]<<2)|(in[5]>>6)) & 0x7F];
out[6] = parity_table[((in[5]<<1)|(in[6]>>7)) & 0x7F];
out[7] = parity_table[in[6] & 0x7F];
}
/* create the lm and nt hashes
newPassword: the clear text utf8 password newPassword: the clear text utf8 password
upperPasswd: upper case version of clear text utf8 password nt_key[out]: array with generated hash
do_lm_hash: determine if LM hash is generated
do_nt_hash: determine if NT hash is generated
keys[out]: array with generated hashes
*/ */
int encode_ntlm_keys(char *newPasswd, int encode_nt_key(char *newPasswd, uint8_t *nt_key)
char *upperPasswd,
bool do_lm_hash,
bool do_nt_hash,
struct ntlm_keys *keys)
{ {
int ret = 0; int ret = 0;
iconv_t cd;
size_t cs, il, ol, sl;
char *inc, *outc;
char *ucs2Passwd;
MD4_CTX md4ctx;
/* do lanman first */ /* TODO: must store the dos charset somewhere in the directory */
if (do_lm_hash) { cd = iconv_open(KTF_UCS2, KTF_UTF8);
iconv_t cd; if (cd == (iconv_t)(-1)) {
size_t cs, il, ol; ret = -1;
char *inc, *outc; goto done;
char *asciiPasswd;
DES_key_schedule schedule;
DES_cblock deskey;
DES_cblock magic = "KGS!@#$%";
if (upperPasswd == NULL) {
ret = -1;
goto done;
}
il = strlen(upperPasswd);
/* TODO: must store the dos charset somewhere in the directory */
cd = iconv_open(KTF_DOS_CHARSET, KTF_UTF8);
if (cd == (iconv_t)(-1)) {
ret = -1;
goto done;
}
/* an ascii string can only be smaller than or equal to an utf8 one */
ol = il;
if (ol < 14) ol = 14;
asciiPasswd = calloc(ol+1, 1);
if (!asciiPasswd) {
iconv_close(cd);
ret = -1;
goto done;
}
inc = upperPasswd;
outc = asciiPasswd;
cs = iconv(cd, &inc, &il, &outc, &ol);
if (cs == -1) {
ret = -1;
free(asciiPasswd);
iconv_close(cd);
goto done;
}
/* done with these */
iconv_close(cd);
/* we are interested only in the first 14 ASCII chars for lanman */
if (strlen(asciiPasswd) > 14) {
asciiPasswd[14] = '\0';
}
/* first half */
lm_shuffle(deskey, (uint8_t *)asciiPasswd);
DES_set_key_unchecked(&deskey, &schedule);
DES_ecb_encrypt(&magic, (DES_cblock *)keys->lm,
&schedule, DES_ENCRYPT);
/* second half */
lm_shuffle(deskey, (uint8_t *)&asciiPasswd[7]);
DES_set_key_unchecked(&deskey, &schedule);
DES_ecb_encrypt(&magic, (DES_cblock *)&(keys->lm[8]),
&schedule, DES_ENCRYPT);
/* done with it */
free(asciiPasswd);
} else {
memset(keys->lm, 0, 16);
} }
if (do_nt_hash) { il = strlen(newPasswd);
iconv_t cd;
size_t cs, il, ol, sl;
char *inc, *outc;
char *ucs2Passwd;
MD4_CTX md4ctx;
/* TODO: must store the dos charset somewhere in the directory */ /* an ucs2 string can be at most double than an utf8 one */
cd = iconv_open(KTF_UCS2, KTF_UTF8); sl = ol = (il+1)*2;
if (cd == (iconv_t)(-1)) { ucs2Passwd = calloc(ol, 1);
ret = -1; if (!ucs2Passwd) {
goto done; ret = -1;
}
il = strlen(newPasswd);
/* an ucs2 string can be at most double than an utf8 one */
sl = ol = (il+1)*2;
ucs2Passwd = calloc(ol, 1);
if (!ucs2Passwd) {
ret = -1;
iconv_close(cd);
goto done;
}
inc = newPasswd;
outc = ucs2Passwd;
cs = iconv(cd, &inc, &il, &outc, &ol);
if (cs == -1) {
ret = -1;
free(ucs2Passwd);
iconv_close(cd);
goto done;
}
/* done with it */
iconv_close(cd); iconv_close(cd);
goto done;
}
/* get the final ucs2 string length */ inc = newPasswd;
sl -= ol; outc = ucs2Passwd;
cs = iconv(cd, &inc, &il, &outc, &ol);
if (cs == -1) {
ret = -1;
free(ucs2Passwd);
iconv_close(cd);
goto done;
}
ret = MD4_Init(&md4ctx); /* done with it */
if (ret == 0) { iconv_close(cd);
ret = -1;
free(ucs2Passwd);
goto done;
}
ret = MD4_Update(&md4ctx, ucs2Passwd, sl);
if (ret == 0) {
ret = -1;
free(ucs2Passwd);
goto done;
}
ret = MD4_Final(keys->nt, &md4ctx);
if (ret == 0) {
ret = -1;
free(ucs2Passwd);
goto done;
}
} else { /* get the final ucs2 string length */
memset(keys->nt, 0, 16); sl -= ol;
ret = MD4_Init(&md4ctx);
if (ret == 0) {
ret = -1;
free(ucs2Passwd);
goto done;
}
ret = MD4_Update(&md4ctx, ucs2Passwd, sl);
if (ret == 0) {
ret = -1;
free(ucs2Passwd);
goto done;
}
ret = MD4_Final(nt_key, &md4ctx);
if (ret == 0) {
ret = -1;
free(ucs2Passwd);
goto done;
} }
ret = 0; ret = 0;