summaryrefslogtreecommitdiff
path: root/source3/libsmb/ntlmssp.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb/ntlmssp.c')
-rw-r--r--source3/libsmb/ntlmssp.c102
1 files changed, 80 insertions, 22 deletions
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
index a50ae9b70f..42bf18d1d2 100644
--- a/source3/libsmb/ntlmssp.c
+++ b/source3/libsmb/ntlmssp.c
@@ -140,7 +140,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
&cliname,
&domname)) {
DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n"));
- dump_data(2, request.data, request.length);
+ dump_data(2, (const char *)request.data, request.length);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -172,6 +172,9 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
target_name = ntlmssp_target_name(ntlmssp_state,
neg_flags, &chal_flags);
+ if (target_name == NULL)
+ return NT_STATUS_INVALID_PARAMETER;
+
/* This should be a 'netbios domain -> DNS domain' mapping */
dnsdomname[0] = '\0';
get_mydomname(dnsdomname);
@@ -273,7 +276,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
&sess_key,
&neg_flags)) {
DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
- dump_data(2, request.data, request.length);
+ dump_data(2, (const char *)request.data, request.length);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -412,6 +415,8 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat
if (ntlmssp_state->use_ntlmv2) {
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
}
+
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
/* generate the ntlmssp negotiate packet */
msrpc_gen(next_request, "CddAA",
@@ -446,16 +451,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
DATA_BLOB lm_response = data_blob(NULL, 0);
DATA_BLOB nt_response = data_blob(NULL, 0);
DATA_BLOB session_key = data_blob(NULL, 0);
- uint8 datagram_sess_key[16];
- size_t datagram_sess_key_len;
-
-#if 0 /* until we know what flag to tigger it on */
- generate_random_buffer(datagram_sess_key, sizeof(datagram_sess_key), False);
- datagram_sess_key_len = sizeof(datagram_sess_key);
-#else
- ZERO_STRUCT(datagram_sess_key);
- datagram_sess_key_len = 0;
-#endif
+ DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
if (!msrpc_parse(&reply, "CdBd",
"NTLMSSP",
@@ -463,7 +459,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
&server_domain_blob,
&chal_flags)) {
DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
- dump_data(2, reply.data, reply.length);
+ dump_data(2, (const char *)reply.data, reply.length);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -489,7 +485,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
} else {
chal_parse_string = "CdAdbdd";
}
+
auth_gen_string = "CdBBAAABd";
+
ntlmssp_state->unicode = False;
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE;
ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
@@ -513,6 +511,10 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
}
+ if (!(chal_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
+ }
+
DEBUG(3, ("NTLMSSP: Set final flags:\n"));
debug_ntlmssp_flags(ntlmssp_state->neg_flags);
@@ -525,17 +527,22 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
&unkn1, &unkn2,
&struct_blob)) {
DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
- dump_data(2, reply.data, reply.length);
+ dump_data(2, (const char *)reply.data, reply.length);
return NT_STATUS_INVALID_PARAMETER;
}
+ ntlmssp_state->server_domain = talloc_strdup(ntlmssp_state->mem_ctx,
+ server_domain);
+
SAFE_FREE(server_domain);
if (challenge_blob.length != 8) {
data_blob_free(&struct_blob);
return NT_STATUS_INVALID_PARAMETER;
}
- if (ntlmssp_state->use_ntlmv2) {
+ if (!ntlmssp_state->password) {
+ /* do nothing - blobs are zero length */
+ } else if (ntlmssp_state->use_ntlmv2) {
if (!struct_blob.length) {
/* be lazy, match win2k - we can't do NTLMv2 without it */
@@ -554,7 +561,38 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
data_blob_free(&struct_blob);
return NT_STATUS_NO_MEMORY;
}
+ } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+ struct MD5Context md5_session_nonce_ctx;
+ uchar nt_hash[16];
+ uchar session_nonce[16];
+ uchar session_nonce_hash[16];
+ uchar nt_session_key[16];
+ E_md4hash(ntlmssp_state->password, nt_hash);
+
+ lm_response = data_blob(NULL, 24);
+ generate_random_buffer(lm_response.data, 8, False);
+ memset(lm_response.data+8, 0, 16);
+
+ memcpy(session_nonce, challenge_blob.data, 8);
+ memcpy(&session_nonce[8], lm_response.data, 8);
+
+ MD5Init(&md5_session_nonce_ctx);
+ MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
+ MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
+ MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
+
+ nt_response = data_blob(NULL, 24);
+ SMBNTencrypt(ntlmssp_state->password,
+ session_nonce_hash,
+ nt_response.data);
+
+ session_key = data_blob(NULL, 16);
+
+ SMBsesskeygen_ntv1(nt_hash, NULL, nt_session_key);
+ hmac_md5(nt_session_key, session_nonce, sizeof(session_nonce), session_key.data);
} else {
+
+
uchar lm_hash[16];
uchar nt_hash[16];
E_deshash(ntlmssp_state->password, lm_hash);
@@ -565,15 +603,15 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
lm_response = data_blob(NULL, 24);
SMBencrypt(ntlmssp_state->password,challenge_blob.data,
lm_response.data);
- }
+ }
nt_response = data_blob(NULL, 24);
SMBNTencrypt(ntlmssp_state->password,challenge_blob.data,
nt_response.data);
-
+
session_key = data_blob(NULL, 16);
if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
- && lp_client_lanman_auth()) {
+ && lp_client_lanman_auth()) {
SMBsesskeygen_lmv1(lm_hash, lm_response.data,
session_key.data);
} else {
@@ -582,6 +620,18 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
}
data_blob_free(&struct_blob);
+ /* Key exchange encryptes a new client-generated session key with
+ the password-derived key */
+ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+ uint8 client_session_key[16];
+
+ generate_random_buffer(client_session_key, sizeof(client_session_key), False);
+ encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
+ SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
+ data_blob_free(&session_key);
+ session_key = data_blob(client_session_key, sizeof(client_session_key));
+ }
+
/* this generates the actual auth packet */
if (!msrpc_gen(next_request, auth_gen_string,
"NTLMSSP",
@@ -591,7 +641,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
ntlmssp_state->domain,
ntlmssp_state->user,
ntlmssp_state->get_global_myname(),
- datagram_sess_key, datagram_sess_key_len,
+ encrypted_session_key.data, encrypted_session_key.length,
ntlmssp_state->neg_flags)) {
data_blob_free(&lm_response);
@@ -600,6 +650,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
return NT_STATUS_NO_MEMORY;
}
+ data_blob_free(&encrypted_session_key);
+
data_blob_free(&ntlmssp_state->chal);
data_blob_free(&ntlmssp_state->lm_resp);
data_blob_free(&ntlmssp_state->nt_resp);
@@ -638,6 +690,8 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state)
(*ntlmssp_state)->neg_flags =
NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_NEGOTIATE_NTLM2 |
+ NTLMSSP_NEGOTIATE_KEY_EXCH |
NTLMSSP_REQUEST_TARGET;
(*ntlmssp_state)->ref_count = 1;
@@ -706,9 +760,13 @@ NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *u
NTSTATUS ntlmssp_set_password(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *password)
{
- ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
- if (!ntlmssp_state->password) {
- return NT_STATUS_NO_MEMORY;
+ if (!password) {
+ ntlmssp_state->password = NULL;
+ } else {
+ ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password);
+ if (!ntlmssp_state->password) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
return NT_STATUS_OK;
}