/* * This implements the X/Open SMB password encryption * It takes a password, a 8 byte "crypt key" and puts 24 bytes of * encrypted password into p24 */ void SMBencrypt(uchar * passwd, uchar * c8, uchar * p24) { uchar p14[15], p21[21]; memset(p21, '\0', 21); memset(p14, '\0', 14); StrnCpy((char *) p14, (char *) passwd, 14); strupper((char *) p14); E_P16(p14, p21); E_P24(p21, c8, p24); }
bool E_deshash(const char *passwd, uint8_t p16[16]) { bool ret; uint8_t dospwd[14]; TALLOC_CTX *frame = talloc_stackframe(); size_t converted_size; char *tmpbuf; ZERO_STRUCT(dospwd); tmpbuf = strupper_talloc(frame, passwd); if (tmpbuf == NULL) { /* Too many callers don't check this result, we need to fill in the buffer with something */ strlcpy((char *)dospwd, passwd ? passwd : "", sizeof(dospwd)); E_P16(dospwd, p16); talloc_free(frame); return false; } ZERO_STRUCT(dospwd); ret = convert_string_error(CH_UNIX, CH_DOS, tmpbuf, strlen(tmpbuf), dospwd, sizeof(dospwd), &converted_size); talloc_free(frame); /* Only the first 14 chars are considered, password need not * be null terminated. We do this in the error and success * case to avoid returning a fixed 'password' buffer, but * callers should not use it when E_deshash returns false */ E_P16((const uint8_t *)dospwd, p16); ZERO_STRUCT(dospwd); return ret; }
/* Note that password must be uppercased and null terminated */ void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) { unsigned char p14[15], p21[21]; memset(p21, '\0', 21); memset(p14, '\0', 14); strncpy((char *) p14, (char *) passwd, 14); /* strupper((char *)p14); *//* BB at least uppercase the easy range */ E_P16(p14, p21); SMBOWFencrypt(p21, c8, p24); memset(p14, 0, 15); memset(p21, 0, 21); }
BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2) { static uchar null_pw[16]; uchar unenc_new_pw[16]; BOOL ret; if (smbpw == NULL) { DEBUG(0,("change_lanman_password: no smb password entry.\n")); return False; } if (smbpw->acct_ctrl & ACB_DISABLED) { DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); return False; } if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ)) { uchar no_pw[14]; memset(no_pw, '\0', 14); E_P16(no_pw, null_pw); smbpw->smb_passwd = null_pw; } else if (smbpw->smb_passwd == NULL) { DEBUG(0,("change_lanman_password: no lanman password !\n")); return False; } /* Get the new lanman hash. */ D_P16(smbpw->smb_passwd, pass2, unenc_new_pw); smbpw->smb_passwd = unenc_new_pw; smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */ /* Now write it into the file. */ become_root(0); ret = mod_smbpwd_entry(smbpw,False); unbecome_root(0); return ret; }
BOOL E_deshash(const char *passwd, uchar p16[16]) { BOOL ret = True; fstring dospwd; ZERO_STRUCT(dospwd); /* Password must be converted to DOS charset - null terminated, uppercase. */ push_ascii(dospwd, passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE); /* Only the fisrt 14 chars are considered, password need not be null terminated. */ E_P16((const unsigned char *)dospwd, p16); if (strlen(dospwd) > 14) { ret = False; } ZERO_STRUCT(dospwd); return ret; }
/* This implements the X/Open SMB password encryption It takes a password, a 8 byte "crypt key" and puts 24 bytes of encrypted password into p24 */ void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24) { uchar p14[15], p21[21]; memset(p21,'\0',21); memset(p14,'\0',14); StrnCpy((char *)p14,(char *)passwd,14); strupper((char *)p14); E_P16(p14, p21); SMBOWFencrypt(p21, c8, p24); #ifdef DEBUG_PASSWORD DEBUG(100,("SMBencrypt: lm#, challenge, response\n")); dump_data(100, (char *)p21, 16); dump_data(100, (char *)c8, 8); dump_data(100, (char *)p24, 24); #endif }
void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16) { char passwd[130]; strlcpy(passwd, pwd, sizeof(passwd)); /* Calculate the MD4 hash (NT compatible) of the password */ memset(nt_p16, '\0', 16); E_md4hash((uchar *)passwd, (uchar *)nt_p16); /* Mangle the passwords into Lanman format */ passwd[14] = '\0'; strupper(passwd); /* Calculate the SMB (lanman) hash functions of the password */ memset(p16, '\0', 16); E_P16((uchar *) passwd, (uchar *)p16); /* clear out local copy of user's password (just being paranoid). */ bzero(passwd, sizeof(passwd)); }
BOOL E_deshash(const char *passwd, uchar p16[16]) { BOOL ret = True; fstring dospwd; ZERO_STRUCT(dospwd); /* Password must be converted to DOS charset - null terminated, uppercase. */ //push_ascii(dospwd, passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE); { int i; if (passwd == 0) return 0; i = 0; while(1) { if(passwd[i] == 0) { dospwd[i] = 0; break; } else { dospwd[i] = toupper(passwd); } i++; } } /* Only the fisrt 14 chars are considered, password need not be null terminated. */ E_P16((const unsigned char *)dospwd, p16); if (strlen(dospwd) > 14) { ret = False; } ZERO_STRUCT(dospwd); return ret; }
NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, const DATA_BLOB *challenge, const DATA_BLOB *lm_response, const DATA_BLOB *nt_response, const DATA_BLOB *lm_interactive_pwd, const DATA_BLOB *nt_interactive_pwd, const char *username, const char *client_username, const char *client_domain, const uint8 *lm_pw, const uint8 *nt_pw, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { static const unsigned char zeros[8]; if (nt_pw == NULL) { DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", username)); } if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) { if (nt_interactive_pwd->length != 16) { DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length, username)); return NT_STATUS_WRONG_PASSWORD; } if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) { if (user_sess_key) { *user_sess_key = data_blob(NULL, 16); SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data); } return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n", username)); return NT_STATUS_WRONG_PASSWORD; } } else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) { if (lm_interactive_pwd->length != 16) { DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length, username)); return NT_STATUS_WRONG_PASSWORD; } if (!lp_lanman_auth()) { DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n", username)); return NT_STATUS_WRONG_PASSWORD; } if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) { return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n", username)); return NT_STATUS_WRONG_PASSWORD; } } /* Check for cleartext netlogon. Used by Exchange 5.5. */ if (challenge->length == sizeof(zeros) && (memcmp(challenge->data, zeros, challenge->length) == 0 )) { DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n", username)); if (nt_pw && nt_response->length) { unsigned char pwhash[16]; mdfour(pwhash, nt_response->data, nt_response->length); if (memcmp(pwhash, nt_pw, sizeof(pwhash)) == 0) { return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: NT (Unicode) plaintext password check failed for user %s\n", username)); return NT_STATUS_WRONG_PASSWORD; } } else if (!lp_lanman_auth()) { DEBUG(3,("ntlm_password_check: (plaintext password check) LANMAN passwords NOT PERMITTED for user %s\n", username)); } else if (lm_pw && lm_response->length) { uchar dospwd[14]; uchar p16[16]; ZERO_STRUCT(dospwd); memcpy(dospwd, lm_response->data, MIN(lm_response->length, sizeof(dospwd))); /* Only the fisrt 14 chars are considered, password need not be null terminated. */ /* we *might* need to upper-case the string here */ E_P16((const unsigned char *)dospwd, p16); if (memcmp(p16, lm_pw, sizeof(p16)) == 0) { return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: LANMAN (ASCII) plaintext password check failed for user %s\n", username)); return NT_STATUS_WRONG_PASSWORD; } } else { DEBUG(3, ("Plaintext authentication for user %s attempted, but neither NT nor LM passwords available\n", username)); return NT_STATUS_WRONG_PASSWORD; } } if (nt_response->length != 0 && nt_response->length < 24) { DEBUG(2,("ntlm_password_check: invalid NT password length (%lu) for user %s\n", (unsigned long)nt_response->length, username)); } if (nt_response->length >= 24 && nt_pw) { if (nt_response->length > 24) { /* We have the NT MD4 hash challenge available - see if we can use it */ DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain)); if (smb_pwd_check_ntlmv2( nt_response, nt_pw, challenge, client_username, client_domain, False, user_sess_key)) { return NT_STATUS_OK; } DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain)); if (smb_pwd_check_ntlmv2( nt_response, nt_pw, challenge, client_username, client_domain, True, user_sess_key)) { return NT_STATUS_OK; } DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n")); if (smb_pwd_check_ntlmv2( nt_response, nt_pw, challenge, client_username, "", False, user_sess_key)) { return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n")); return NT_STATUS_WRONG_PASSWORD; } } if (lp_ntlm_auth()) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("ntlm_password_check: Checking NT MD4 password\n")); if (smb_pwd_check_ntlmv1(nt_response, nt_pw, challenge, user_sess_key)) { /* The LM session key for this response is not very secure, so use it only if we otherwise allow LM authentication */ if (lp_lanman_auth() && lm_pw) { uint8 first_8_lm_hash[16]; memcpy(first_8_lm_hash, lm_pw, 8); memset(first_8_lm_hash + 8, '\0', 8); if (lm_sess_key) { *lm_sess_key = data_blob(first_8_lm_hash, 16); } } return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: NT MD4 password check failed for user %s\n", username)); return NT_STATUS_WRONG_PASSWORD; } } else { DEBUG(2,("ntlm_password_check: NTLMv1 passwords NOT PERMITTED for user %s\n", username)); /* no return, becouse we might pick up LMv2 in the LM field */ } } if (lm_response->length == 0) { DEBUG(3,("ntlm_password_check: NEITHER LanMan nor NT password supplied for user %s\n", username)); return NT_STATUS_WRONG_PASSWORD; } if (lm_response->length < 24) { DEBUG(2,("ntlm_password_check: invalid LanMan password length (%lu) for user %s\n", (unsigned long)nt_response->length, username)); return NT_STATUS_WRONG_PASSWORD; } if (!lp_lanman_auth()) { DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n", username)); } else if (!lm_pw) { DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n", username)); } else { DEBUG(4,("ntlm_password_check: Checking LM password\n")); if (smb_pwd_check_ntlmv1(lm_response, lm_pw, challenge, NULL)) { uint8 first_8_lm_hash[16]; memcpy(first_8_lm_hash, lm_pw, 8); memset(first_8_lm_hash + 8, '\0', 8); if (user_sess_key) { *user_sess_key = data_blob(first_8_lm_hash, 16); } if (lm_sess_key) { *lm_sess_key = data_blob(first_8_lm_hash, 16); } return NT_STATUS_OK; } } if (!nt_pw) { DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username)); return NT_STATUS_WRONG_PASSWORD; } /* This is for 'LMv2' authentication. almost NTLMv2 but limited to 24 bytes. - related to Win9X, legacy NAS pass-though authentication */ DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n", client_domain)); if (smb_pwd_check_ntlmv2( lm_response, nt_pw, challenge, client_username, client_domain, False, NULL)) { return NT_STATUS_OK; } DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", client_domain)); if (smb_pwd_check_ntlmv2( lm_response, nt_pw, challenge, client_username, client_domain, True, NULL)) { return NT_STATUS_OK; } DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n")); if (smb_pwd_check_ntlmv2( lm_response, nt_pw, challenge, client_username, "", False, NULL)) { return NT_STATUS_OK; } /* Apparently NT accepts NT responses in the LM field - I think this is related to Win9X pass-though authentication */ DEBUG(4,("ntlm_password_check: Checking NT MD4 password in LM field\n")); if (lp_ntlm_auth()) { if (smb_pwd_check_ntlmv1(lm_response, nt_pw, challenge, NULL)) { /* The session key for this response is still very odd. It not very secure, so use it only if we otherwise allow LM authentication */ if (lp_lanman_auth() && lm_pw) { uint8 first_8_lm_hash[16]; memcpy(first_8_lm_hash, lm_pw, 8); memset(first_8_lm_hash + 8, '\0', 8); if (user_sess_key) { *user_sess_key = data_blob(first_8_lm_hash, 16); } if (lm_sess_key) { *lm_sess_key = data_blob(first_8_lm_hash, 16); } } return NT_STATUS_OK; } DEBUG(3,("ntlm_password_check: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",username)); } else { DEBUG(3,("ntlm_password_check: LM password and LMv2 failed for user %s, and NT MD4 password in LM field not permitted\n",username)); } return NT_STATUS_WRONG_PASSWORD; }