summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/libsmb/cliconnect.c15
-rw-r--r--source3/libsmb/ntlmssp.c10
-rw-r--r--source3/libsmb/smbencrypt.c112
-rw-r--r--source3/utils/ntlm_auth.c113
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);