diff options
-rw-r--r-- | source3/libsmb/cliconnect.c | 15 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp.c | 10 | ||||
-rw-r--r-- | source3/libsmb/smbencrypt.c | 112 | ||||
-rw-r--r-- | source3/utils/ntlm_auth.c | 113 |
4 files changed, 131 insertions, 119 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 982cbfff06..f58a458aba 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -257,14 +257,23 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, if (passlen != 24) { if (lp_client_ntlmv2_auth()) { DATA_BLOB server_chal; - + DATA_BLOB names_blob; server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); - if (!SMBNTLMv2encrypt(user, workgroup, pass, server_chal, - &lm_response, &nt_response, NULL, &session_key)) { + /* note that the 'workgroup' here is a best guess - we don't know + the server's domain at this point. The 'server name' is also + dodgy... + */ + names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup); + + if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal, + &names_blob, + &lm_response, &nt_response, &session_key)) { + data_blob_free(&names_blob); data_blob_free(&server_chal); return False; } + data_blob_free(&names_blob); data_blob_free(&server_chal); } else { diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 356bb0c4fe..636e384e65 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -487,9 +487,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st } SAFE_FREE(server_domain); - data_blob_free(&struct_blob); - if (challenge_blob.length != 8) { + data_blob_free(&struct_blob); return NT_STATUS_INVALID_PARAMETER; } @@ -500,9 +499,11 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st if (!SMBNTLMv2encrypt(ntlmssp_state->user, ntlmssp_state->domain, - ntlmssp_state->password, challenge_blob, - &lm_response, &nt_response, NULL, &session_key)) { + ntlmssp_state->password, &challenge_blob, + &struct_blob, + &lm_response, &nt_response, &session_key)) { data_blob_free(&challenge_blob); + data_blob_free(&struct_blob); return NT_STATUS_NO_MEMORY; } } else { @@ -522,6 +523,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st session_key = data_blob(NULL, 16); SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); } + data_blob_free(&struct_blob); /* this generates the actual auth packet */ if (!msrpc_gen(next_request, auth_gen_string, diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index bab18a07b1..c1b3880299 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -249,21 +249,21 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[ /* Does the md5 encryption from the NT hash for NTLMv2. */ void SMBOWFencrypt_ntv2(const uchar kr[16], - const DATA_BLOB srv_chal, - const DATA_BLOB cli_chal, + const DATA_BLOB *srv_chal, + const DATA_BLOB *cli_chal, uchar resp_buf[16]) { HMACMD5Context ctx; hmac_md5_init_limK_to_64(kr, 16, &ctx); - hmac_md5_update(srv_chal.data, srv_chal.length, &ctx); - hmac_md5_update(cli_chal.data, cli_chal.length, &ctx); + hmac_md5_update(srv_chal->data, srv_chal->length, &ctx); + hmac_md5_update(cli_chal->data, cli_chal->length, &ctx); hmac_md5_final(resp_buf, &ctx); #ifdef DEBUG_PASSWORD DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n")); - dump_data(100, srv_chal.data, srv_chal.length); - dump_data(100, cli_chal.data, cli_chal.length); + dump_data(100, srv_chal->data, srv_chal->length); + dump_data(100, cli_chal->data, cli_chal->length); dump_data(100, resp_buf, 16); #endif } @@ -294,36 +294,98 @@ void SMBsesskeygen_ntv1(const uchar kr[16], #endif } -static DATA_BLOB NTLMv2_generate_response(uchar ntlm_v2_hash[16], - DATA_BLOB server_chal, size_t client_chal_length) +DATA_BLOB NTLMv2_generate_names_blob(const char *hostname, + const char *domain) +{ + DATA_BLOB names_blob = data_blob(NULL, 0); + + msrpc_gen(&names_blob, "aaa", + True, NTLMSSP_NAME_TYPE_DOMAIN, domain, + True, NTLMSSP_NAME_TYPE_SERVER, hostname, + True, 0, ""); + return names_blob; +} + +static DATA_BLOB NTLMv2_generate_client_data(const DATA_BLOB *names_blob) +{ + uchar client_chal[8]; + DATA_BLOB response = data_blob(NULL, 0); + char long_date[8]; + + generate_random_buffer(client_chal, sizeof(client_chal), False); + + put_long_date(long_date, time(NULL)); + + /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */ + + msrpc_gen(&response, "ddbbdb", + 0x00000101, /* Header */ + 0, /* 'Reserved' */ + long_date, 8, /* Timestamp */ + client_chal, 8, /* client challenge */ + 0, /* Unknown */ + names_blob->data, names_blob->length); /* End of name list */ + + return response; +} + +static DATA_BLOB NTLMv2_generate_response(const uchar ntlm_v2_hash[16], + const DATA_BLOB *server_chal, + const DATA_BLOB *names_blob) { uchar ntlmv2_response[16]; DATA_BLOB ntlmv2_client_data; DATA_BLOB final_response; /* NTLMv2 */ + /* generate some data to pass into the response function - including + the hostname and domain name of the server */ + ntlmv2_client_data = NTLMv2_generate_client_data(names_blob); - /* We also get to specify some random data */ - ntlmv2_client_data = data_blob(NULL, client_chal_length); - generate_random_buffer(ntlmv2_client_data.data, ntlmv2_client_data.length, False); - /* Given that data, and the challenge from the server, generate a response */ - SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, ntlmv2_client_data, ntlmv2_response); + SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response); - /* put it into nt_response, for the code below to put into the packet */ - final_response = data_blob(NULL, ntlmv2_client_data.length + sizeof(ntlmv2_response)); + final_response = data_blob(NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length); + memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response)); - /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */ - memcpy(final_response.data + sizeof(ntlmv2_response), ntlmv2_client_data.data, ntlmv2_client_data.length); + + memcpy(final_response.data+sizeof(ntlmv2_response), + ntlmv2_client_data.data, ntlmv2_client_data.length); + data_blob_free(&ntlmv2_client_data); return final_response; } +static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16], + const DATA_BLOB *server_chal) +{ + uchar lmv2_response[16]; + DATA_BLOB lmv2_client_data = data_blob(NULL, 8); + DATA_BLOB final_response = data_blob(NULL, 24); + + /* LMv2 */ + /* client-supplied random data */ + generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length, False); + + /* Given that data, and the challenge from the server, generate a response */ + SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response); + memcpy(final_response.data, lmv2_response, sizeof(lmv2_response)); + + /* after the first 16 bytes is the random data we generated above, + so the server can verify us with it */ + memcpy(final_response.data+sizeof(lmv2_response), + lmv2_client_data.data, lmv2_client_data.length); + + data_blob_free(&lmv2_client_data); + + return final_response; +} + BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, - const DATA_BLOB server_chal, + const DATA_BLOB *server_chal, + const DATA_BLOB *names_blob, DATA_BLOB *lm_response, DATA_BLOB *nt_response, - DATA_BLOB *lm_session_key, DATA_BLOB *nt_session_key) { uchar nt_hash[16]; @@ -339,7 +401,8 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password } if (nt_response) { - *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, 64 /* pick a number, > 8 */); + *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, + names_blob); if (nt_session_key) { *nt_session_key = data_blob(NULL, 16); @@ -352,14 +415,7 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password /* LMv2 */ if (lm_response) { - *lm_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, 8); - if (lm_session_key) { - *lm_session_key = data_blob(NULL, 16); - - /* The NTLMv2 calculations also provide a session key, for signing etc later */ - /* use only the first 16 bytes of nt_response for session key */ - SMBsesskeygen_ntv2(ntlm_v2_hash, lm_response->data, lm_session_key->data); - } + *lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal); } return True; diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index fda4869f36..a713f3aa2d 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -832,26 +832,25 @@ static BOOL test_ntlmv2(void) NTSTATUS nt_status; uint32 flags = 0; DATA_BLOB ntlmv2_response = data_blob(NULL, 0); - DATA_BLOB lmv2_response = data_blob(NULL, 0); DATA_BLOB nt_session_key = data_blob(NULL, 0); - DATA_BLOB lm_session_key = data_blob(NULL, 0); + DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain()); - uchar lm_key[16]; uchar nt_key[16]; DATA_BLOB chall = get_challenge(); char *error_string; - ZERO_STRUCT(lm_key); ZERO_STRUCT(nt_key); - flags |= WINBIND_PAM_LMKEY; flags |= WINBIND_PAM_NTKEY; - if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, chall, - &lmv2_response, &ntlmv2_response, - &lm_session_key, &nt_session_key)) { + if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + &names_blob, + NULL, &ntlmv2_response, + &nt_session_key)) { + data_blob_free(&names_blob); return False; } + data_blob_free(&names_blob); nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, @@ -859,11 +858,10 @@ static BOOL test_ntlmv2(void) NULL, &ntlmv2_response, flags, - lm_key, + NULL, nt_key, &error_string); - data_blob_free(&lmv2_response); data_blob_free(&ntlmv2_response); if (!NT_STATUS_IS_OK(nt_status)) { @@ -874,16 +872,6 @@ static BOOL test_ntlmv2(void) return False; } -#if 0 - if (memcmp(lm_session_key.data, lm_key, - sizeof(lm_key)) != 0) { - DEBUG(1, ("LM Session Key does not match expectations!\n")); - DEBUG(1, ("lm_key:\n")); - dump_data(1, lm_key, 16); - DEBUG(1, ("expected:\n")); - dump_data(1, lm_session_key.data, lm_session_key.length); - pass = False; - } if (memcmp(nt_session_key.data, nt_key, sizeof(nt_key)) != 0) { DEBUG(1, ("NT Session Key does not match expectations!\n")); @@ -893,7 +881,6 @@ static BOOL test_ntlmv2(void) dump_data(1, nt_session_key.data, nt_session_key.length); pass = False; } -#endif return pass; } @@ -909,24 +896,24 @@ static BOOL test_lmv2_ntlmv2(void) DATA_BLOB ntlmv2_response = data_blob(NULL, 0); DATA_BLOB lmv2_response = data_blob(NULL, 0); DATA_BLOB nt_session_key = data_blob(NULL, 0); - DATA_BLOB lm_session_key = data_blob(NULL, 0); + DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain()); - uchar lm_key[16]; uchar nt_key[16]; DATA_BLOB chall = get_challenge(); char *error_string; ZERO_STRUCT(nt_key); - ZERO_STRUCT(lm_key); - flags |= WINBIND_PAM_LMKEY; flags |= WINBIND_PAM_NTKEY; - if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, chall, + if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + &names_blob, &lmv2_response, &ntlmv2_response, - &lm_session_key, &nt_session_key)) { + &nt_session_key)) { + data_blob_free(&names_blob); return False; } + data_blob_free(&names_blob); nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, @@ -934,7 +921,7 @@ static BOOL test_lmv2_ntlmv2(void) &lmv2_response, &ntlmv2_response, flags, - lm_key, + NULL, nt_key, &error_string); @@ -949,16 +936,6 @@ static BOOL test_lmv2_ntlmv2(void) return False; } -#if 0 - if (memcmp(lm_session_key.data, lm_key, - sizeof(lm_key)) != 0) { - DEBUG(1, ("LM Session Key does not match expectations!\n")); - DEBUG(1, ("lm_key:\n")); - dump_data(1, lm_key, 16); - DEBUG(1, ("expected:\n")); - dump_data(1, lm_session_key.data, lm_session_key.length); - pass = False; - } if (memcmp(nt_session_key.data, nt_key, sizeof(nt_key)) != 0) { DEBUG(1, ("NT Session Key does not match expectations!\n")); @@ -968,7 +945,6 @@ static BOOL test_lmv2_ntlmv2(void) dump_data(1, nt_session_key.data, nt_session_key.length); pass = False; } -#endif return pass; } @@ -981,25 +957,15 @@ static BOOL test_lmv2(void) BOOL pass = True; NTSTATUS nt_status; uint32 flags = 0; - DATA_BLOB ntlmv2_response = data_blob(NULL, 0); DATA_BLOB lmv2_response = data_blob(NULL, 0); - DATA_BLOB nt_session_key = data_blob(NULL, 0); - DATA_BLOB lm_session_key = data_blob(NULL, 0); - uchar lm_key[16]; - uchar nt_key[16]; DATA_BLOB chall = get_challenge(); char *error_string; - ZERO_STRUCT(nt_key); - ZERO_STRUCT(lm_key); - - flags |= WINBIND_PAM_LMKEY; - flags |= WINBIND_PAM_NTKEY; - - if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, chall, - &lmv2_response, &ntlmv2_response, - &lm_session_key, &nt_session_key)) { + if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + NULL, + &lmv2_response, NULL, + NULL)) { return False; } @@ -1009,12 +975,11 @@ static BOOL test_lmv2(void) &lmv2_response, NULL, flags, - lm_key, - nt_key, + NULL, + NULL, &error_string); data_blob_free(&lmv2_response); - data_blob_free(&ntlmv2_response); if (!NT_STATUS_IS_OK(nt_status)) { d_printf("%s (0x%x)\n", @@ -1024,26 +989,6 @@ static BOOL test_lmv2(void) return False; } -#if 0 - if (memcmp(lm_session_key.data, lm_key, - sizeof(lm_key)) != 0) { - DEBUG(1, ("LM Session Key does not match expectations!\n")); - DEBUG(1, ("lm_key:\n")); - dump_data(1, lm_key, 16); - DEBUG(1, ("expected:\n")); - dump_data(1, lm_session_key.data, lm_session_key.length); - pass = False; - } - if (memcmp(nt_session_key.data, nt_key, - sizeof(nt_key)) != 0) { - DEBUG(1, ("NT Session Key does not match expectations!\n")); - DEBUG(1, ("nt_key:\n")); - dump_data(1, nt_key, 16); - DEBUG(1, ("expected:\n")); - dump_data(1, nt_session_key.data, nt_session_key.length); - pass = False; - } -#endif return pass; } @@ -1145,24 +1090,24 @@ static BOOL test_ntlmv2_broken(BOOL break_lmv2) DATA_BLOB ntlmv2_response = data_blob(NULL, 0); DATA_BLOB lmv2_response = data_blob(NULL, 0); DATA_BLOB nt_session_key = data_blob(NULL, 0); - DATA_BLOB lm_session_key = data_blob(NULL, 0); + DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain()); - uchar lm_key[16]; uchar nt_key[16]; DATA_BLOB chall = get_challenge(); char *error_string; ZERO_STRUCT(nt_key); - ZERO_STRUCT(lm_key); - flags |= WINBIND_PAM_LMKEY; flags |= WINBIND_PAM_NTKEY; - - if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, chall, + + if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + &names_blob, &lmv2_response, &ntlmv2_response, - &lm_session_key, &nt_session_key)) { + &nt_session_key)) { + data_blob_free(&names_blob); return False; } + data_blob_free(&names_blob); /* Heh - this should break the appropriate password hash nicely! */ @@ -1177,7 +1122,7 @@ static BOOL test_ntlmv2_broken(BOOL break_lmv2) &lmv2_response, &ntlmv2_response, flags, - lm_key, + NULL, nt_key, &error_string); |