diff options
Diffstat (limited to 'source3/libsmb/ntlmssp.c')
-rw-r--r-- | source3/libsmb/ntlmssp.c | 102 |
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; } |