int E_md4hash(const unsigned char *passwd, unsigned char *p16) { int rc; int len; __u16 wpwd[129]; /* Password cannot be longer than 128 characters */ if (passwd) { len = strlen((char *) passwd); if (len > 128) len = 128; /* Password must be converted to NT unicode */ _my_mbstowcs(wpwd, passwd, len); } else len = 0; wpwd[len] = 0; /* Ensure string is null terminated */ /* Calculate length in bytes */ len = _my_wcslen(wpwd) * sizeof(__u16); rc = mdfour(p16, (unsigned char *) wpwd, len); memset(wpwd, 0, 129 * 2); return rc; }
char *decrypt_trustdom_secret(const char *pass, DATA_BLOB *data_in) { DATA_BLOB data_out, sess_key; uchar nt_hash[16]; uint32_t length; uint32_t version; fstring cleartextpwd; if (!data_in || !pass) return NULL; /* generate md4 password-hash derived from the NT UNICODE password */ E_md4hash(pass, nt_hash); /* hashed twice with md4 */ mdfour(nt_hash, nt_hash, 16); /* 16-Byte session-key */ sess_key = data_blob(nt_hash, 16); if (sess_key.data == NULL) return NULL; data_out = data_blob(NULL, data_in->length); if (data_out.data == NULL) return NULL; /* decrypt with des3 */ sess_crypt_blob(&data_out, data_in, &sess_key, 0); /* 4 Byte length, 4 Byte version */ length = IVAL(data_out.data, 0); version = IVAL(data_out.data, 4); if (length > data_in->length - 8) { DEBUG(0,("decrypt_trustdom_secret: invalid length (%d)\n", length)); return NULL; } if (version != 1) { DEBUG(0,("decrypt_trustdom_secret: unknown version number (%d)\n", version)); return NULL; } rpcstr_pull(cleartextpwd, data_out.data + 8, sizeof(fstring), length, 0 ); #ifdef DEBUG_PASSWORD DEBUG(100,("decrypt_trustdom_secret: length is: %d, version is: %d, password is: %s\n", length, version, cleartextpwd)); #endif data_blob_free(&data_out); data_blob_free(&sess_key); return SMB_STRDUP(cleartextpwd); }
/* We fill in key by putting in 40 byte array which was allocated by caller */ int cifs_calculate_mac_key(char * key, const char * rn, const char * password) { char temp_key[16]; if ((key == NULL) || (rn == NULL)) return -EINVAL; E_md4hash(password, temp_key); mdfour(key,temp_key,16); memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE); return 0; }
unsigned int Com_BlockChecksum(const void *buffer, int length){ int digest[4]; unsigned int val; mdfour((unsigned char *) digest,(unsigned char *) buffer, length); val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3]; return val; }
bool E_md4hash(const char *passwd, uint8_t p16[16]) { size_t len; smb_ucs2_t *wpwd; bool ret; ret = push_ucs2_talloc(NULL, &wpwd, passwd, &len); if (!ret || len < 2) { /* We don't want to return fixed data, as most callers * don't check */ mdfour(p16, (const uint8_t *)passwd, strlen(passwd)); return false; } len -= 2; mdfour(p16, (const uint8_t *)wpwd, len); talloc_free(wpwd); return true; }
void SMBsesskeygen_ntv1(const uint8_t kr[16], uint8_t sess_key[16]) { /* yes, this session key does not change - yes, this is a problem - but it is 128 bits */ mdfour((uint8_t *)sess_key, kr, 16); #ifdef DEBUG_PASSWORD DEBUG(100, ("SMBsesskeygen_ntv1:\n")); dump_data(100, sess_key, 16); #endif }
/* We fill in key by putting in 40 byte array which was allocated by caller */ int cifs_calculate_mac_key(struct mac_key *key, const char *rn, const char *password) { char temp_key[16]; if ((key == NULL) || (rn == NULL)) return -EINVAL; E_md4hash(password, temp_key); mdfour(key->data.ntlm, temp_key, 16); memcpy(key->data.ntlm+16, rn, CIFS_SESS_KEY_SIZE); key->len = 40; return 0; }
void E_md4hash(const char *passwd, uchar p16[16]) { int len; smb_ucs2_t wpwd[129]; /* Password must be converted to NT unicode - null terminated. */ //push_ucs2(NULL, wpwd, (const char *)passwd, 256, STR_UNICODE|STR_NOALIGN|STR_TERMINATE); /* Calculate length in bytes */ len = strlen_w(wpwd) * sizeof(int16); mdfour(p16, (unsigned char *)wpwd, len); ZERO_STRUCT(wpwd); }
static void do_filehash(const char *fname, unsigned char *the_hash) { unsigned char buf[1011]; /* deliberate weird size */ unsigned char tmp_md4[16]; int fd, n; fd = sys_open(fname,O_RDONLY,0); if (fd == -1) return; while ((n = read(fd, (char *)buf, sizeof(buf))) > 0) { mdfour(tmp_md4, buf, n); for (n=0;n<16;n++) the_hash[n] ^= tmp_md4[n]; } close(fd); }
void E_md4hash(uchar *passwd, uchar *p16) { int len; int16 wpwd[129]; /* Password cannot be longer than 128 characters */ len = strlen((char *)passwd); if(len > 128) len = 128; /* Password must be converted to NT unicode */ _my_mbstowcs(wpwd, passwd, len); wpwd[len] = 0; /* Ensure string is null terminated */ /* Calculate length in bytes */ len = _my_wcslen(wpwd) * sizeof(int16); mdfour(p16, (unsigned char *)wpwd, len); }
/** Interface to the (hopefully) good crypto random number generator. Will use our internal PRNG if more than 40 bytes of random generation has been requested, otherwise tries to read from /dev/random **/ _PUBLIC_ void generate_random_buffer(uint8_t *out, int len) { unsigned char md4_buf[64]; unsigned char tmp_buf[16]; unsigned char *p; if(!done_reseed) { bytes_since_reseed += len; /* Magic constant to try and avoid reading 40 bytes * and setting up the PRNG if the app only ever wants * a few bytes */ if (bytes_since_reseed < 40) { if (urand_fd == -1) { urand_fd = open( "/dev/urandom", O_RDONLY,0); if (urand_fd != -1) { smb_set_close_on_exec(urand_fd); } } if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { return; } } urand_fd = do_reseed(urand_fd); done_reseed = true; } /* * Generate random numbers in chunks of 64 bytes, * then md4 them & copy to the output buffer. * This way the raw state of the stream is never externally * seen. */ p = out; while(len > 0) { int copy_len = len > 16 ? 16 : len; get_random_stream(md4_buf, sizeof(md4_buf)); mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); memcpy(p, tmp_buf, copy_len); p += copy_len; len -= copy_len; } }
/* * Set a utf16 password on the credentials context, including an indication * of 'how' the password was obtained * * This is required because the nt_hash is calculated over the raw utf16 blob, * which might not be completely valid utf16, which means the conversion * from CH_UTF16MUNGED to CH_UTF8 might loose information. */ _PUBLIC_ bool cli_credentials_set_utf16_password(struct cli_credentials *cred, const DATA_BLOB *password_utf16, enum credentials_obtained obtained) { if (password_utf16 == NULL) { return cli_credentials_set_password(cred, NULL, obtained); } if (obtained >= cred->password_obtained) { struct samr_Password *nt_hash = NULL; char *password_talloc = NULL; size_t password_len = 0; bool ok; nt_hash = talloc(cred, struct samr_Password); if (nt_hash == NULL) { return false; } ok = convert_string_talloc(cred, CH_UTF16MUNGED, CH_UTF8, password_utf16->data, password_utf16->length, (void *)&password_talloc, &password_len); if (!ok) { TALLOC_FREE(nt_hash); return false; } ok = cli_credentials_set_password(cred, password_talloc, obtained); TALLOC_FREE(password_talloc); if (!ok) { TALLOC_FREE(nt_hash); return false; } mdfour(nt_hash->hash, password_utf16->data, password_utf16->length); cred->nt_hash = nt_hash; return true; } return false; }
void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now) { static BOOL done_reseed = False; static int urand_fd = -1; unsigned char md4_buf[64]; unsigned char tmp_buf[16]; unsigned char *p; if(!done_reseed || do_reseed_now) { urand_fd = do_reseed(True, urand_fd); done_reseed = True; } if (urand_fd != -1 && len > 0) { if (read(urand_fd, out, len) == len) return; /* len bytes of random data read from urandom. */ /* Read of urand error, drop back to non urand method. */ close(urand_fd); urand_fd = -1; do_reseed(False, -1); done_reseed = True; } /* * Generate random numbers in chunks of 64 bytes, * then md4 them & copy to the output buffer. * This way the raw state of the stream is never externally * seen. */ p = out; while(len > 0) { int copy_len = len > 16 ? 16 : len; get_random_stream(md4_buf, sizeof(md4_buf)); mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); memcpy(p, tmp_buf, copy_len); p += copy_len; len -= copy_len; } }
void E_md4hash(const char *passwd, uchar p16[16]) { int len; smb_ucs2_t wpwd[129]; int i; len = strlen(passwd); for (i = 0; i < len; i++) { #if __BYTE_ORDER == __LITTLE_ENDIAN wpwd[i] = (unsigned char)passwd[i]; #else wpwd[i] = (unsigned char)passwd[i]; wpwd[i] <<= 8; #endif } wpwd[i] = 0; len = len * sizeof(int16); mdfour(p16, (unsigned char *)wpwd, len); ZERO_STRUCT(wpwd); }
/******************************************************************* Get the next challenge value - no repeats. ********************************************************************/ void generate_next_challenge(char *challenge) { unsigned char buf[16]; static int counter = 0; struct timeval tval; int v1,v2; /* get a sort-of random number */ GetTimeOfDay(&tval); v1 = (counter++) + getpid() + tval.tv_sec; v2 = (counter++) * getpid() + tval.tv_usec; SIVAL(challenge,0,v1); SIVAL(challenge,4,v2); /* mash it up with md4 */ mdfour(buf, (unsigned char *)challenge, 8); memcpy(saved_challenge, buf, 8); memcpy(challenge,buf,8); challenge_sent = True; }
/* * Set a old utf16 password on the credentials context. * * This is required because the nt_hash is calculated over the raw utf16 blob, * which might not be completely valid utf16, which means the conversion * from CH_UTF16MUNGED to CH_UTF8 might loose information. */ _PUBLIC_ bool cli_credentials_set_old_utf16_password(struct cli_credentials *cred, const DATA_BLOB *password_utf16) { struct samr_Password *nt_hash = NULL; char *password_talloc = NULL; size_t password_len = 0; bool ok; if (password_utf16 == NULL) { return cli_credentials_set_old_password(cred, NULL, CRED_SPECIFIED); } nt_hash = talloc(cred, struct samr_Password); if (nt_hash == NULL) { return false; } ok = convert_string_talloc(cred, CH_UTF16MUNGED, CH_UTF8, password_utf16->data, password_utf16->length, (void *)&password_talloc, &password_len); if (!ok) { TALLOC_FREE(nt_hash); return false; } ok = cli_credentials_set_old_password(cred, password_talloc, CRED_SPECIFIED); TALLOC_FREE(password_talloc); if (!ok) { TALLOC_FREE(nt_hash); return false; } mdfour(nt_hash->hash, password_utf16->data, password_utf16->length); cred->old_nt_hash = nt_hash; return true; }
/* first calculate 24 bytes ntlm response and then 16 byte session key */ int setup_ntlm_response(struct cifsSesInfo *ses) { unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; char temp_key[CIFS_SESS_KEY_SIZE]; if (!ses) return -EINVAL; ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL); if (!ses->auth_key.response) { cERROR(1, "NTLM can't allocate (%u bytes) memory", temp_len); return -ENOMEM; } ses->auth_key.len = temp_len; SMBNTencrypt(ses->password, ses->server->cryptkey, ses->auth_key.response + CIFS_SESS_KEY_SIZE); E_md4hash(ses->password, temp_key); mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); return 0; }
/* first calculate 24 bytes ntlm response and then 16 byte session key */ int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp) { int rc = 0; unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; char temp_key[CIFS_SESS_KEY_SIZE]; if (!ses) return -EINVAL; ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL); if (!ses->auth_key.response) return -ENOMEM; ses->auth_key.len = temp_len; rc = SMBNTencrypt(ses->password, ses->server->cryptkey, ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp); if (rc) { cifs_dbg(FYI, "%s Can't generate NTLM response, error: %d\n", __func__, rc); return rc; } rc = E_md4hash(ses->password, temp_key, nls_cp); if (rc) { cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n", __func__, rc); return rc; } rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); if (rc) cifs_dbg(FYI, "%s Can't generate NTLM session key, error: %d\n", __func__, rc); return rc; }
/* first calculate 24 bytes ntlm response and then 16 byte session key */ int setup_ntlm_response(struct cifsSesInfo *ses) { int rc = 0; unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; char temp_key[CIFS_SESS_KEY_SIZE]; if (!ses) return -EINVAL; ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL); if (!ses->auth_key.response) { cERROR(1, "NTLM can't allocate (%u bytes) memory", temp_len); return -ENOMEM; } ses->auth_key.len = temp_len; rc = SMBNTencrypt(ses->password, ses->server->cryptkey, ses->auth_key.response + CIFS_SESS_KEY_SIZE); if (rc) { cFYI(1, "%s Can't generate NTLM response, error: %d", __func__, rc); return rc; } rc = E_md4hash(ses->password, temp_key); if (rc) { cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); return rc; } rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); if (rc) cFYI(1, "%s Can't generate NTLM session key, error: %d", __func__, rc); return rc; }
int SyncedSDFileSystem::disk_initialize() { int ret; TCPSocketErr err; ret = SDFileSystem::disk_initialize(); dirty_ = vector<bool>(MAX_SYNCED_BLOCKS, false); block_md4_ = vector<struct block_hash>(MAX_SYNCED_BLOCKS); for (int i = 0; i < MAX_SYNCED_BLOCKS; ++i) { block_md4_[i].block_num = i; if (SDFileSystem::disk_read((char *)buffer_, i)) { // TODO: handle error } mdfour((unsigned char *) block_md4_[i].md4, buffer_, BLOCK_SIZE); } if (is_master_) { tcp_socket_->setOnEvent(this, &SyncedSDFileSystem::on_master_event); tcp_socket_->bind(Host(address_, SYNC_FS_PORT)); tcp_socket_->listen(); debug("MASTER: listening for connections"); } else { tcp_socket_->setOnEvent(this, &SyncedSDFileSystem::on_node_event); err = tcp_socket_->connect(Host(IpAddr(192, 168, 1, MASTER_ADDR), SYNC_FS_PORT)); if (err) { // TODO: retry master registration periodically tcp_socket_->close(); delete tcp_socket_; printf("SLAVE: failed to connect to master, entering standalone mode\n\r"); // TODO: handle offline mode by checking if tcp_socket_ == NULL } else { debug("SLAVE: connected to master"); } } return ret; }
void SyncedSDFileSystem::node_handle_update_block() { debug("SLAVE: handling UPDATE_BLOCK"); int ret; int block_num; ret = tcp_socket_->recv((char *) &block_num, sizeof(int)); if (ret != sizeof(int)) { // TODO: handle error } ret = tcp_socket_->recv((char *) buffer_, BLOCK_SIZE); if (ret != BLOCK_SIZE) { // TODO: handle error } ret = SDFileSystem::disk_write((char *)buffer_, block_num); if (ret) { // TODO: handle error } mdfour((unsigned char*)block_md4_[block_num].md4, buffer_, BLOCK_SIZE); dirty_[block_num] = false; }
static void SMBsesskeygen_ntv1(const unsigned char kr[16], const unsigned char *nt_resp, __u8 sess_key[16]) { mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16); }
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; }
/* samr_ChangePasswordUser3 */ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct samr_ChangePasswordUser3 *r) { NTSTATUS status; DATA_BLOB new_password; struct ldb_context *sam_ctx = NULL; struct ldb_dn *user_dn; int ret; struct ldb_message **res, *mod; const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL }; struct samr_Password *nt_pwd, *lm_pwd; DATA_BLOB nt_pwd_blob; struct samr_DomInfo1 *dominfo = NULL; struct samr_ChangeReject *reject = NULL; enum samr_RejectReason reason = SAMR_REJECT_OTHER; uint8_t new_nt_hash[16], new_lm_hash[16]; struct samr_Password nt_verifier, lm_verifier; *r->out.dominfo = NULL; *r->out.reject = NULL; if (r->in.nt_password == NULL || r->in.nt_verifier == NULL) { return NT_STATUS_INVALID_PARAMETER; } /* To change a password we need to open as system */ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx)); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } ret = ldb_transaction_start(sam_ctx); if (ret) { talloc_free(sam_ctx); DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); return NT_STATUS_TRANSACTION_ABORTED; } /* we need the users dn and the domain dn (derived from the user SID). We also need the current lm and nt password hashes in order to decrypt the incoming passwords */ ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs, "(&(sAMAccountName=%s)(objectclass=user))", r->in.account->string); if (ret != 1) { /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */ status = NT_STATUS_WRONG_PASSWORD; goto failed; } user_dn = res[0]->dn; status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, res[0], &lm_pwd, &nt_pwd); if (!NT_STATUS_IS_OK(status) ) { goto failed; } if (!nt_pwd) { status = NT_STATUS_WRONG_PASSWORD; goto failed; } /* decrypt the password we have been given */ nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash)); arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob); data_blob_free(&nt_pwd_blob); if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) { ldb_transaction_cancel(sam_ctx); DEBUG(3,("samr: failed to decode password buffer\n")); return NT_STATUS_WRONG_PASSWORD; } if (r->in.nt_verifier == NULL) { status = NT_STATUS_WRONG_PASSWORD; goto failed; } /* check NT verifier */ mdfour(new_nt_hash, new_password.data, new_password.length); E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash); if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) { status = NT_STATUS_WRONG_PASSWORD; goto failed; } /* check LM verifier (really not needed as we just checked the * much stronger NT hash, but the RPC-SAMR test checks for * this) */ if (lm_pwd && r->in.lm_verifier != NULL) { char *new_pass; if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), CH_UTF16, CH_UNIX, (const char *)new_password.data, new_password.length, (void **)&new_pass, NULL, false)) { E_deshash(new_pass, new_lm_hash); E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash); if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) { status = NT_STATUS_WRONG_PASSWORD; goto failed; } } } mod = ldb_msg_new(mem_ctx); if (mod == NULL) { status = NT_STATUS_NO_MEMORY; goto failed; } mod->dn = ldb_dn_copy(mod, user_dn); if (!mod->dn) { status = NT_STATUS_NO_MEMORY; goto failed; } /* set the password on the user DN specified. This may fail * due to password policies */ status = samdb_set_password(sam_ctx, mem_ctx, user_dn, NULL, mod, &new_password, NULL, NULL, true, /* this is a user password change */ &reason, &dominfo); if (!NT_STATUS_IS_OK(status)) { goto failed; } /* The above call only setup the modifications, this actually * makes the write to the database. */ ret = samdb_replace(sam_ctx, mem_ctx, mod); if (ret != 0) { DEBUG(2,("samdb_replace failed to change password for %s: %s\n", ldb_dn_get_linearized(user_dn), ldb_errstring(sam_ctx))); status = NT_STATUS_UNSUCCESSFUL; goto failed; } /* And this confirms it in a transaction commit */ ret = ldb_transaction_commit(sam_ctx); if (ret != 0) { DEBUG(1,("Failed to commit transaction to change password on %s: %s\n", ldb_dn_get_linearized(user_dn), ldb_errstring(sam_ctx))); status = NT_STATUS_TRANSACTION_ABORTED; goto failed; } return NT_STATUS_OK; failed: ldb_transaction_cancel(sam_ctx); talloc_free(sam_ctx); reject = talloc(mem_ctx, struct samr_ChangeReject); *r->out.dominfo = dominfo; *r->out.reject = reject; if (reject == NULL) { return status; } ZERO_STRUCTP(reject); reject->reason = reason; return status; }
/* samr_ChangePasswordUser3 */ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct samr_ChangePasswordUser3 *r) { NTSTATUS status; DATA_BLOB new_password; struct ldb_context *sam_ctx = NULL; struct ldb_dn *user_dn; int ret; struct ldb_message **res; const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL }; struct samr_Password *nt_pwd, *lm_pwd; DATA_BLOB nt_pwd_blob; struct samr_DomInfo1 *dominfo = NULL; struct userPwdChangeFailureInformation *reject = NULL; enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR; uint8_t new_nt_hash[16], new_lm_hash[16]; struct samr_Password nt_verifier, lm_verifier; *r->out.dominfo = NULL; *r->out.reject = NULL; if (r->in.nt_password == NULL || r->in.nt_verifier == NULL) { return NT_STATUS_INVALID_PARAMETER; } /* Connect to a SAMDB with system privileges for fetching the old pw * hashes. */ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } /* we need the users dn and the domain dn (derived from the user SID). We also need the current lm and nt password hashes in order to decrypt the incoming passwords */ ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs, "(&(sAMAccountName=%s)(objectclass=user))", r->in.account->string); if (ret != 1) { /* Don't give the game away: (don't allow anonymous users to prove the existance of usernames) */ status = NT_STATUS_WRONG_PASSWORD; goto failed; } user_dn = res[0]->dn; status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, res[0], &lm_pwd, &nt_pwd); if (!NT_STATUS_IS_OK(status) ) { goto failed; } if (!nt_pwd) { status = NT_STATUS_WRONG_PASSWORD; goto failed; } /* decrypt the password we have been given */ nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash)); arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob); data_blob_free(&nt_pwd_blob); if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) { DEBUG(3,("samr: failed to decode password buffer\n")); status = NT_STATUS_WRONG_PASSWORD; goto failed; } if (r->in.nt_verifier == NULL) { status = NT_STATUS_WRONG_PASSWORD; goto failed; } /* check NT verifier */ mdfour(new_nt_hash, new_password.data, new_password.length); E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash); if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) { status = NT_STATUS_WRONG_PASSWORD; goto failed; } /* check LM verifier (really not needed as we just checked the * much stronger NT hash, but the RPC-SAMR test checks for * this) */ if (lm_pwd && r->in.lm_verifier != NULL) { char *new_pass; if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), CH_UTF16, CH_UNIX, (const char *)new_password.data, new_password.length, (void **)&new_pass, NULL, false)) { E_deshash(new_pass, new_lm_hash); E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash); if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) { status = NT_STATUS_WRONG_PASSWORD; goto failed; } } } /* Connect to a SAMDB with user privileges for the password change */ sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, 0); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } ret = ldb_transaction_start(sam_ctx); if (ret != LDB_SUCCESS) { DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx))); return NT_STATUS_TRANSACTION_ABORTED; } /* Performs the password modification. We pass the old hashes read out * from the database since they were already checked against the user- * provided ones. */ status = samdb_set_password(sam_ctx, mem_ctx, user_dn, NULL, &new_password, NULL, NULL, lm_pwd, nt_pwd, /* this is a user password change */ &reason, &dominfo); if (!NT_STATUS_IS_OK(status)) { ldb_transaction_cancel(sam_ctx); goto failed; } /* And this confirms it in a transaction commit */ ret = ldb_transaction_commit(sam_ctx); if (ret != LDB_SUCCESS) { DEBUG(1,("Failed to commit transaction to change password on %s: %s\n", ldb_dn_get_linearized(user_dn), ldb_errstring(sam_ctx))); status = NT_STATUS_TRANSACTION_ABORTED; goto failed; } return NT_STATUS_OK; failed: reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation); if (reject != NULL) { reject->extendedFailureReason = reason; *r->out.reject = reject; } *r->out.dominfo = dominfo; return status; }
R_API ut8 *r_hash_do_md4(RHash *ctx, const ut8 *input, int len) { if (len<0) return NULL; mdfour (ctx->digest, input, len); return ctx->digest; }
void gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra) { dstring_t *cache, *fullpath; unsigned char model_digest[MDFOUR_DIGEST_BYTES]; unsigned char mesh_digest[MDFOUR_DIGEST_BYTES]; int i, j; int *cmds; QFile *f; qboolean remesh = true; qboolean do_cache = false; aliasmodel = m; paliashdr = hdr; cache = dstring_new (); fullpath = dstring_new (); if (!gl_alias_render_tri->int_val) { if (gl_mesh_cache->int_val && gl_mesh_cache->int_val <= paliashdr->mdl.numtris) { do_cache = true; mdfour (model_digest, (unsigned char *) _m, _s); // look for a cached version dstring_copystr (cache, "glquake/"); dstring_appendstr (cache, m->name); QFS_StripExtension (m->name + strlen ("progs/"), cache->str + strlen ("glquake/")); dstring_appendstr (cache, ".qfms"); QFS_FOpenFile (cache->str, &f); if (f) { unsigned char d1[MDFOUR_DIGEST_BYTES]; unsigned char d2[MDFOUR_DIGEST_BYTES]; struct mdfour md; int len, vers; int nc = 0, no = 0; int *c = 0, *vo = 0; memset (d1, 0, sizeof (d1)); memset (d2, 0, sizeof (d2)); Qread (f, &vers, sizeof (int)); Qread (f, &len, sizeof (int)); Qread (f, &nc, sizeof (int)); Qread (f, &no, sizeof (int)); if (vers == 1 && (nc + no) == len) { c = malloc (((nc + 1023) & ~1023) * sizeof (c[0])); vo = malloc (((no + 1023) & ~1023) * sizeof (vo[0])); if (!c || !vo) Sys_Error ("gl_mesh.c: out of memory"); Qread (f, c, nc * sizeof (c[0])); Qread (f, vo, no * sizeof (vo[0])); Qread (f, d1, MDFOUR_DIGEST_BYTES); Qread (f, d2, MDFOUR_DIGEST_BYTES); Qclose (f); mdfour_begin (&md); mdfour_update (&md, (unsigned char *) &vers, sizeof(int)); mdfour_update (&md, (unsigned char *) &len, sizeof(int)); mdfour_update (&md, (unsigned char *) &nc, sizeof(int)); mdfour_update (&md, (unsigned char *) &no, sizeof(int)); mdfour_update (&md, (unsigned char *) c, nc * sizeof (c[0])); mdfour_update (&md, (unsigned char *) vo, no * sizeof (vo[0])); mdfour_update (&md, d1, MDFOUR_DIGEST_BYTES); mdfour_result (&md, mesh_digest); if (memcmp (d2, mesh_digest, MDFOUR_DIGEST_BYTES) == 0 && memcmp (d1, model_digest, MDFOUR_DIGEST_BYTES) == 0) { remesh = false; numcommands = nc; numorder = no; if (numcommands > commands_size) { if (commands) free (commands); commands_size = (numcommands + 1023) & ~1023; commands = c; } else { memcpy (commands, c, numcommands * sizeof (c[0])); free(c); } if (numorder > vertexorder_size) { if (vertexorder) free (vertexorder); vertexorder_size = (numorder + 1023) & ~1023; vertexorder = vo; } else { memcpy (vertexorder, vo, numorder * sizeof (vo[0])); free (vo); } } } } } if (remesh) { // build it from scratch Sys_MaskPrintf (SYS_DEV, "meshing %s...\n", m->name); BuildTris (); // trifans or lists if (do_cache) { // save out the cached version dsprintf (fullpath, "%s/%s", qfs_gamedir->dir.def, cache->str); f = QFS_WOpen (fullpath->str, 9); if (f) { struct mdfour md; int vers = 1; int len = numcommands + numorder; mdfour_begin (&md); mdfour_update (&md, (unsigned char *) &vers, sizeof (int)); mdfour_update (&md, (unsigned char *) &len, sizeof (int)); mdfour_update (&md, (unsigned char *) &numcommands, sizeof (int)); mdfour_update (&md, (unsigned char *) &numorder, sizeof (int)); mdfour_update (&md, (unsigned char *) commands, numcommands * sizeof (commands[0])); mdfour_update (&md, (unsigned char *) vertexorder, numorder * sizeof (vertexorder[0])); mdfour_update (&md, model_digest, MDFOUR_DIGEST_BYTES); mdfour_result (&md, mesh_digest); Qwrite (f, &vers, sizeof (int)); Qwrite (f, &len, sizeof (int)); Qwrite (f, &numcommands, sizeof (int)); Qwrite (f, &numorder, sizeof (int)); Qwrite (f, commands, numcommands * sizeof (commands[0])); Qwrite (f, vertexorder, numorder * sizeof (vertexorder[0])); Qwrite (f, model_digest, MDFOUR_DIGEST_BYTES); Qwrite (f, mesh_digest, MDFOUR_DIGEST_BYTES); Qclose (f); } } } // save the data out paliashdr->poseverts = numorder; cmds = Hunk_Alloc (numcommands * sizeof (int)); paliashdr->commands = (byte *) cmds - (byte *) paliashdr; memcpy (cmds, commands, numcommands * sizeof (int)); } else { tex_coord_t *tex_coord; numorder = 0; for (i=0; i < pheader->mdl.numtris; i++) { add_vertex(triangles[i].vertindex[0]); add_vertex(triangles[i].vertindex[1]); add_vertex(triangles[i].vertindex[2]); } paliashdr->poseverts = numorder; tex_coord = Hunk_Alloc (numorder * sizeof(tex_coord_t)); paliashdr->tex_coord = (byte *) tex_coord - (byte *) paliashdr; for (i=0; i < numorder; i++) { float s, t; int k; k = vertexorder[i]; s = stverts[k].s; t = stverts[k].t; if (!triangles[i/3].facesfront && stverts[k].onseam) s += pheader->mdl.skinwidth / 2; // on back side s = (s + 0.5) / pheader->mdl.skinwidth; t = (t + 0.5) / pheader->mdl.skinheight; tex_coord[i].st[0] = s; tex_coord[i].st[1] = t; } } if (extra) { trivertx16_t *verts; verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof (trivertx16_t)); paliashdr->posedata = (byte *) verts - (byte *) paliashdr; for (i = 0; i < paliashdr->numposes; i++) { trivertx_t *pv = poseverts[i]; for (j = 0; j < numorder; j++) { trivertx16_t v; // convert MD16's split coordinates into something a little // saner. The first chunk of vertices is fully compatible with // IDPO alias models (even the scale). The second chunk is the // fractional bits of the vertex, giving 8.8. However, it's // easier for us to multiply everything by 256 and adjust the // model scale appropriately VectorMultAdd (pv[vertexorder[j] + hdr->mdl.numverts].v, 256, pv[vertexorder[j]].v, v.v); v.lightnormalindex = poseverts[i][vertexorder[j]].lightnormalindex; *verts++ = v; } } } else { trivertx_t *verts; verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof (trivertx_t)); paliashdr->posedata = (byte *) verts - (byte *) paliashdr; for (i = 0; i < paliashdr->numposes; i++) { for (j = 0; j < numorder; j++) *verts++ = poseverts[i][vertexorder[j]]; } } dstring_delete (cache); dstring_delete (fullpath); }
void Com_BlockFullChecksum(const void *buffer, int len, unsigned char *outbuf){ mdfour(outbuf,(unsigned char *) buffer, len); }
static int do_reseed(bool use_fd, int fd) { unsigned char seed_inbuf[40]; uint32 v1, v2; struct timeval tval; pid_t mypid; struct passwd *pw; int reseed_data = 0; if (use_fd) { if (fd != -1) return fd; fd = sys_open( "/dev/urandom", O_RDONLY,0); if(fd >= 0) return fd; } /* Add in some secret file contents */ do_filehash("/etc/shadow", &seed_inbuf[0]); do_filehash(lp_smb_passwd_file(), &seed_inbuf[16]); /* * Add in the root encrypted password. * On any system where security is taken * seriously this will be secret. */ pw = getpwnam_alloc(talloc_autofree_context(), "root"); if (pw && pw->pw_passwd) { size_t i; unsigned char md4_tmp[16]; mdfour(md4_tmp, (unsigned char *)pw->pw_passwd, strlen(pw->pw_passwd)); for (i=0;i<16;i++) seed_inbuf[8+i] ^= md4_tmp[i]; TALLOC_FREE(pw); } /* * Add the counter, time of day, and pid. */ GetTimeOfDay(&tval); mypid = sys_getpid(); v1 = (counter++) + mypid + tval.tv_sec; v2 = (counter++) * mypid + tval.tv_usec; SIVAL(seed_inbuf, 32, v1 ^ IVAL(seed_inbuf, 32)); SIVAL(seed_inbuf, 36, v2 ^ IVAL(seed_inbuf, 36)); /* * Add any user-given reseed data. */ get_rand_reseed_data(&reseed_data); if (reseed_data) { size_t i; for (i = 0; i < sizeof(seed_inbuf); i++) seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; } smb_arc4_init(smb_arc4_state, seed_inbuf, sizeof(seed_inbuf)); return -1; }
NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, bool lanman_auth, bool ntlm_auth, uint32_t logon_parameters, const DATA_BLOB *challenge, const DATA_BLOB *lm_response, const DATA_BLOB *nt_response, const char *username, const char *client_username, const char *client_domain, const struct samr_Password *stored_lanman, const struct samr_Password *stored_nt, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { const static uint8_t zeros[8]; DATA_BLOB tmp_sess_key; const char *upper_client_domain = NULL; if (client_domain != NULL) { upper_client_domain = talloc_strdup_upper(mem_ctx, client_domain); if (upper_client_domain == NULL) { return NT_STATUS_NO_MEMORY; } } if (stored_nt == NULL) { DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", username)); } *lm_sess_key = data_blob(NULL, 0); *user_sess_key = data_blob(NULL, 0); /* Check for cleartext netlogon. Used by Exchange 5.5. */ if ((logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_ALLOWED) && challenge->length == sizeof(zeros) && (memcmp(challenge->data, zeros, challenge->length) == 0 )) { struct samr_Password client_nt; struct samr_Password client_lm; char *unix_pw = NULL; bool lm_ok; size_t converted_size = 0; DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n", username)); mdfour(client_nt.hash, nt_response->data, nt_response->length); if (lm_response->length && (convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, lm_response->data, lm_response->length, (void *)&unix_pw, &converted_size))) { if (E_deshash(unix_pw, client_lm.hash)) { lm_ok = true; } else { lm_ok = false; } } else { lm_ok = false; } return hash_password_check(mem_ctx, lanman_auth, lm_ok ? &client_lm : NULL, nt_response->length ? &client_nt : NULL, username, stored_lanman, stored_nt); } 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 && stored_nt) { /* 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 ? client_domain : "<NULL>")); if (smb_pwd_check_ntlmv2(mem_ctx, nt_response, stored_nt->hash, challenge, client_username, client_domain, user_sess_key)) { if (user_sess_key->length) { *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", upper_client_domain ? upper_client_domain : "<NULL>")); if (smb_pwd_check_ntlmv2(mem_ctx, nt_response, stored_nt->hash, challenge, client_username, upper_client_domain, user_sess_key)) { if (user_sess_key->length) { *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n")); if (smb_pwd_check_ntlmv2(mem_ctx, nt_response, stored_nt->hash, challenge, client_username, "", user_sess_key)) { if (user_sess_key->length) { *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n")); } } else if (nt_response->length == 24 && stored_nt) { if (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(mem_ctx, nt_response, stored_nt->hash, 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 (lanman_auth && stored_lanman) { *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, MIN(8, user_sess_key->length)); } 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, because 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 (!lanman_auth) { DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n", username)); } else if (!stored_lanman) { DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n", username)); } else if (strchr_m(username, '@')) { DEBUG(3,("ntlm_password_check: NO LanMan password allowed for username@realm logins (user: %s)\n", username)); } else { DEBUG(4,("ntlm_password_check: Checking LM password\n")); if (smb_pwd_check_ntlmv1(mem_ctx, lm_response, stored_lanman->hash, 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 (lanman_auth && stored_lanman) { uint8_t first_8_lm_hash[16]; memcpy(first_8_lm_hash, stored_lanman->hash, 8); memset(first_8_lm_hash + 8, '\0', 8); *user_sess_key = data_blob_talloc(mem_ctx, first_8_lm_hash, 16); *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8); } return NT_STATUS_OK; } } if (!stored_nt) { 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 ? client_domain : "<NULL>")); if (smb_pwd_check_ntlmv2(mem_ctx, lm_response, stored_nt->hash, challenge, client_username, client_domain, &tmp_sess_key)) { if (nt_response->length > 24) { /* If NTLMv2 authentication has preceded us * (even if it failed), then use the session * key from that. See the RPC-SAMLOGON * torture test */ smb_sess_key_ntlmv2(mem_ctx, nt_response, stored_nt->hash, challenge, client_username, client_domain, user_sess_key); } else { /* Otherwise, use the LMv2 session key */ *user_sess_key = tmp_sess_key; } if (user_sess_key->length) { *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", upper_client_domain ? upper_client_domain : "<NULL>")); if (smb_pwd_check_ntlmv2(mem_ctx, lm_response, stored_nt->hash, challenge, client_username, upper_client_domain, &tmp_sess_key)) { if (nt_response->length > 24) { /* If NTLMv2 authentication has preceded us * (even if it failed), then use the session * key from that. See the RPC-SAMLOGON * torture test */ smb_sess_key_ntlmv2(mem_ctx, nt_response, stored_nt->hash, challenge, client_username, upper_client_domain, user_sess_key); } else { /* Otherwise, use the LMv2 session key */ *user_sess_key = tmp_sess_key; } if (user_sess_key->length) { *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } return NT_STATUS_OK; } DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n")); if (smb_pwd_check_ntlmv2(mem_ctx, lm_response, stored_nt->hash, challenge, client_username, "", &tmp_sess_key)) { if (nt_response->length > 24) { /* If NTLMv2 authentication has preceded us * (even if it failed), then use the session * key from that. See the RPC-SAMLOGON * torture test */ smb_sess_key_ntlmv2(mem_ctx, nt_response, stored_nt->hash, challenge, client_username, "", user_sess_key); } else { /* Otherwise, use the LMv2 session key */ *user_sess_key = tmp_sess_key; } if (user_sess_key->length) { *lm_sess_key = data_blob_talloc(mem_ctx, user_sess_key->data, MIN(8, user_sess_key->length)); } 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 (ntlm_auth) { if (smb_pwd_check_ntlmv1(mem_ctx, lm_response, stored_nt->hash, 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 (lanman_auth && stored_lanman) { uint8_t first_8_lm_hash[16]; memcpy(first_8_lm_hash, stored_lanman->hash, 8); memset(first_8_lm_hash + 8, '\0', 8); *user_sess_key = data_blob_talloc(mem_ctx, first_8_lm_hash, 16); *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8); } 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)); } /* Try and match error codes */ if (strchr_m(username, '@')) { return NT_STATUS_NOT_FOUND; } return NT_STATUS_WRONG_PASSWORD; }