From 58fe4d9c20203f6f55c8e995402e156becb91b3e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 15 Jan 2003 12:52:38 +0000 Subject: Refactor the NTLMSSP code again - this time we use function pointers to eliminate the dependency on the auth subsystem. The next step is to add the required code to 'ntlm_auth', for export to Squid etc. Andrew Bartlett (This used to be commit 9e48ab86da40e4c1cafa70c04fb9ebdcce23dfab) --- source3/libsmb/ntlmssp.c | 278 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 source3/libsmb/ntlmssp.c (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c new file mode 100644 index 0000000000..4183f3e77a --- /dev/null +++ b/source3/libsmb/ntlmssp.c @@ -0,0 +1,278 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + handle NLTMSSP, server side + + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2001-2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + * Default challange generation code. + * + */ + + +static const uint8 *get_challenge(void *cookie) +{ + static uchar chal[8]; + generate_random_buffer(chal, sizeof(chal), False); + + return chal; +} + +NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_init("NTLMSSP context"); + + *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state)); + if (!*ntlmssp_state) { + DEBUG(0,("ntlmssp_start: talloc failed!\n")); + talloc_destroy(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + ZERO_STRUCTP(*ntlmssp_state); + + (*ntlmssp_state)->mem_ctx = mem_ctx; + (*ntlmssp_state)->get_challenge = get_challenge; + + (*ntlmssp_state)->get_global_myname = global_myname; + (*ntlmssp_state)->get_domain = lp_workgroup; + + return NT_STATUS_OK; +} + +NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; + + data_blob_free(&(*ntlmssp_state)->lm_resp); + data_blob_free(&(*ntlmssp_state)->nt_resp); + + SAFE_FREE((*ntlmssp_state)->user); + SAFE_FREE((*ntlmssp_state)->domain); + SAFE_FREE((*ntlmssp_state)->workstation); + + talloc_destroy(mem_ctx); + *ntlmssp_state = NULL; + return NT_STATUS_OK; +} + +NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, + DATA_BLOB request, DATA_BLOB *reply) +{ + uint32 ntlmssp_command; + + if (!msrpc_parse(&request, "Cd", + "NTLMSSP", + &ntlmssp_command)) { + return NT_STATUS_LOGON_FAILURE; + } + + if (ntlmssp_command == NTLMSSP_NEGOTIATE) { + return ntlmssp_negotiate(ntlmssp_state, request, reply); + } else if (ntlmssp_command == NTLMSSP_AUTH) { + return ntlmssp_auth(ntlmssp_state, request, reply); + } else { + return NT_STATUS_LOGON_FAILURE; + } +} + +static const char *ntlmssp_target_name(NTLMSSP_STATE *ntlmssp_state, + uint32 neg_flags, uint32 *chal_flags) +{ + if (neg_flags & NTLMSSP_REQUEST_TARGET) { + *chal_flags |= NTLMSSP_CHAL_TARGET_INFO; + *chal_flags |= NTLMSSP_REQUEST_TARGET; + if (lp_server_role() == ROLE_STANDALONE) { + *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER; + return ntlmssp_state->get_global_myname(); + } else { + *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN; + return ntlmssp_state->get_domain(); + }; + } else { + return ""; + } +} + +NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state, + DATA_BLOB request, DATA_BLOB *reply) +{ + DATA_BLOB struct_blob; + fstring dnsname, dnsdomname; + uint32 ntlmssp_command, neg_flags, chal_flags; + char *cliname=NULL, *domname=NULL; + const uint8 *cryptkey; + const char *target_name; + + /* parse the NTLMSSP packet */ +#if 0 + file_save("ntlmssp_negotiate.dat", request.data, request.length); +#endif + + if (!msrpc_parse(&request, "CddAA", + "NTLMSSP", + &ntlmssp_command, + &neg_flags, + &cliname, + &domname)) { + return NT_STATUS_LOGON_FAILURE; + } + + SAFE_FREE(cliname); + SAFE_FREE(domname); + + debug_ntlmssp_flags(neg_flags); + + cryptkey = ntlmssp_state->get_challenge(ntlmssp_state->auth_context); + + /* Give them the challenge. For now, ignore neg_flags and just + return the flags we want. Obviously this is not correct */ + + chal_flags = + NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_NTLM; + + if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { + chal_flags |= NTLMSSP_NEGOTIATE_UNICODE; + ntlmssp_state->unicode = True; + } else { + chal_flags |= NTLMSSP_NEGOTIATE_OEM; + } + + target_name = ntlmssp_target_name(ntlmssp_state, + neg_flags, &chal_flags); + + /* This should be a 'netbios domain -> DNS domain' mapping */ + dnsdomname[0] = '\0'; + get_mydomname(dnsdomname); + strlower(dnsdomname); + + dnsname[0] = '\0'; + get_myfullname(dnsname); + strlower(dnsname); + + if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) + { + const char *target_name_dns = ""; + if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) { + target_name_dns = dnsdomname; + } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) { + target_name_dns = dnsname; + } + + /* the numbers here are the string type flags */ + msrpc_gen(&struct_blob, "aaaaa", + ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN, target_name, + ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), + ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN_DNS, target_name_dns, + ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER_DNS, dnsdomname, + ntlmssp_state->unicode, 0, ""); + } else { + struct_blob = data_blob(NULL, 0); + } + + { + const char *gen_string; + if (ntlmssp_state->unicode) { + gen_string = "CdUdbddB"; + } else { + gen_string = "CdAdbddB"; + } + + msrpc_gen(reply, gen_string, + "NTLMSSP", + NTLMSSP_CHALLENGE, + target_name, + chal_flags, + cryptkey, 8, + 0, 0, + struct_blob.data, struct_blob.length); + } + + data_blob_free(&struct_blob); + + return NT_STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state, + DATA_BLOB request, DATA_BLOB *reply) +{ + DATA_BLOB sess_key; + uint32 ntlmssp_command, neg_flags; + NTSTATUS nt_status; + + const char *parse_string; + + /* parse the NTLMSSP packet */ +#if 0 + file_save("ntlmssp_auth.dat", request.data, request.length); +#endif + + if (ntlmssp_state->unicode) { + parse_string = "CdBBUUUBd"; + } else { + parse_string = "CdBBAAABd"; + } + + data_blob_free(&ntlmssp_state->lm_resp); + data_blob_free(&ntlmssp_state->nt_resp); + + SAFE_FREE(ntlmssp_state->user); + SAFE_FREE(ntlmssp_state->domain); + SAFE_FREE(ntlmssp_state->workstation); + + /* now the NTLMSSP encoded auth hashes */ + if (!msrpc_parse(&request, parse_string, + "NTLMSSP", + &ntlmssp_command, + &ntlmssp_state->lm_resp, + &ntlmssp_state->nt_resp, + &ntlmssp_state->domain, + &ntlmssp_state->user, + &ntlmssp_state->workstation, + &sess_key, + &neg_flags)) { + return NT_STATUS_LOGON_FAILURE; + } + + data_blob_free(&sess_key); + + DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%d len2=%d\n", + ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, ntlmssp_state->lm_resp.length, ntlmssp_state->nt_resp.length)); + +#if 0 + file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length); + file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length); +#endif + + nt_status = ntlmssp_state->check_password(ntlmssp_state->auth_context); + + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + *reply = data_blob(NULL, 0); + + return nt_status; +} -- cgit From d456bec06ef5f59e3b20907679a4f5783a3da45e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 15 Jan 2003 20:39:33 +0000 Subject: Missed auth_ntlmssp.c in last night's checkin. Also keep track of the current challenge in the NTLMSSP context. Andrew Bartlett (This used to be commit ba13e058d4533b1ffba723b9e98e95090ad63d85) --- source3/libsmb/ntlmssp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 4183f3e77a..21f3612034 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -65,6 +65,7 @@ NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state) { TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; + data_blob_free(&(*ntlmssp_state)->chal); data_blob_free(&(*ntlmssp_state)->lm_resp); data_blob_free(&(*ntlmssp_state)->nt_resp); @@ -146,6 +147,9 @@ NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state, cryptkey = ntlmssp_state->get_challenge(ntlmssp_state->auth_context); + data_blob_free(&ntlmssp_state->chal); + ntlmssp_state->chal = data_blob(cryptkey, 8); + /* Give them the challenge. For now, ignore neg_flags and just return the flags we want. Obviously this is not correct */ -- cgit From 30ddea1f05a83cde1dc3ef72583ec7ba04d1d013 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 16 Jan 2003 04:40:07 +0000 Subject: (missed in last commit) Change the 'cookie' to be the ntlmssp_context, and use the 'auth_context' on that to store the cookie. Ensures that simple callbacks can 'just work'. Also make it clear that we are doing a pull_string into a pstring, not just any sized buffer. Andrew Bartlett (This used to be commit c7793f27188e658b7fc6336aa51d367eab36fc17) --- source3/libsmb/ntlmssp.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 21f3612034..6837674736 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -29,7 +29,7 @@ */ -static const uint8 *get_challenge(void *cookie) +static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state) { static uchar chal[8]; generate_random_buffer(chal, sizeof(chal), False); @@ -57,6 +57,7 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) (*ntlmssp_state)->get_global_myname = global_myname; (*ntlmssp_state)->get_domain = lp_workgroup; + (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */ return NT_STATUS_OK; } @@ -82,10 +83,12 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, DATA_BLOB request, DATA_BLOB *reply) { uint32 ntlmssp_command; - + *reply = data_blob(NULL, 0); + if (!msrpc_parse(&request, "Cd", "NTLMSSP", &ntlmssp_command)) { + return NT_STATUS_LOGON_FAILURE; } @@ -104,7 +107,7 @@ static const char *ntlmssp_target_name(NTLMSSP_STATE *ntlmssp_state, if (neg_flags & NTLMSSP_REQUEST_TARGET) { *chal_flags |= NTLMSSP_CHAL_TARGET_INFO; *chal_flags |= NTLMSSP_REQUEST_TARGET; - if (lp_server_role() == ROLE_STANDALONE) { + if (ntlmssp_state->server_role == ROLE_STANDALONE) { *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER; return ntlmssp_state->get_global_myname(); } else { @@ -145,7 +148,7 @@ NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state, debug_ntlmssp_flags(neg_flags); - cryptkey = ntlmssp_state->get_challenge(ntlmssp_state->auth_context); + cryptkey = ntlmssp_state->get_challenge(ntlmssp_state); data_blob_free(&ntlmssp_state->chal); ntlmssp_state->chal = data_blob(cryptkey, 8); @@ -270,7 +273,7 @@ NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state, file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length); #endif - nt_status = ntlmssp_state->check_password(ntlmssp_state->auth_context); + nt_status = ntlmssp_state->check_password(ntlmssp_state); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; -- cgit From dc4bb3bed82773ab0a07eb72b3d21305cccb6ecf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 28 Jan 2003 03:37:14 +0000 Subject: Factor out common code in the NTLMSSP/SPNEGO code. The idea here is to seperate, as much as possible, the SPNEGO layer from the NTLMSSP layer. This not only helps us with protocol correctness, but also should allow further mechinisms to be added with relitive ease. I indend to make the kerberos code use this shortly. I've never seen the 'zero length blob' form of the anonymous login, so I've removed that case. Andrew Bartlett (This used to be commit a8773c9f825539c5bc17e4200b16d7ebbe0b7620) --- source3/libsmb/ntlmssp.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 6837674736..5b608e0a7a 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -275,10 +275,6 @@ NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state, nt_status = ntlmssp_state->check_password(ntlmssp_state); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - *reply = data_blob(NULL, 0); return nt_status; -- cgit From d1221c9b6c369113a531063737890b58d89bf6fe Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Feb 2003 02:55:00 +0000 Subject: Merge from HEAD client-side authentication changes: - new kerberos code, allowing the account to change it's own password without special SD settings required - NTLMSSP client code, now seperated from cliconnect.c - NTLMv2 client code - SMB signing fixes Andrew Bartlett (This used to be commit 837680ca517982f2e5944730581a83012d4181ae) --- source3/libsmb/ntlmssp.c | 488 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 416 insertions(+), 72 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 5b608e0a7a..e1509f6b63 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -24,11 +24,53 @@ #include "includes.h" /** - * Default challange generation code. + * Print out the NTLMSSP flags for debugging + * @param neg_flags The flags from the packet + */ + +void debug_ntlmssp_flags(uint32 neg_flags) +{ + DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags)); + + if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_UNICODE\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_OEM) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM\n")); + if (neg_flags & NTLMSSP_REQUEST_TARGET) + DEBUGADD(4, (" NTLMSSP_REQUEST_TARGET\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SIGN\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_SEAL) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SEAL\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NETWARE\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_NTLM) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM2\n")); + if (neg_flags & NTLMSSP_CHAL_TARGET_INFO) + DEBUGADD(4, (" NTLMSSP_CHAL_TARGET_INFO\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_128) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_128\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n")); +} + +/** + * Default challenge generation code. * */ - static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state) { static uchar chal[8]; @@ -37,71 +79,17 @@ static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state) return chal; } -NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) -{ - TALLOC_CTX *mem_ctx; - - mem_ctx = talloc_init("NTLMSSP context"); - - *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state)); - if (!*ntlmssp_state) { - DEBUG(0,("ntlmssp_start: talloc failed!\n")); - talloc_destroy(mem_ctx); - return NT_STATUS_NO_MEMORY; - } - - ZERO_STRUCTP(*ntlmssp_state); - - (*ntlmssp_state)->mem_ctx = mem_ctx; - (*ntlmssp_state)->get_challenge = get_challenge; - - (*ntlmssp_state)->get_global_myname = global_myname; - (*ntlmssp_state)->get_domain = lp_workgroup; - (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */ - - return NT_STATUS_OK; -} - -NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state) -{ - TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; - - data_blob_free(&(*ntlmssp_state)->chal); - data_blob_free(&(*ntlmssp_state)->lm_resp); - data_blob_free(&(*ntlmssp_state)->nt_resp); - - SAFE_FREE((*ntlmssp_state)->user); - SAFE_FREE((*ntlmssp_state)->domain); - SAFE_FREE((*ntlmssp_state)->workstation); - - talloc_destroy(mem_ctx); - *ntlmssp_state = NULL; - return NT_STATUS_OK; -} - -NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, - DATA_BLOB request, DATA_BLOB *reply) -{ - uint32 ntlmssp_command; - *reply = data_blob(NULL, 0); - - if (!msrpc_parse(&request, "Cd", - "NTLMSSP", - &ntlmssp_command)) { - - return NT_STATUS_LOGON_FAILURE; - } - - if (ntlmssp_command == NTLMSSP_NEGOTIATE) { - return ntlmssp_negotiate(ntlmssp_state, request, reply); - } else if (ntlmssp_command == NTLMSSP_AUTH) { - return ntlmssp_auth(ntlmssp_state, request, reply); - } else { - return NT_STATUS_LOGON_FAILURE; - } -} +/** + * Determine correct target name flags for reply, given server role + * and negoitated falgs + * + * @param ntlmssp_state NTLMSSP State + * @param neg_flags The flags from the packet + * @param chal_flags The flags to be set in the reply packet + * @return The 'target name' string. + */ -static const char *ntlmssp_target_name(NTLMSSP_STATE *ntlmssp_state, +static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state, uint32 neg_flags, uint32 *chal_flags) { if (neg_flags & NTLMSSP_REQUEST_TARGET) { @@ -119,8 +107,17 @@ static const char *ntlmssp_target_name(NTLMSSP_STATE *ntlmssp_state, } } -NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state, - DATA_BLOB request, DATA_BLOB *reply) +/** + * Next state function for the Negotiate packet + * + * @param ntlmssp_state NTLMSSP State + * @param request The request, as a DATA_BLOB + * @param request The reply, as an allocated DATA_BLOB, caller to free. + * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent. + */ + +static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, + const DATA_BLOB request, DATA_BLOB *reply) { DATA_BLOB struct_blob; fstring dnsname, dnsdomname; @@ -140,7 +137,7 @@ NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state, &neg_flags, &cliname, &domname)) { - return NT_STATUS_LOGON_FAILURE; + return NT_STATUS_INVALID_PARAMETER; } SAFE_FREE(cliname); @@ -219,11 +216,22 @@ NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state, data_blob_free(&struct_blob); + ntlmssp_state->expected_state = NTLMSSP_AUTH; + return NT_STATUS_MORE_PROCESSING_REQUIRED; } -NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state, - DATA_BLOB request, DATA_BLOB *reply) +/** + * Next state function for the Authenticate packet + * + * @param ntlmssp_state NTLMSSP State + * @param request The request, as a DATA_BLOB + * @param request The reply, as an allocated DATA_BLOB, caller to free. + * @return Errors or NT_STATUS_OK. + */ + +static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, + const DATA_BLOB request, DATA_BLOB *reply) { DATA_BLOB sess_key; uint32 ntlmssp_command, neg_flags; @@ -260,7 +268,7 @@ NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state, &ntlmssp_state->workstation, &sess_key, &neg_flags)) { - return NT_STATUS_LOGON_FAILURE; + return NT_STATUS_INVALID_PARAMETER; } data_blob_free(&sess_key); @@ -279,3 +287,339 @@ NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state, return nt_status; } + +/** + * Create an NTLMSSP state machine + * + * @param ntlmssp_state NTLMSSP State, allocated by this funciton + */ + +NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_init("NTLMSSP context"); + + *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state)); + if (!*ntlmssp_state) { + DEBUG(0,("ntlmssp_server_start: talloc failed!\n")); + talloc_destroy(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + (*ntlmssp_state)->mem_ctx = mem_ctx; + (*ntlmssp_state)->get_challenge = get_challenge; + + (*ntlmssp_state)->get_global_myname = global_myname; + (*ntlmssp_state)->get_domain = lp_workgroup; + (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */ + + (*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE; + + return NT_STATUS_OK; +} + +/** + * End an NTLMSSP state machine + * + * @param ntlmssp_state NTLMSSP State, free()ed by this funciton + */ + +NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; + + data_blob_free(&(*ntlmssp_state)->chal); + data_blob_free(&(*ntlmssp_state)->lm_resp); + data_blob_free(&(*ntlmssp_state)->nt_resp); + + SAFE_FREE((*ntlmssp_state)->user); + SAFE_FREE((*ntlmssp_state)->domain); + SAFE_FREE((*ntlmssp_state)->workstation); + + talloc_destroy(mem_ctx); + *ntlmssp_state = NULL; + return NT_STATUS_OK; +} + +/** + * Next state function for the NTLMSSP state machine + * + * @param ntlmssp_state NTLMSSP State + * @param request The request, as a DATA_BLOB + * @param request The reply, as an allocated DATA_BLOB, caller to free. + * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK. + */ + +NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, + const DATA_BLOB request, DATA_BLOB *reply) +{ + uint32 ntlmssp_command; + *reply = data_blob(NULL, 0); + + if (!msrpc_parse(&request, "Cd", + "NTLMSSP", + &ntlmssp_command)) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (ntlmssp_command != ntlmssp_state->expected_state) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (ntlmssp_command == NTLMSSP_NEGOTIATE) { + return ntlmssp_server_negotiate(ntlmssp_state, request, reply); + } else if (ntlmssp_command == NTLMSSP_AUTH) { + return ntlmssp_server_auth(ntlmssp_state, request, reply); + } else { + return NT_STATUS_INVALID_PARAMETER; + } +} + +/********************************************************************* + Client side NTLMSSP +*********************************************************************/ + +/** + * Next state function for the Initial packet + * + * @param ntlmssp_state NTLMSSP State + * @param request The request, as a DATA_BLOB. reply.data must be NULL + * @param request The reply, as an allocated DATA_BLOB, caller to free. + * @return Errors or NT_STATUS_OK. + */ + +static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_state, + DATA_BLOB reply, DATA_BLOB *next_request) +{ + if (ntlmssp_state->unicode) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; + } + + /* generate the ntlmssp negotiate packet */ + msrpc_gen(next_request, "CddAA", + "NTLMSSP", + NTLMSSP_NEGOTIATE, + ntlmssp_state->neg_flags, + ntlmssp_state->get_domain(), + ntlmssp_state->get_global_myname()); + + return NT_STATUS_MORE_PROCESSING_REQUIRED; +} + +/** + * Next state function for the Challenge Packet. Generate an auth packet. + * + * @param ntlmssp_state NTLMSSP State + * @param request The request, as a DATA_BLOB. reply.data must be NULL + * @param request The reply, as an allocated DATA_BLOB, caller to free. + * @return Errors or NT_STATUS_OK. + */ + +static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_state, + const DATA_BLOB reply, DATA_BLOB *next_request) +{ + uint32 chal_flags, ntlmssp_command, unkn1, unkn2; + DATA_BLOB server_domain_blob; + DATA_BLOB challenge_blob; + DATA_BLOB struct_blob; + char *server_domain; + const char *chal_parse_string; + const char *auth_gen_string; + 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]; + + ZERO_STRUCT(datagram_sess_key); + + if (!msrpc_parse(&reply, "CdBd", + "NTLMSSP", + &ntlmssp_command, + &server_domain_blob, + &chal_flags)) { + DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + data_blob_free(&server_domain_blob); + + if (chal_flags & NTLMSSP_NEGOTIATE_UNICODE) { + chal_parse_string = "CdUdbddB"; + auth_gen_string = "CdBBUUUBd"; + ntlmssp_state->unicode = True; + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM; + } else if (chal_flags & NTLMSSP_NEGOTIATE_OEM) { + chal_parse_string = "CdAdbddB"; + auth_gen_string = "CdBBAAABd"; + ntlmssp_state->unicode = False; + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE; + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; + } else { + return NT_STATUS_INVALID_PARAMETER; + } + + if (!msrpc_parse(&reply, chal_parse_string, + "NTLMSSP", + &ntlmssp_command, + &server_domain, + &chal_flags, + &challenge_blob, 8, + &unkn1, &unkn2, + &struct_blob)) { + DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + SAFE_FREE(server_domain); + data_blob_free(&struct_blob); + + if (challenge_blob.length != 8) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (ntlmssp_state->use_ntlmv2) { + + /* TODO: if the remote server is standalone, then we should replace 'domain' + with the server name as supplied above */ + + if (!SMBNTLMv2encrypt(ntlmssp_state->user, + ntlmssp_state->domain, + ntlmssp_state->password, challenge_blob, + &lm_response, &nt_response, &session_key)) { + data_blob_free(&challenge_blob); + return NT_STATUS_NO_MEMORY; + } + } else { + uchar nt_hash[16]; + E_md4hash(ntlmssp_state->password, nt_hash); + + /* non encrypted password supplied. Ignore ntpass. */ + if (lp_client_lanman_auth()) { + 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); + SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + } + + data_blob_free(&challenge_blob); + + /* this generates the actual auth packet */ + if (!msrpc_gen(next_request, auth_gen_string, + "NTLMSSP", + NTLMSSP_AUTH, + lm_response.data, lm_response.length, + nt_response.data, nt_response.length, + ntlmssp_state->domain, + ntlmssp_state->user, + ntlmssp_state->get_global_myname(), + datagram_sess_key, 0, + ntlmssp_state->neg_flags)) { + + data_blob_free(&lm_response); + data_blob_free(&nt_response); + data_blob_free(&session_key); + return NT_STATUS_NO_MEMORY; + } + + data_blob_free(&lm_response); + data_blob_free(&nt_response); + + ntlmssp_state->session_key = session_key; + + return NT_STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_init("NTLMSSP Client context"); + + *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state)); + if (!*ntlmssp_state) { + DEBUG(0,("ntlmssp_server_start: talloc failed!\n")); + talloc_destroy(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + (*ntlmssp_state)->mem_ctx = mem_ctx; + + (*ntlmssp_state)->get_global_myname = global_myname; + (*ntlmssp_state)->get_domain = lp_workgroup; + + (*ntlmssp_state)->unicode = True; + + (*ntlmssp_state)->neg_flags = + NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_REQUEST_TARGET; + + return NT_STATUS_OK; +} + +NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; + + data_blob_free(&(*ntlmssp_state)->session_key); + talloc_destroy(mem_ctx); + *ntlmssp_state = NULL; + return NT_STATUS_OK; +} + +NTSTATUS ntlmssp_client_update(NTLMSSP_CLIENT_STATE *ntlmssp_state, + DATA_BLOB reply, DATA_BLOB *next_request) +{ + uint32 ntlmssp_command; + *next_request = data_blob(NULL, 0); + + if (!reply.length) { + return ntlmssp_client_initial(ntlmssp_state, reply, next_request); + } + + if (!msrpc_parse(&reply, "Cd", + "NTLMSSP", + &ntlmssp_command)) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (ntlmssp_command == NTLMSSP_CHALLENGE) { + return ntlmssp_client_challenge(ntlmssp_state, reply, next_request); + } + return NT_STATUS_INVALID_PARAMETER; +} + +NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *user) +{ + ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user); + if (!ntlmssp_state->user) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +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; + } + return NT_STATUS_OK; +} + +NTSTATUS ntlmssp_set_domain(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *domain) +{ + ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain); + if (!ntlmssp_state->domain) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} -- cgit From 972e492bed431d7a19f9b54727952293ce395660 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 18 Mar 2003 11:53:20 +0000 Subject: NTLMSSP updates from HEAD. Andrew Bartlett (This used to be commit f4ae028c2ad6ff8c7da3a6ef77a92762861144e1) --- source3/libsmb/ntlmssp.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index e1509f6b63..5722b8efcd 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -81,7 +81,7 @@ static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state) /** * Determine correct target name flags for reply, given server role - * and negoitated falgs + * and negotiated flags * * @param ntlmssp_state NTLMSSP State * @param neg_flags The flags from the packet @@ -291,7 +291,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, /** * Create an NTLMSSP state machine * - * @param ntlmssp_state NTLMSSP State, allocated by this funciton + * @param ntlmssp_state NTLMSSP State, allocated by this function */ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) @@ -322,7 +322,7 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) /** * End an NTLMSSP state machine * - * @param ntlmssp_state NTLMSSP State, free()ed by this funciton + * @param ntlmssp_state NTLMSSP State, free()ed by this function */ NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state) @@ -431,7 +431,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st DATA_BLOB session_key = data_blob(NULL, 0); uint8 datagram_sess_key[16]; - ZERO_STRUCT(datagram_sess_key); + generate_random_buffer(datagram_sess_key, sizeof(datagram_sess_key), False); if (!msrpc_parse(&reply, "CdBd", "NTLMSSP", @@ -508,8 +508,6 @@ 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(&challenge_blob); /* this generates the actual auth packet */ if (!msrpc_gen(next_request, auth_gen_string, @@ -520,7 +518,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, 0, + datagram_sess_key, 16, ntlmssp_state->neg_flags)) { data_blob_free(&lm_response); @@ -529,9 +527,14 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st return NT_STATUS_NO_MEMORY; } - data_blob_free(&lm_response); - data_blob_free(&nt_response); + data_blob_free(&ntlmssp_state->chal); + data_blob_free(&ntlmssp_state->lm_resp); + data_blob_free(&ntlmssp_state->nt_resp); + data_blob_free(&ntlmssp_state->session_key); + ntlmssp_state->chal = challenge_blob; + ntlmssp_state->lm_resp = lm_response; + ntlmssp_state->nt_resp = nt_response; ntlmssp_state->session_key = session_key; return NT_STATUS_MORE_PROCESSING_REQUIRED; @@ -558,10 +561,12 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) (*ntlmssp_state)->unicode = True; (*ntlmssp_state)->neg_flags = - NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_REQUEST_TARGET; + (*ntlmssp_state)->ref_count = 1; + return NT_STATUS_OK; } @@ -569,8 +574,16 @@ NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state) { TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; - data_blob_free(&(*ntlmssp_state)->session_key); - talloc_destroy(mem_ctx); + (*ntlmssp_state)->ref_count--; + + if ((*ntlmssp_state)->ref_count == 0) { + data_blob_free(&(*ntlmssp_state)->chal); + data_blob_free(&(*ntlmssp_state)->lm_resp); + data_blob_free(&(*ntlmssp_state)->nt_resp); + data_blob_free(&(*ntlmssp_state)->session_key); + talloc_destroy(mem_ctx); + } + *ntlmssp_state = NULL; return NT_STATUS_OK; } -- cgit From 53beee9e5675a59c67d9ecfbaec50dca4ac01750 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Mar 2003 09:54:13 +0000 Subject: (merge from HEAD) NTLM Authentication: - Add a 'privileged' mode to Winbindd. This is achieved by means of a directory under lockdir, that the admin can change the group access for. - This mode is now required to access with 'CRAP' authentication feature. - This *will* break the current SQUID helper, so I've fixed up our ntlm_auth replacement: - Update our NTLMSSP code to cope with 'datagram' mode, where we don't get a challenge. - Use this to make our ntlm_auth utility suitable for use in current Squid 2.5 servers. - Tested - works for Win2k clients, but not Win9X at present. NTLMSSP updates are needed. - Now uses fgets(), not x_fgets() to cope with Squid environment (I think somthing to do with non-blocking stdin). - Add much more robust connection code to wb_common.c - it will not connect to a server of a different protocol version, and it will automatically try and reconnect to the 'privileged' pipe if possible. - This could help with 'privileged' idmap operations etc in future. - Add a generic HEX encode routine to util_str.c, - fix a small line of dodgy C in StrnCpy_fn() - Correctly pull our 'session key' out of the info3 from th the DC. This is used in both the auth code, and in for export over the winbind pipe to ntlm_auth. - Given the user's challenge/response and access to the privileged pipe, allow external access to the 'session key'. To be used for MSCHAPv2 integration. Andrew Bartlett (This used to be commit ec071ca3dcbd3881dc08e6a8d7ac2ff0bcd57664) --- source3/libsmb/ntlmssp.c | 50 +++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 5722b8efcd..0cd1ac33ec 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -121,7 +121,8 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, { DATA_BLOB struct_blob; fstring dnsname, dnsdomname; - uint32 ntlmssp_command, neg_flags, chal_flags; + uint32 neg_flags = 0; + uint32 ntlmssp_command, chal_flags; char *cliname=NULL, *domname=NULL; const uint8 *cryptkey; const char *target_name; @@ -131,20 +132,24 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, file_save("ntlmssp_negotiate.dat", request.data, request.length); #endif - if (!msrpc_parse(&request, "CddAA", - "NTLMSSP", - &ntlmssp_command, - &neg_flags, - &cliname, - &domname)) { - return NT_STATUS_INVALID_PARAMETER; + if (request.length) { + if (!msrpc_parse(&request, "CddAA", + "NTLMSSP", + &ntlmssp_command, + &neg_flags, + &cliname, + &domname)) { + DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n")); + dump_data(2, request.data, request.length); + return NT_STATUS_INVALID_PARAMETER; + } + + SAFE_FREE(cliname); + SAFE_FREE(domname); + + debug_ntlmssp_flags(neg_flags); } - - SAFE_FREE(cliname); - SAFE_FREE(domname); - - debug_ntlmssp_flags(neg_flags); - + cryptkey = ntlmssp_state->get_challenge(ntlmssp_state); data_blob_free(&ntlmssp_state->chal); @@ -268,6 +273,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, &ntlmssp_state->workstation, &sess_key, &neg_flags)) { + DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); + dump_data(2, request.data, request.length); return NT_STATUS_INVALID_PARAMETER; } @@ -357,13 +364,19 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, uint32 ntlmssp_command; *reply = data_blob(NULL, 0); - if (!msrpc_parse(&request, "Cd", - "NTLMSSP", - &ntlmssp_command)) { - return NT_STATUS_INVALID_PARAMETER; + if (request.length) { + if (!msrpc_parse(&request, "Cd", + "NTLMSSP", + &ntlmssp_command)) { + return NT_STATUS_INVALID_PARAMETER; + } + } else { + /* 'datagram' mode - no neg packet */ + ntlmssp_command = NTLMSSP_NEGOTIATE; } if (ntlmssp_command != ntlmssp_state->expected_state) { + DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); return NT_STATUS_INVALID_PARAMETER; } @@ -372,6 +385,7 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, } else if (ntlmssp_command == NTLMSSP_AUTH) { return ntlmssp_server_auth(ntlmssp_state, request, reply); } else { + DEBUG(1, ("unknown NTLMSSP command %u\n", ntlmssp_command, ntlmssp_state->expected_state)); return NT_STATUS_INVALID_PARAMETER; } } -- cgit From 3643d94b4f01311a4cf068375da5cd728a150755 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Apr 2003 00:20:58 +0000 Subject: Fixup format warning. Jeremy. (This used to be commit 32dc4ddb04f4d3eecfdd542cb3495830067a2eed) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 0cd1ac33ec..b8ef3a80c2 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -385,7 +385,7 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, } else if (ntlmssp_command == NTLMSSP_AUTH) { return ntlmssp_server_auth(ntlmssp_state, request, reply); } else { - DEBUG(1, ("unknown NTLMSSP command %u\n", ntlmssp_command, ntlmssp_state->expected_state)); + DEBUG(1, ("unknown NTLMSSP command %u\n", ntlmssp_command)); return NT_STATUS_INVALID_PARAMETER; } } -- cgit From a48d89bb9d0092d9b2368d55fdd1e2350210c012 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 7 Apr 2003 07:37:46 +0000 Subject: Make this match head. (This used to be commit a718630961e713ca2bacc98ad0b7c2e996e20bf5) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index b8ef3a80c2..c179b98abf 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -385,7 +385,7 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, } else if (ntlmssp_command == NTLMSSP_AUTH) { return ntlmssp_server_auth(ntlmssp_state, request, reply); } else { - DEBUG(1, ("unknown NTLMSSP command %u\n", ntlmssp_command)); + DEBUG(1, ("unknown NTLMSSP command %u expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); return NT_STATUS_INVALID_PARAMETER; } } -- cgit From 1e2147fc0f677914fb2e3168b4fd4d7ddb4b9867 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Apr 2003 13:00:39 +0000 Subject: Merge SMB signing, cli buffer clobber and NTLMSSP signing tweaks from HEAD. (This used to be commit c6c4f69b8ddc500890a65829e1b9fb7a3e9839e9) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index c179b98abf..d54655d17f 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -385,7 +385,7 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, } else if (ntlmssp_command == NTLMSSP_AUTH) { return ntlmssp_server_auth(ntlmssp_state, request, reply); } else { - DEBUG(1, ("unknown NTLMSSP command %u expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); + DEBUG(1, ("unknown NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); return NT_STATUS_INVALID_PARAMETER; } } -- cgit From 423bd582f4f0f03ff086054060954e8e23cd02cd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 5 May 2003 05:15:54 +0000 Subject: Allow the NTLMv2 functions to spit out both possible varients on the session key, so we can test it in ntlm_auth. I suspect the 'lm' version doesn't exist, but it's easy to change back. Andrew Bartlett (This used to be commit 5efd95622c411f123660b6613b86c7a68bba68e8) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index d54655d17f..356bb0c4fe 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -501,7 +501,7 @@ 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, &session_key)) { + &lm_response, &nt_response, NULL, &session_key)) { data_blob_free(&challenge_blob); return NT_STATUS_NO_MEMORY; } -- cgit From d06f95ca78834403a602e4c1d64e13e059f3017e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 9 May 2003 14:42:20 +0000 Subject: Finally get NTLMv2 working on the client! With big thanks to tpot for the ethereal disector, and for the base code behind this, we now fully support NTLMv2 as a client. In particular, we support it with direct domain logons (tested with ntlm_auth --diagnostics), with 'old style' session setups, and with NTLMSSP. In fact, for NTLMSSP we recycle one of the parts of the server's reply directly... (we might need to parse for unicode issues later). In particular, a Win2k domain controller now supplies us with a session key for this password, which means that doman joins, and non-spnego SMB signing are now supported with NTLMv2! Andrew Bartlett (This used to be commit 9f6a26769d345d319ec167cd0e82a45e1207ed81) --- source3/libsmb/ntlmssp.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') 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, -- cgit From ce72beb2b558d86fb49063c6b1fa00e07952ce56 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 3 Jul 2003 19:11:31 +0000 Subject: Removed strupper/strlower macros that automatically map to strupper_m/strlower_m. I really want people to think about when they're using multibyte strings. Jeremy. (This used to be commit ff222716a08af65d26ad842ce4c2841cc6540959) --- source3/libsmb/ntlmssp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 636e384e65..609b394560 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -175,11 +175,11 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname[0] = '\0'; get_mydomname(dnsdomname); - strlower(dnsdomname); + strlower_m(dnsdomname); dnsname[0] = '\0'; get_myfullname(dnsname); - strlower(dnsname); + strlower_m(dnsname); if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { -- cgit From 31e6ed17a34dd922355bfe515909290947e87c54 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 14 Jul 2003 01:49:07 +0000 Subject: Delete obsolete comment. (This used to be commit 5416c51133297e866210ec0d8454e04c25541d91) --- source3/libsmb/ntlmssp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 609b394560..4dc9d42659 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -190,7 +190,6 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, target_name_dns = dnsname; } - /* the numbers here are the string type flags */ msrpc_gen(&struct_blob, "aaaaa", ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN, target_name, ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), -- cgit From 456f51bcbe04ccbb37a27b6e115a851cc134adcd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 14 Jul 2003 08:46:32 +0000 Subject: Jeremy requested that I get my NTLMSSP patch into CVS. He didn't request the schannel code, but I've included that anyway. :-) This patch revives the client-side NTLMSSP support for RPC named pipes in Samba, and cleans up the client and server schannel code. The use of the new code is enabled by the 'sign', 'seal' and 'schannel' commands in rpcclient. The aim was to prove that our separate NTLMSSP client library actually implements NTLMSSP signing and sealing as per Microsoft's NTLMv1 implementation, in the hope that knowing this will assist us in correctly implementing NTLMSSP signing for SMB packets. (Still not yet functional) This patch replaces the NTLMSSP implementation in rpc_client/cli_pipe.c with calls to libsmb/ntlmssp.c. In the process, we have gained the ability to use the more secure NT password, and the ability to sign-only, instead of having to seal the pipe connection. (Previously we were limited to sealing, and could only use the LM-password derived key). Our new client-side NTLMSSP code also needed alteration to cope with our comparatively simple server-side implementation. A future step is to replace it with calls to the same NTLMSSP library. Also included in this patch is the schannel 'sign only' patch I submitted to the team earlier. While not enabled (and not functional, at this stage) the work in this patch makes the code paths *much* easier to follow. I have also included similar hooks in rpccleint to allow the use of schannel on *any* pipe. rpcclient now defaults to not using schannel (or any other extra per-pipe authenticiation) for any connection. The 'schannel' command enables schannel for all pipes until disabled. This code is also much more secure than the previous code, as changes to our cli_pipe routines ensure that the authentication footer cannot be removed by an attacker, and more error states are correctly handled. (The same needs to be done to our server) Andrew Bartlett (This used to be commit 5472ddc9eaf4e79c5b2e1c8ee8c7f190dc285f19) --- source3/libsmb/ntlmssp.c | 107 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 95 insertions(+), 12 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 4dc9d42659..66dc6e08eb 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -409,6 +409,10 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; } + if (ntlmssp_state->use_ntlmv2) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + /* generate the ntlmssp negotiate packet */ msrpc_gen(next_request, "CddAA", "NTLMSSP", @@ -435,7 +439,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st uint32 chal_flags, ntlmssp_command, unkn1, unkn2; DATA_BLOB server_domain_blob; DATA_BLOB challenge_blob; - DATA_BLOB struct_blob; + DATA_BLOB struct_blob = data_blob(NULL, 0); char *server_domain; const char *chal_parse_string; const char *auth_gen_string; @@ -443,28 +447,48 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st 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 if (!msrpc_parse(&reply, "CdBd", "NTLMSSP", &ntlmssp_command, &server_domain_blob, &chal_flags)) { - DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n")); + DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n")); + dump_data(2, reply.data, reply.length); + return NT_STATUS_INVALID_PARAMETER; } data_blob_free(&server_domain_blob); + DEBUG(3, ("Got challenge flags:\n")); + debug_ntlmssp_flags(chal_flags); + if (chal_flags & NTLMSSP_NEGOTIATE_UNICODE) { - chal_parse_string = "CdUdbddB"; + if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { + chal_parse_string = "CdUdbddB"; + } else { + chal_parse_string = "CdUdbdd"; + } auth_gen_string = "CdBBUUUBd"; ntlmssp_state->unicode = True; ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM; } else if (chal_flags & NTLMSSP_NEGOTIATE_OEM) { - chal_parse_string = "CdAdbddB"; + if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { + chal_parse_string = "CdAdbddB"; + } else { + chal_parse_string = "CdAdbdd"; + } auth_gen_string = "CdBBAAABd"; ntlmssp_state->unicode = False; ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE; @@ -473,6 +497,25 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st return NT_STATUS_INVALID_PARAMETER; } + if (chal_flags & NTLMSSP_NEGOTIATE_LM_KEY && lp_client_lanman_auth()) { + /* server forcing us to use LM */ + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; + ntlmssp_state->use_ntlmv2 = False; + } else { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; + } + + if (!(chal_flags & NTLMSSP_NEGOTIATE_NTLM2)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; + } + + if (!(chal_flags & NTLMSSP_NEGOTIATE_128)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; + } + + DEBUG(3, ("NTLMSSP: Set final flags:\n")); + debug_ntlmssp_flags(ntlmssp_state->neg_flags); + if (!msrpc_parse(&reply, chal_parse_string, "NTLMSSP", &ntlmssp_command, @@ -481,7 +524,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st &challenge_blob, 8, &unkn1, &unkn2, &struct_blob)) { - DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n")); + DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n")); + dump_data(2, reply.data, reply.length); return NT_STATUS_INVALID_PARAMETER; } @@ -493,6 +537,11 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st if (ntlmssp_state->use_ntlmv2) { + if (!struct_blob.length) { + /* be lazy, match win2k - we can't do NTLMv2 without it */ + return NT_STATUS_INVALID_PARAMETER; + } + /* TODO: if the remote server is standalone, then we should replace 'domain' with the server name as supplied above */ @@ -506,10 +555,12 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st return NT_STATUS_NO_MEMORY; } } else { + uchar lm_hash[16]; uchar nt_hash[16]; + E_deshash(ntlmssp_state->password, lm_hash); E_md4hash(ntlmssp_state->password, nt_hash); - /* non encrypted password supplied. Ignore ntpass. */ + /* lanman auth is insecure, it may be disabled */ if (lp_client_lanman_auth()) { lm_response = data_blob(NULL, 24); SMBencrypt(ntlmssp_state->password,challenge_blob.data, @@ -519,8 +570,15 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st nt_response = data_blob(NULL, 24); SMBNTencrypt(ntlmssp_state->password,challenge_blob.data, nt_response.data); + session_key = data_blob(NULL, 16); - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) + && lp_client_lanman_auth()) { + SMBsesskeygen_lmv1(lm_hash, lm_response.data, + session_key.data); + } else { + SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + } } data_blob_free(&struct_blob); @@ -533,7 +591,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, 16, + datagram_sess_key, datagram_sess_key_len, ntlmssp_state->neg_flags)) { data_blob_free(&lm_response); @@ -575,6 +633,8 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) (*ntlmssp_state)->unicode = True; + (*ntlmssp_state)->use_ntlmv2 = lp_client_ntlmv2_auth(); + (*ntlmssp_state)->neg_flags = NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_NTLM | @@ -596,6 +656,7 @@ NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state) data_blob_free(&(*ntlmssp_state)->lm_resp); data_blob_free(&(*ntlmssp_state)->nt_resp); data_blob_free(&(*ntlmssp_state)->session_key); + data_blob_free(&(*ntlmssp_state)->stored_response); talloc_destroy(mem_ctx); } @@ -606,12 +667,18 @@ NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state) NTSTATUS ntlmssp_client_update(NTLMSSP_CLIENT_STATE *ntlmssp_state, DATA_BLOB reply, DATA_BLOB *next_request) { + NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; uint32 ntlmssp_command; *next_request = data_blob(NULL, 0); if (!reply.length) { - return ntlmssp_client_initial(ntlmssp_state, reply, next_request); - } + /* If there is a cached reply, use it - otherwise this is the first packet */ + if (!ntlmssp_state->stored_response.length) { + return ntlmssp_client_initial(ntlmssp_state, reply, next_request); + } + + reply = ntlmssp_state->stored_response; + } if (!msrpc_parse(&reply, "Cd", "NTLMSSP", @@ -620,9 +687,12 @@ NTSTATUS ntlmssp_client_update(NTLMSSP_CLIENT_STATE *ntlmssp_state, } if (ntlmssp_command == NTLMSSP_CHALLENGE) { - return ntlmssp_client_challenge(ntlmssp_state, reply, next_request); + nt_status = ntlmssp_client_challenge(ntlmssp_state, reply, next_request); } - return NT_STATUS_INVALID_PARAMETER; + if (ntlmssp_state->stored_response.length) { + data_blob_free(&ntlmssp_state->stored_response); + } + return nt_status; } NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *user) @@ -651,3 +721,16 @@ NTSTATUS ntlmssp_set_domain(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *dom } return NT_STATUS_OK; } + +/** + * Store a DATA_BLOB containing an NTLMSSP response, for use later. + * This 'keeps' the data blob - the caller must *not* free it. + */ + +NTSTATUS ntlmssp_client_store_response(NTLMSSP_CLIENT_STATE *ntlmssp_state, + DATA_BLOB response) +{ + data_blob_free(&ntlmssp_state->stored_response); + ntlmssp_state->stored_response = response; + return NT_STATUS_OK; +} -- cgit From 77373f1f8e3b2f61e9bbcd9fadfb83257d390cf2 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 24 Jul 2003 23:46:27 +0000 Subject: More printf fixes - size_t is long on some architectures. (This used to be commit ba4d334b822248d8ab929c9568533431603d967e) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 66dc6e08eb..175e952f86 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -279,7 +279,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, data_blob_free(&sess_key); - DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%d len2=%d\n", + DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%l len2=%l\n", ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, ntlmssp_state->lm_resp.length, ntlmssp_state->nt_resp.length)); #if 0 -- cgit From 7d833de662b83f026b54a236588da27dd8899630 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 25 Jul 2003 04:24:40 +0000 Subject: More printf portability fixes. Got caught out by some gcc'isms last time. )-: (This used to be commit 59dae1da66a5eb7e128263bd578f167d8746e9f0) --- source3/libsmb/ntlmssp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 175e952f86..a50ae9b70f 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -279,8 +279,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, data_blob_free(&sess_key); - DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%l len2=%l\n", - ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, ntlmssp_state->lm_resp.length, ntlmssp_state->nt_resp.length)); + DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n", + ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length)); #if 0 file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length); -- cgit From 94bbd5c93a777ad1a6b3951358306e29e6277251 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 10 Aug 2003 20:18:05 +0000 Subject: Store the server domain from the ntlmssp challenge in the client struct to be able to ask a LMB for the servers in its workgroup. Against W2k this only works on port 139.... Volker (This used to be commit 62b04d7776852098dd768268500f36c3a362f688) --- source3/libsmb/ntlmssp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index a50ae9b70f..e76ad75e6e 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -529,6 +529,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st 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); -- cgit From 76ecaa347ebffe0a713afe8d7fcdfdadc4cce6d5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 11 Aug 2003 20:40:39 +0000 Subject: Fix a segfault in ntlm_auth when we can't find a domain or hostname. Volker (This used to be commit 49c4f8a764a2b9e266c33f018515e6a742cfc8b0) --- source3/libsmb/ntlmssp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index e76ad75e6e..37f5510c65 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -174,11 +174,13 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname[0] = '\0'; - get_mydomname(dnsdomname); + if (!get_mydomname(dnsdomname)) + return NT_STATUS_INVALID_PARAMETER; strlower_m(dnsdomname); dnsname[0] = '\0'; - get_myfullname(dnsname); + if (!get_myfullname(dnsname)) + return NT_STATUS_INVALID_PARAMETER; strlower_m(dnsname); if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) -- cgit From 6932617c50f0cd084b7d8ad4f976d7ac33394c01 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 11 Aug 2003 20:51:47 +0000 Subject: Revert the latest fix. Need to investigate further. Volker (This used to be commit 447f130619ad7aaab351c2b46d3e57eaf31a9454) --- source3/libsmb/ntlmssp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 37f5510c65..e76ad75e6e 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -174,13 +174,11 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname[0] = '\0'; - if (!get_mydomname(dnsdomname)) - return NT_STATUS_INVALID_PARAMETER; + get_mydomname(dnsdomname); strlower_m(dnsdomname); dnsname[0] = '\0'; - if (!get_myfullname(dnsname)) - return NT_STATUS_INVALID_PARAMETER; + get_myfullname(dnsname); strlower_m(dnsname); if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) -- cgit From 494ea488210eae8206dce69ebbff977fe37f8f83 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 11 Aug 2003 21:00:13 +0000 Subject: I think this is the one to check... Volker (This used to be commit f6d853d36a37dd854a410717af2f7eaf9457eeb5) --- source3/libsmb/ntlmssp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index e76ad75e6e..a314aa15db 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -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); -- cgit From 3b8485d047492788925b530e9e622a61c66f2dbd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 12 Aug 2003 05:53:43 +0000 Subject: As described in http://davenport.sourceforge.net/ntlm.html add NTLM2 authentication. NTLM2 is a version of NTLM, that involves both a client and server challenge, and the creating of a new (presuable more secure) session key. Unfortunetly this is not quite the same as NTLMv2, and we don't know how to get the session key. I suggest looking very closely at what MSCHAPv2, and other MS auth protocols do... Andrew Bartlett (This used to be commit d4a5f4fdf97b707b44a0787267e1e4388d1b5388) --- source3/libsmb/ntlmssp.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index a314aa15db..47e283dc51 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -23,6 +23,12 @@ #include "includes.h" +#if 0 +/* we currently do not know how to get the right session key for this, so + we cannot enable it by default... :-( */ +#define USE_NTLM2 1 +#endif + /** * Print out the NTLMSSP flags for debugging * @param neg_flags The flags from the packet @@ -415,6 +421,10 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat if (ntlmssp_state->use_ntlmv2) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; } + +#ifdef USE_NTLM2 + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; +#endif /* generate the ntlmssp negotiate packet */ msrpc_gen(next_request, "CddAA", @@ -560,7 +570,34 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st data_blob_free(&struct_blob); return NT_STATUS_NO_MEMORY; } +#ifdef USE_NTLM2 + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + struct MD5Context md5_session_nonce_ctx; + uchar nt_hash[16]; + uchar session_nonce[16]; + E_md4hash(ntlmssp_state->password, nt_hash); + + generate_random_buffer(lm_response.data, 8, False); + memset(lm_response.data+8, 0, 16); + + 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, &md5_session_nonce_ctx); + + nt_response = data_blob(NULL, 24); + SMBNTencrypt(ntlmssp_state->password, + challenge_blob.data, + nt_response.data); + + /* This is *NOT* the correct session key algorithm - just + fill in the bytes with something... */ + session_key = data_blob(NULL, 16); + SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); +#endif } else { + + uchar lm_hash[16]; uchar nt_hash[16]; E_deshash(ntlmssp_state->password, lm_hash); @@ -571,15 +608,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 { -- cgit From 172766eea7a374e910ea91c857fcce45996783a2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 14 Aug 2003 01:08:00 +0000 Subject: Change Samba to always use extended security for it's guest logins, (ie, NTLMSSP with "" username, NULL password), and add --machine-pass (-P) to all of Samba's clients. When connecting to an Active Directory DC, you must initiate the CIFS level session setup with Kerberos, not a guest login. If you don't, your machine account is demoted to NT4. Andrew Bartlett (This used to be commit 3547cb3def45a90f99f67829a533eac1ccba5e77) --- source3/libsmb/ntlmssp.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 47e283dc51..43c3464bd2 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -551,7 +551,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st 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 */ @@ -749,9 +751,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; } -- cgit From 062f89bc2833bf49f873a7fd5c2624babd702db0 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 15 Aug 2003 01:42:30 +0000 Subject: get rid of some sompiler warnings on IRIX (This used to be commit a6a39c61e8228c8b3b7552ab3c61ec3a6a639143) --- source3/libsmb/ntlmssp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 43c3464bd2..e4d4acd29b 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -146,7 +146,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; } @@ -282,7 +282,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; } @@ -476,7 +476,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; } @@ -538,7 +538,7 @@ 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; } -- cgit From c913fc058113b3a3a193f7b98459679945afcf03 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 6 Sep 2003 19:23:24 +0000 Subject: address bug #359. Andrew B's patch for implementing client portion of NTLMv2 key exchange. Also revert the default for 'client ntlmv2 auth' to no. This caused no ends of grief in different cases. And based on abartlet's mail.... > All I care about at this point is that we use NTLMv2 > in our client code when connecting to a server that > supports it. There is *no* way to tell this. The server can't tell us, because it doesn't know what it's DC supports. The DC can't tell us, because it doesn't know what the trusted DC supports. One DC might be Win2k, and the PDC could be an older NT4. (This used to be commit fe585d49cc3df0d71314ff43d3271d276d7d4503) --- source3/libsmb/ntlmssp.c | 63 +++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 27 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index e4d4acd29b..42bf18d1d2 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -23,12 +23,6 @@ #include "includes.h" -#if 0 -/* we currently do not know how to get the right session key for this, so - we cannot enable it by default... :-( */ -#define USE_NTLM2 1 -#endif - /** * Print out the NTLMSSP flags for debugging * @param neg_flags The flags from the packet @@ -422,9 +416,7 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; } -#ifdef USE_NTLM2 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; -#endif /* generate the ntlmssp negotiate packet */ msrpc_gen(next_request, "CddAA", @@ -459,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", @@ -502,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; @@ -526,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); @@ -572,31 +561,35 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st data_blob_free(&struct_blob); return NT_STATUS_NO_MEMORY; } -#ifdef USE_NTLM2 } 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, &md5_session_nonce_ctx); + MD5Final(session_nonce_hash, &md5_session_nonce_ctx); nt_response = data_blob(NULL, 24); SMBNTencrypt(ntlmssp_state->password, - challenge_blob.data, + session_nonce_hash, nt_response.data); - /* This is *NOT* the correct session key algorithm - just - fill in the bytes with something... */ session_key = data_blob(NULL, 16); - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); -#endif + + SMBsesskeygen_ntv1(nt_hash, NULL, nt_session_key); + hmac_md5(nt_session_key, session_nonce, sizeof(session_nonce), session_key.data); } else { @@ -627,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", @@ -636,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); @@ -645,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); @@ -683,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; -- cgit From 1555cacd7c7814571ed8bb91a0d3a722cf7dc30b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Sep 2003 01:27:46 +0000 Subject: Fix #442 which Alexander considered a showstopper. Allow us to join mixed mode domains. Jeremy. (This used to be commit c816aacefb6621533194a374251835f186ca838f) --- source3/libsmb/ntlmssp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 42bf18d1d2..c51b599b04 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -692,6 +692,12 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | + /* + * We need to set this to allow a later SetPassword + * via the SAMR pipe to succeed. Strange.... We could + * also add NTLMSSP_NEGOTIATE_SEAL here. JRA. + * */ + NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_REQUEST_TARGET; (*ntlmssp_state)->ref_count = 1; -- cgit From fcbfc7ad0669009957c65fa61bb20df75a9701b4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 22 Nov 2003 13:19:38 +0000 Subject: Changes all over the shop, but all towards: - NTLM2 support in the server - KEY_EXCH support in the server - variable length session keys. In detail: - NTLM2 is an extension of NTLMv1, that is compatible with existing domain controllers (unlike NTLMv2, which requires a DC upgrade). * This is known as 'NTLMv2 session security' * (This is not yet implemented on the RPC pipes however, so there may well still be issues for PDC setups, particuarly around password changes. We do not fully understand the sign/seal implications of NTLM2 on RPC pipes.) This requires modifications to our authentication subsystem, as we must handle the 'challege' input into the challenge-response algorithm being changed. This also needs to be turned off for 'security=server', which does not support this. - KEY_EXCH is another 'security' mechanism, whereby the session key actually used by the server is sent by the client, rather than being the shared-secret directly or indirectly. - As both these methods change the session key, the auth subsystem needed to be changed, to 'override' session keys provided by the backend. - There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation. - The 'names blob' in NTLMSSP is always in unicode - never in ascii. Don't make an ascii version ever. - The other big change is to allow variable length session keys. We have always assumed that session keys are 16 bytes long - and padded to this length if shorter. However, Kerberos session keys are 8 bytes long, when the krb5 login uses DES. * This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. * - Add better DEBUG() messages to ntlm_auth, warning administrators of misconfigurations that prevent access to the privileged pipe. This should help reduce some of the 'it just doesn't work' issues. - Fix data_blob_talloc() to behave the same way data_blob() does when passed a NULL data pointer. (just allocate) REMEMBER to make clean after this commit - I have changed plenty of data structures... (This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc) --- source3/libsmb/ntlmssp.c | 741 +++++++++++++++++++++++++++++++---------------- 1 file changed, 496 insertions(+), 245 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index c51b599b04..a0da1efcc1 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -23,6 +23,35 @@ #include "includes.h" +static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, + DATA_BLOB reply, DATA_BLOB *next_request); +static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, + const DATA_BLOB in, DATA_BLOB *out); +static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, + const DATA_BLOB reply, DATA_BLOB *next_request); +static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, + const DATA_BLOB request, DATA_BLOB *reply); + +/** + * Callbacks for NTLMSSP - for both client and server operating modes + * + */ + +static const struct ntlmssp_callbacks { + enum NTLMSSP_ROLE role; + enum NTLM_MESSAGE_TYPE ntlmssp_command; + NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state, + DATA_BLOB in, DATA_BLOB *out); +} ntlmssp_callbacks[] = { + {NTLMSSP_CLIENT, NTLMSSP_INITIAL, ntlmssp_client_initial}, + {NTLMSSP_SERVER, NTLMSSP_NEGOTIATE, ntlmssp_server_negotiate}, + {NTLMSSP_CLIENT, NTLMSSP_CHALLENGE, ntlmssp_client_challenge}, + {NTLMSSP_SERVER, NTLMSSP_AUTH, ntlmssp_server_auth}, + {NTLMSSP_CLIENT, NTLMSSP_UNKNOWN, NULL}, + {NTLMSSP_SERVER, NTLMSSP_UNKNOWN, NULL} +}; + + /** * Print out the NTLMSSP flags for debugging * @param neg_flags The flags from the packet @@ -71,7 +100,7 @@ void debug_ntlmssp_flags(uint32 neg_flags) * */ -static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state) +static const uint8 *get_challenge(const struct ntlmssp_state *ntlmssp_state) { static uchar chal[8]; generate_random_buffer(chal, sizeof(chal), False); @@ -79,6 +108,188 @@ static const uint8 *get_challenge(struct ntlmssp_state *ntlmssp_state) return chal; } +/** + * Default 'we can set the challenge to anything we like' implementation + * + */ + +static BOOL may_set_challenge(const struct ntlmssp_state *ntlmssp_state) +{ + return True; +} + +/** + * Default 'we can set the challenge to anything we like' implementation + * + * Does not actually do anything, as the value is always in the structure anyway. + * + */ + +static NTSTATUS set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge) +{ + SMB_ASSERT(challenge->length == 8); + return NT_STATUS_OK; +} + +/** + * Set a username on an NTLMSSP context - ensures it is talloc()ed + * + */ + +NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user) +{ + ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user); + if (!ntlmssp_state->user) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +/** + * Set a password on an NTLMSSP context - ensures it is talloc()ed + * + */ +NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password) +{ + 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; +} + +/** + * Set a domain on an NTLMSSP context - ensures it is talloc()ed + * + */ +NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain) +{ + ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain); + if (!ntlmssp_state->domain) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +/** + * Set a workstation on an NTLMSSP context - ensures it is talloc()ed + * + */ +NTSTATUS ntlmssp_set_workstation(NTLMSSP_STATE *ntlmssp_state, const char *workstation) +{ + ntlmssp_state->workstation = talloc_strdup(ntlmssp_state->mem_ctx, workstation); + if (!ntlmssp_state->domain) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +/** + * Store a DATA_BLOB containing an NTLMSSP response, for use later. + * This copies the data blob + */ + +NTSTATUS ntlmssp_store_response(NTLMSSP_STATE *ntlmssp_state, + DATA_BLOB response) +{ + ntlmssp_state->stored_response = data_blob_talloc(ntlmssp_state->mem_ctx, + response.data, response.length); + return NT_STATUS_OK; +} + +/** + * Next state function for the NTLMSSP state machine + * + * @param ntlmssp_state NTLMSSP State + * @param in The packet in from the NTLMSSP partner, as a DATA_BLOB + * @param out The reply, as an allocated DATA_BLOB, caller to free. + * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK. + */ + +NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state, + const DATA_BLOB in, DATA_BLOB *out) +{ + DATA_BLOB input; + uint32 ntlmssp_command; + int i; + + *out = data_blob(NULL, 0); + + if (!in.length && ntlmssp_state->stored_response.length) { + input = ntlmssp_state->stored_response; + + /* we only want to read the stored response once - overwrite it */ + ntlmssp_state->stored_response = data_blob(NULL, 0); + } else { + input = in; + } + + if (!input.length) { + switch (ntlmssp_state->role) { + case NTLMSSP_CLIENT: + ntlmssp_command = NTLMSSP_INITIAL; + break; + case NTLMSSP_SERVER: + /* 'datagram' mode - no neg packet */ + ntlmssp_command = NTLMSSP_NEGOTIATE; + break; + } + } else { + if (!msrpc_parse(&input, "Cd", + "NTLMSSP", + &ntlmssp_command)) { + DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n")); + dump_data(2, (const char *)input.data, input.length); + return NT_STATUS_INVALID_PARAMETER; + } + } + + if (ntlmssp_command != ntlmssp_state->expected_state) { + DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); + return NT_STATUS_INVALID_PARAMETER; + } + + for (i=0; ntlmssp_callbacks[i].fn; i++) { + if (ntlmssp_callbacks[i].role == ntlmssp_state->role + && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) { + return ntlmssp_callbacks[i].fn(ntlmssp_state, input, out); + } + } + + DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n", + ntlmssp_state->role, ntlmssp_command)); + + return NT_STATUS_INVALID_PARAMETER; +} + +/** + * End an NTLMSSP state machine + * + * @param ntlmssp_state NTLMSSP State, free()ed by this function + */ + +void ntlmssp_end(NTLMSSP_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; + + (*ntlmssp_state)->ref_count--; + + if ((*ntlmssp_state)->ref_count == 0) { + data_blob_free(&(*ntlmssp_state)->chal); + data_blob_free(&(*ntlmssp_state)->lm_resp); + data_blob_free(&(*ntlmssp_state)->nt_resp); + + talloc_destroy(mem_ctx); + } + + *ntlmssp_state = NULL; + return; +} + /** * Determine correct target name flags for reply, given server role * and negotiated flags @@ -107,6 +318,46 @@ static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state, } } +static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, + uint32 neg_flags, BOOL allow_lm) { + if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM; + ntlmssp_state->unicode = True; + } else { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE; + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; + ntlmssp_state->unicode = False; + } + + if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY && allow_lm) { + /* other end forcing us to use LM */ + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; + ntlmssp_state->use_ntlmv2 = False; + } else { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; + } + + if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; + } + + if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; + } + + if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH; + } + + if ((neg_flags & NTLMSSP_REQUEST_TARGET)) { + ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET; + } + +} + + /** * Next state function for the Negotiate packet * @@ -150,31 +401,27 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, debug_ntlmssp_flags(neg_flags); } - cryptkey = ntlmssp_state->get_challenge(ntlmssp_state); + ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth()); - data_blob_free(&ntlmssp_state->chal); - ntlmssp_state->chal = data_blob(cryptkey, 8); - - /* Give them the challenge. For now, ignore neg_flags and just - return the flags we want. Obviously this is not correct */ - - chal_flags = - NTLMSSP_NEGOTIATE_128 | - NTLMSSP_NEGOTIATE_NTLM; - - if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { - chal_flags |= NTLMSSP_NEGOTIATE_UNICODE; - ntlmssp_state->unicode = True; - } else { - chal_flags |= NTLMSSP_NEGOTIATE_OEM; - } + chal_flags = ntlmssp_state->neg_flags; target_name = ntlmssp_target_name(ntlmssp_state, neg_flags, &chal_flags); - - if (target_name == NULL) + if (target_name == NULL) return NT_STATUS_INVALID_PARAMETER; + /* Ask our caller what challenge they would like in the packet */ + cryptkey = ntlmssp_state->get_challenge(ntlmssp_state); + + /* Check if we may set the challenge */ + if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; + } + + ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8); + ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8); + + /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname[0] = '\0'; get_mydomname(dnsdomname); @@ -184,6 +431,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, get_myfullname(dnsname); strlower_m(dnsname); + /* This creates the 'blob' of names that appears at the end of the packet */ if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { const char *target_name_dns = ""; @@ -194,16 +442,17 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, } msrpc_gen(&struct_blob, "aaaaa", - ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN, target_name, - ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), - ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN_DNS, target_name_dns, - ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER_DNS, dnsdomname, - ntlmssp_state->unicode, 0, ""); + NTLMSSP_NAME_TYPE_DOMAIN, target_name, + NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), + NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsdomname, + NTLMSSP_NAME_TYPE_SERVER_DNS, dnsname, + 0, ""); } else { struct_blob = data_blob(NULL, 0); } { + /* Marshel the packet in the right format, be it unicode or ASCII */ const char *gen_string; if (ntlmssp_state->unicode) { gen_string = "CdUdbddB"; @@ -240,13 +489,27 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, const DATA_BLOB request, DATA_BLOB *reply) { - DATA_BLOB sess_key; - uint32 ntlmssp_command, neg_flags; + DATA_BLOB encrypted_session_key = data_blob(NULL, 0); + DATA_BLOB nt_session_key = data_blob(NULL, 0); + DATA_BLOB lm_session_key = data_blob(NULL, 0); + DATA_BLOB session_key = data_blob(NULL, 0); + uint32 ntlmssp_command, auth_flags; NTSTATUS nt_status; + /* used by NTLM2 */ + BOOL doing_ntlm2 = False; + + uchar session_nonce[16]; + uchar session_nonce_hash[16]; + const char *parse_string; + char *domain = NULL; + char *user = NULL; + char *workstation = NULL; /* parse the NTLMSSP packet */ + *reply = data_blob(NULL, 0); + #if 0 file_save("ntlmssp_auth.dat", request.data, request.length); #endif @@ -260,9 +523,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, data_blob_free(&ntlmssp_state->lm_resp); data_blob_free(&ntlmssp_state->nt_resp); - SAFE_FREE(ntlmssp_state->user); - SAFE_FREE(ntlmssp_state->domain); - SAFE_FREE(ntlmssp_state->workstation); + ntlmssp_state->user = NULL; + ntlmssp_state->domain = NULL; + ntlmssp_state->workstation = NULL; /* now the NTLMSSP encoded auth hashes */ if (!msrpc_parse(&request, parse_string, @@ -270,18 +533,73 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, &ntlmssp_command, &ntlmssp_state->lm_resp, &ntlmssp_state->nt_resp, - &ntlmssp_state->domain, - &ntlmssp_state->user, - &ntlmssp_state->workstation, - &sess_key, - &neg_flags)) { + &domain, + &user, + &workstation, + &encrypted_session_key, + &auth_flags)) { DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); dump_data(2, (const char *)request.data, request.length); - return NT_STATUS_INVALID_PARAMETER; + SAFE_FREE(domain); + SAFE_FREE(user); + SAFE_FREE(workstation); + data_blob_free(&encrypted_session_key); + auth_flags = 0; + + /* Try again with a shorter string (Win9X truncates this packet) */ + if (ntlmssp_state->unicode) { + parse_string = "CdBBUUU"; + } else { + parse_string = "CdBBAAA"; + } + + /* now the NTLMSSP encoded auth hashes */ + if (!msrpc_parse(&request, parse_string, + "NTLMSSP", + &ntlmssp_command, + &ntlmssp_state->lm_resp, + &ntlmssp_state->nt_resp, + &domain, + &user, + &workstation)) { + DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); + dump_data(2, (const char *)request.data, request.length); + SAFE_FREE(domain); + SAFE_FREE(user); + SAFE_FREE(workstation); + + return NT_STATUS_INVALID_PARAMETER; + } } - data_blob_free(&sess_key); - + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) { + SAFE_FREE(domain); + SAFE_FREE(user); + SAFE_FREE(workstation); + data_blob_free(&encrypted_session_key); + return nt_status; + } + + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) { + SAFE_FREE(domain); + SAFE_FREE(user); + SAFE_FREE(workstation); + data_blob_free(&encrypted_session_key); + return nt_status; + } + + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) { + SAFE_FREE(domain); + SAFE_FREE(user); + SAFE_FREE(workstation); + data_blob_free(&encrypted_session_key); + return nt_status; + } + + SAFE_FREE(domain); + SAFE_FREE(user); + SAFE_FREE(workstation); + DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n", ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length)); @@ -290,9 +608,98 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length); #endif - nt_status = ntlmssp_state->check_password(ntlmssp_state); + /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a + client challenge - *reply = data_blob(NULL, 0); + However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful. + */ + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) { + struct MD5Context md5_session_nonce_ctx; + SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8); + + doing_ntlm2 = True; + + memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8); + memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8); + + MD5Init(&md5_session_nonce_ctx); + MD5Update(&md5_session_nonce_ctx, session_nonce, 16); + MD5Final(session_nonce_hash, &md5_session_nonce_ctx); + + ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, session_nonce_hash, 8); + + /* LM response is no longer useful */ + data_blob_free(&ntlmssp_state->lm_resp); + + /* We changed the effective challenge - set it */ + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) { + data_blob_free(&encrypted_session_key); + return nt_status; + } + } + } + + /* Finally, actually ask if the password is OK */ + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, &nt_session_key, &lm_session_key))) { + data_blob_free(&encrypted_session_key); + return nt_status; + } + + dump_data_pw("NT session key:\n", nt_session_key.data, nt_session_key.length); + dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length); + + /* Handle the different session key derivation for NTLM2 */ + if (doing_ntlm2) { + if (nt_session_key.data && nt_session_key.length == 16) { + session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); + hmac_md5(nt_session_key.data, session_nonce, + sizeof(session_nonce), session_key.data); + dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); + + } + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { + if (lm_session_key.data && lm_session_key.length >= 8 && + ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) { + session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); + SMBsesskeygen_lmv1(lm_session_key.data, ntlmssp_state->lm_resp.data, + session_key.data); + dump_data_pw("LM session key:\n", session_key.data, session_key.length); + } + } else if (nt_session_key.data) { + session_key = nt_session_key; + dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); + } + + /* With KEY_EXCH, the client supplies the proposed session key, + but encrypts it with the long-term key */ + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { + if (!encrypted_session_key.data || encrypted_session_key.length != 16) { + data_blob_free(&encrypted_session_key); + DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", + encrypted_session_key.length)); + return NT_STATUS_INVALID_PARAMETER; + } else if (!session_key.data || session_key.length != 16) { + DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", + session_key.length)); + } else { + dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); + SamOEMhash(encrypted_session_key.data, + session_key.data, + encrypted_session_key.length); + ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx, + encrypted_session_key.data, + encrypted_session_key.length); + dump_data_pw("KEY_EXCH session key:\n", session_key.data, session_key.length); + } + } else { + ntlmssp_state->session_key = session_key; + } + + data_blob_free(&encrypted_session_key); + + /* allow arbitarily many authentications */ + ntlmssp_state->expected_state = NTLMSSP_AUTH; return nt_status; } @@ -316,8 +723,12 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) return NT_STATUS_NO_MEMORY; } + (*ntlmssp_state)->role = NTLMSSP_SERVER; + (*ntlmssp_state)->mem_ctx = mem_ctx; (*ntlmssp_state)->get_challenge = get_challenge; + (*ntlmssp_state)->set_challenge = set_challenge; + (*ntlmssp_state)->may_set_challenge = may_set_challenge; (*ntlmssp_state)->get_global_myname = global_myname; (*ntlmssp_state)->get_domain = lp_workgroup; @@ -325,73 +736,18 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) (*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE; - return NT_STATUS_OK; -} - -/** - * End an NTLMSSP state machine - * - * @param ntlmssp_state NTLMSSP State, free()ed by this function - */ - -NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state) -{ - TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; - - data_blob_free(&(*ntlmssp_state)->chal); - data_blob_free(&(*ntlmssp_state)->lm_resp); - data_blob_free(&(*ntlmssp_state)->nt_resp); + (*ntlmssp_state)->ref_count = 1; - SAFE_FREE((*ntlmssp_state)->user); - SAFE_FREE((*ntlmssp_state)->domain); - SAFE_FREE((*ntlmssp_state)->workstation); + (*ntlmssp_state)->neg_flags = + NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_NEGOTIATE_NTLM2 | + NTLMSSP_NEGOTIATE_KEY_EXCH | + NTLMSSP_NEGOTIATE_SIGN; - talloc_destroy(mem_ctx); - *ntlmssp_state = NULL; return NT_STATUS_OK; } -/** - * Next state function for the NTLMSSP state machine - * - * @param ntlmssp_state NTLMSSP State - * @param request The request, as a DATA_BLOB - * @param request The reply, as an allocated DATA_BLOB, caller to free. - * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK. - */ - -NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, - const DATA_BLOB request, DATA_BLOB *reply) -{ - uint32 ntlmssp_command; - *reply = data_blob(NULL, 0); - - if (request.length) { - if (!msrpc_parse(&request, "Cd", - "NTLMSSP", - &ntlmssp_command)) { - return NT_STATUS_INVALID_PARAMETER; - } - } else { - /* 'datagram' mode - no neg packet */ - ntlmssp_command = NTLMSSP_NEGOTIATE; - } - - if (ntlmssp_command != ntlmssp_state->expected_state) { - DEBUG(1, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); - return NT_STATUS_INVALID_PARAMETER; - } - - if (ntlmssp_command == NTLMSSP_NEGOTIATE) { - return ntlmssp_server_negotiate(ntlmssp_state, request, reply); - } else if (ntlmssp_command == NTLMSSP_AUTH) { - return ntlmssp_server_auth(ntlmssp_state, request, reply); - } else { - DEBUG(1, ("unknown NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); - return NT_STATUS_INVALID_PARAMETER; - } -} - /********************************************************************* Client side NTLMSSP *********************************************************************/ @@ -405,11 +761,13 @@ NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, * @return Errors or NT_STATUS_OK. */ -static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_state, +static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, DATA_BLOB reply, DATA_BLOB *next_request) { if (ntlmssp_state->unicode) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; + } else { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; } if (ntlmssp_state->use_ntlmv2) { @@ -426,6 +784,8 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat ntlmssp_state->get_domain(), ntlmssp_state->get_global_myname()); + ntlmssp_state->expected_state = NTLMSSP_CHALLENGE; + return NT_STATUS_MORE_PROCESSING_REQUIRED; } @@ -438,7 +798,7 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat * @return Errors or NT_STATUS_OK. */ -static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_state, +static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, const DATA_BLOB reply, DATA_BLOB *next_request) { uint32 chal_flags, ntlmssp_command, unkn1, unkn2; @@ -469,17 +829,16 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st DEBUG(3, ("Got challenge flags:\n")); debug_ntlmssp_flags(chal_flags); - if (chal_flags & NTLMSSP_NEGOTIATE_UNICODE) { + ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth()); + + if (ntlmssp_state->unicode) { if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { chal_parse_string = "CdUdbddB"; } else { chal_parse_string = "CdUdbdd"; } auth_gen_string = "CdBBUUUBd"; - ntlmssp_state->unicode = True; - ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; - ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM; - } else if (chal_flags & NTLMSSP_NEGOTIATE_OEM) { + } else { if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { chal_parse_string = "CdAdbddB"; } else { @@ -487,32 +846,6 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st } auth_gen_string = "CdBBAAABd"; - - ntlmssp_state->unicode = False; - ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE; - ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; - } else { - return NT_STATUS_INVALID_PARAMETER; - } - - if (chal_flags & NTLMSSP_NEGOTIATE_LM_KEY && lp_client_lanman_auth()) { - /* server forcing us to use LM */ - ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; - ntlmssp_state->use_ntlmv2 = False; - } else { - ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; - } - - if (!(chal_flags & NTLMSSP_NEGOTIATE_NTLM2)) { - ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; - } - - if (!(chal_flags & NTLMSSP_NEGOTIATE_128)) { - 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")); @@ -546,6 +879,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st if (!struct_blob.length) { /* be lazy, match win2k - we can't do NTLMv2 without it */ + DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n")); return NT_STATUS_INVALID_PARAMETER; } @@ -569,7 +903,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st uchar nt_session_key[16]; E_md4hash(ntlmssp_state->password, nt_hash); - lm_response = data_blob(NULL, 24); + lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); generate_random_buffer(lm_response.data, 8, False); memset(lm_response.data+8, 0, 16); @@ -580,16 +914,21 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st 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); + + DEBUG(5, ("NTLMSSP challenge set by NTLM2\n")); + DEBUG(5, ("challenge is: \n")); + dump_data(5, session_nonce_hash, 8); - nt_response = data_blob(NULL, 24); + nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); SMBNTencrypt(ntlmssp_state->password, session_nonce_hash, nt_response.data); - session_key = data_blob(NULL, 16); + session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); SMBsesskeygen_ntv1(nt_hash, NULL, nt_session_key); hmac_md5(nt_session_key, session_nonce, sizeof(session_nonce), session_key.data); + dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { @@ -600,22 +939,24 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st /* lanman auth is insecure, it may be disabled */ if (lp_client_lanman_auth()) { - lm_response = data_blob(NULL, 24); + lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); SMBencrypt(ntlmssp_state->password,challenge_blob.data, lm_response.data); - } + } - nt_response = data_blob(NULL, 24); + nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); SMBNTencrypt(ntlmssp_state->password,challenge_blob.data, nt_response.data); - session_key = data_blob(NULL, 16); + session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && lp_client_lanman_auth()) { SMBsesskeygen_lmv1(lm_hash, lm_response.data, session_key.data); + dump_data_pw("LM session key\n", session_key.data, session_key.length); } else { SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + dump_data_pw("NT session key:\n", session_key.data, session_key.length); } } data_blob_free(&struct_blob); @@ -627,9 +968,12 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st generate_random_buffer(client_session_key, sizeof(client_session_key), False); encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key)); + dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length); + 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)); + session_key = data_blob_talloc(ntlmssp_state->mem_ctx, client_session_key, sizeof(client_session_key)); + dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); } /* this generates the actual auth packet */ @@ -644,28 +988,24 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st encrypted_session_key.data, encrypted_session_key.length, ntlmssp_state->neg_flags)) { - data_blob_free(&lm_response); - data_blob_free(&nt_response); - data_blob_free(&session_key); 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); - data_blob_free(&ntlmssp_state->session_key); ntlmssp_state->chal = challenge_blob; ntlmssp_state->lm_resp = lm_response; ntlmssp_state->nt_resp = nt_response; ntlmssp_state->session_key = session_key; + ntlmssp_state->expected_state = NTLMSSP_UNKNOWN; + return NT_STATUS_MORE_PROCESSING_REQUIRED; } -NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) +NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) { TALLOC_CTX *mem_ctx; @@ -678,6 +1018,8 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) return NT_STATUS_NO_MEMORY; } + (*ntlmssp_state)->role = NTLMSSP_CLIENT; + (*ntlmssp_state)->mem_ctx = mem_ctx; (*ntlmssp_state)->get_global_myname = global_myname; @@ -687,6 +1029,10 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) (*ntlmssp_state)->use_ntlmv2 = lp_client_ntlmv2_auth(); + (*ntlmssp_state)->expected_state = NTLMSSP_INITIAL; + + (*ntlmssp_state)->ref_count = 1; + (*ntlmssp_state)->neg_flags = NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_NTLM | @@ -700,101 +1046,6 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_REQUEST_TARGET; - (*ntlmssp_state)->ref_count = 1; - - return NT_STATUS_OK; -} - -NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state) -{ - TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; - - (*ntlmssp_state)->ref_count--; - - if ((*ntlmssp_state)->ref_count == 0) { - data_blob_free(&(*ntlmssp_state)->chal); - data_blob_free(&(*ntlmssp_state)->lm_resp); - data_blob_free(&(*ntlmssp_state)->nt_resp); - data_blob_free(&(*ntlmssp_state)->session_key); - data_blob_free(&(*ntlmssp_state)->stored_response); - talloc_destroy(mem_ctx); - } - - *ntlmssp_state = NULL; return NT_STATUS_OK; } -NTSTATUS ntlmssp_client_update(NTLMSSP_CLIENT_STATE *ntlmssp_state, - DATA_BLOB reply, DATA_BLOB *next_request) -{ - NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; - uint32 ntlmssp_command; - *next_request = data_blob(NULL, 0); - - if (!reply.length) { - /* If there is a cached reply, use it - otherwise this is the first packet */ - if (!ntlmssp_state->stored_response.length) { - return ntlmssp_client_initial(ntlmssp_state, reply, next_request); - } - - reply = ntlmssp_state->stored_response; - } - - if (!msrpc_parse(&reply, "Cd", - "NTLMSSP", - &ntlmssp_command)) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (ntlmssp_command == NTLMSSP_CHALLENGE) { - nt_status = ntlmssp_client_challenge(ntlmssp_state, reply, next_request); - } - if (ntlmssp_state->stored_response.length) { - data_blob_free(&ntlmssp_state->stored_response); - } - return nt_status; -} - -NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *user) -{ - ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user); - if (!ntlmssp_state->user) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -NTSTATUS ntlmssp_set_password(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *password) -{ - 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; -} - -NTSTATUS ntlmssp_set_domain(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *domain) -{ - ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain); - if (!ntlmssp_state->domain) { - return NT_STATUS_NO_MEMORY; - } - return NT_STATUS_OK; -} - -/** - * Store a DATA_BLOB containing an NTLMSSP response, for use later. - * This 'keeps' the data blob - the caller must *not* free it. - */ - -NTSTATUS ntlmssp_client_store_response(NTLMSSP_CLIENT_STATE *ntlmssp_state, - DATA_BLOB response) -{ - data_blob_free(&ntlmssp_state->stored_response); - ntlmssp_state->stored_response = response; - return NT_STATUS_OK; -} -- cgit From 1b6e6c98ba7175afb994a531bec06a7845950ff3 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 25 Nov 2003 11:25:38 +0000 Subject: Do not add NTLM2 to the NTLMSSP flags unconditionally - allow the defaults specified by the caller to prevail. Don't use NTLM2 for RPC pipes, until we know how it works in signing or sealing. Call ntlmssp_sign_init() unconditionally in the client - we setup the session key, why not setup the rest of the data. Andrew Bartlett (This used to be commit 48123f7e42c3fde85887de23c80ceee04c2f6281) --- source3/libsmb/ntlmssp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index a0da1efcc1..d361196047 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -774,8 +774,6 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; } - ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; - /* generate the ntlmssp negotiate packet */ msrpc_gen(next_request, "CddAA", "NTLMSSP", @@ -812,6 +810,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB encrypted_session_key = data_blob(NULL, 0); + NTSTATUS nt_status; if (!msrpc_parse(&reply, "CdBd", "NTLMSSP", @@ -1002,6 +1001,11 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->expected_state = NTLMSSP_UNKNOWN; + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) { + DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status))); + return nt_status; + } + return NT_STATUS_MORE_PROCESSING_REQUIRED; } -- cgit From 88dad93acb6b2c62ae08d27752ed6b4ab87e7ad0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 4 Dec 2003 04:16:16 +0000 Subject: Picked up by the build farm - despite all my efforts, security=server was broken by my NTLM2 commit. This should correctly cause the NTLM2 case not to be negotiated when 'security=server' is in effect. Andrew Bartlett (This used to be commit 19bb4b582f98eb1da41e22c9a2a2c11602cb95e4) --- source3/libsmb/ntlmssp.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index d361196047..ca1aa67403 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -340,7 +340,6 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) { ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; - ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; } if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) { @@ -403,13 +402,6 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth()); - chal_flags = ntlmssp_state->neg_flags; - - target_name = ntlmssp_target_name(ntlmssp_state, - neg_flags, &chal_flags); - if (target_name == NULL) - return NT_STATUS_INVALID_PARAMETER; - /* Ask our caller what challenge they would like in the packet */ cryptkey = ntlmssp_state->get_challenge(ntlmssp_state); @@ -418,6 +410,19 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; } + /* The flags we send back are not just the negotiated flags, + * they are also 'what is in this packet'. Therfore, we + * operate on 'chal_flags' from here on + */ + + chal_flags = ntlmssp_state->neg_flags; + + /* get the right name to fill in as 'target' */ + target_name = ntlmssp_target_name(ntlmssp_state, + neg_flags, &chal_flags); + if (target_name == NULL) + return NT_STATUS_INVALID_PARAMETER; + ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8); ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8); -- cgit From 54cff4535e8237c43977faa372ebac8baf88b034 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 17 Dec 2003 06:18:13 +0000 Subject: Make sure we correctly generate the lm session key. This fixes a problem joining a Samba domain from a vanilla win2k client that doesn't set the NTLMSSP_NEGOTIATE_NTLM2 flag. Reported on samba ml as "decode_pw: incorrect password length" when handling a samr_set_userinfo(23 or 24) RPC. (This used to be commit ef4ab8d7c497e4229d0c1deeb20d05c95bd8feb9) --- source3/libsmb/ntlmssp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index ca1aa67403..3cfd6d2043 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -660,6 +660,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); hmac_md5(nt_session_key.data, session_nonce, sizeof(session_nonce), session_key.data); + DEBUG(10,("NTLM2 session key set\n")); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } @@ -667,12 +668,14 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, if (lm_session_key.data && lm_session_key.length >= 8 && ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) { session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); - SMBsesskeygen_lmv1(lm_session_key.data, ntlmssp_state->lm_resp.data, + SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, session_key.data); + DEBUG(10,("LM KEY session key set\n")); dump_data_pw("LM session key:\n", session_key.data, session_key.length); } } else if (nt_session_key.data) { session_key = nt_session_key; + DEBUG(10,("unmodified session key set\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } @@ -695,7 +698,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx, encrypted_session_key.data, encrypted_session_key.length); - dump_data_pw("KEY_EXCH session key:\n", session_key.data, session_key.length); + dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, + encrypted_session_key.length); } } else { ntlmssp_state->session_key = session_key; -- cgit From 93a983b7cbac4ee1d967627aa3bfd15f3f0311ea Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Dec 2003 20:11:39 +0000 Subject: Tidyup debug message in ntlmssp code. Add brackets around dodgy if statement. Jeremy (This used to be commit 5aab4b976c0aced68d71c1e71e85287072a6f3c7) --- source3/libsmb/ntlmssp.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 3cfd6d2043..10f2983180 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -330,7 +330,7 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->unicode = False; } - if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY && allow_lm) { + if ((neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && allow_lm) { /* other end forcing us to use LM */ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; ntlmssp_state->use_ntlmv2 = False; @@ -660,9 +660,13 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); hmac_md5(nt_session_key.data, session_nonce, sizeof(session_nonce), session_key.data); - DEBUG(10,("NTLM2 session key set\n")); + DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n")); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); + }else { + data_blob_free(&encrypted_session_key); + DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n")); + return NT_STATUS_INVALID_PARAMETER; } } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { if (lm_session_key.data && lm_session_key.length >= 8 && @@ -670,13 +674,21 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, session_key.data); - DEBUG(10,("LM KEY session key set\n")); + DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); dump_data_pw("LM session key:\n", session_key.data, session_key.length); + } else { + data_blob_free(&encrypted_session_key); + DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); + return NT_STATUS_INVALID_PARAMETER; } } else if (nt_session_key.data) { session_key = nt_session_key; - DEBUG(10,("unmodified session key set\n")); + DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); + } else { + data_blob_free(&encrypted_session_key); + DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified nt session key.\n")); + return NT_STATUS_INVALID_PARAMETER; } /* With KEY_EXCH, the client supplies the proposed session key, @@ -1026,7 +1038,7 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state)); if (!*ntlmssp_state) { - DEBUG(0,("ntlmssp_server_start: talloc failed!\n")); + DEBUG(0,("ntlmssp_client_start: talloc failed!\n")); talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } -- cgit From 68e692738b30f746a99a4392dd438ccdf14d95e0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Dec 2003 21:57:26 +0000 Subject: Add in comments explaining NTLMv2 selection. Use lm session key if that's all there is. Jeremy. (This used to be commit b611f8d170743f1f4d71b1def83bb757d9f467af) --- source3/libsmb/ntlmssp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 10f2983180..7b821da0fd 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -645,7 +645,15 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } } + /* + * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth + * is required (by "ntlm auth = no" and "lm auth = no" being set in the + * smb.conf file) and no NTLMv2 response was sent then the password check + * will fail here. JRA. + */ + /* Finally, actually ask if the password is OK */ + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, &nt_session_key, &lm_session_key))) { data_blob_free(&encrypted_session_key); return nt_status; @@ -685,9 +693,13 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, session_key = nt_session_key; DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); + } else if (lm_session_key.data) { + session_key = lm_session_key; + DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n")); + dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } else { data_blob_free(&encrypted_session_key); - DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified nt session key.\n")); + DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n")); return NT_STATUS_INVALID_PARAMETER; } -- cgit From f73492a58aba4239a9e00cc1bfca51362ca6a9b8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 27 Dec 2003 11:33:24 +0000 Subject: This patch corrects some errors in the NTLMSSP implementation, that would incorrectly return INVALID_PARAMETER, instead of allowing a login. Andrew Bartlett (This used to be commit 76c59469a340209959c420bd5c2e947d3347bdb1) --- source3/libsmb/ntlmssp.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 7b821da0fd..7026a02726 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -577,6 +577,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } } + if (auth_flags) + ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth()); + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) { SAFE_FREE(domain); SAFE_FREE(user); @@ -670,20 +673,26 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, sizeof(session_nonce), session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n")); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); - - }else { + + } else { data_blob_free(&encrypted_session_key); DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n")); return NT_STATUS_INVALID_PARAMETER; } } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { - if (lm_session_key.data && lm_session_key.length >= 8 && - ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) { - session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); - SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, - session_key.data); - DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); - dump_data_pw("LM session key:\n", session_key.data, session_key.length); + if (lm_session_key.data && lm_session_key.length >= 8) { + if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) { + session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); + SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, + session_key.data); + DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); + dump_data_pw("LM session key:\n", session_key.data, session_key.length); + } else { + /* use the key unmodified - it's + * probably a NULL key from the guest + * login */ + session_key = lm_session_key; + } } else { data_blob_free(&encrypted_session_key); DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); -- cgit From 4cc701196e2a3603b62ae3ad8c8178fadcfa853b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 3 Jan 2004 01:12:56 +0000 Subject: There is not a particularly good excuse for complaining to the *client* that it sent 'INVALID_PARAMETER', when it was us as the server that could not come up with a session key. Instead, allow normal authentication to take place, but do not setup a session key. Andrew Bartlett (This used to be commit e5abd93d799e5f86839560feca448743c13a9055) --- source3/libsmb/ntlmssp.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 7026a02726..e58104367f 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -657,7 +657,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, /* Finally, actually ask if the password is OK */ - if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, &nt_session_key, &lm_session_key))) { + if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, + &nt_session_key, &lm_session_key))) { data_blob_free(&encrypted_session_key); return nt_status; } @@ -677,7 +678,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } else { data_blob_free(&encrypted_session_key); DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n")); - return NT_STATUS_INVALID_PARAMETER; + session_key = data_blob(NULL, 0); } } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { if (lm_session_key.data && lm_session_key.length >= 8) { @@ -696,7 +697,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } else { data_blob_free(&encrypted_session_key); DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); - return NT_STATUS_INVALID_PARAMETER; + session_key = data_blob(NULL, 0); } } else if (nt_session_key.data) { session_key = nt_session_key; @@ -709,7 +710,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } else { data_blob_free(&encrypted_session_key); DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n")); - return NT_STATUS_INVALID_PARAMETER; + session_key = data_blob(NULL, 0); } /* With KEY_EXCH, the client supplies the proposed session key, @@ -915,7 +916,14 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, } if (!ntlmssp_state->password) { + static const uchar zeros[16]; /* do nothing - blobs are zero length */ + + /* session key is all zeros */ + session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16); + + /* not doing NLTM2 without a password */ + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; } else if (ntlmssp_state->use_ntlmv2) { if (!struct_blob.length) { -- cgit From e8984d6b9aac91082af745d22a4b195a1be5dee4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 5 Jan 2004 00:11:02 +0000 Subject: Automaticly initialise the signing engine, if we have a session key. (This used to be commit cb063c1b6949a2a9637689537c6ab8dc881bc568) --- source3/libsmb/ntlmssp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index e58104367f..85ae279758 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -739,6 +739,12 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->session_key = session_key; } + if (!NT_STATUS_IS_OK(nt_status)) { + ntlmssp_state->session_key = data_blob(NULL, 0); + } else if (ntlmssp_state->session_key.length) { + nt_status = ntlmssp_sign_init(ntlmssp_state); + } + data_blob_free(&encrypted_session_key); /* allow arbitarily many authentications */ -- cgit From ed55d03c8a087b9a3df9764d3c983bf59af1defc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 5 Jan 2004 12:36:21 +0000 Subject: Don't free the encrypted_session_key early - that causes the subsequent test for a valid length to fail... This should fix 'security=server' and hosts-equiv failures picked up by the build farm. Andrew Bartlett (This used to be commit 39311495de3bd0a902f730967f30176db97be05a) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 85ae279758..0ab51dc960 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -708,7 +708,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } else { - data_blob_free(&encrypted_session_key); DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n")); session_key = data_blob(NULL, 0); } @@ -724,6 +723,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } else if (!session_key.data || session_key.length != 16) { DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", session_key.length)); + ntlmssp_state->session_key = session_key; } else { dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); SamOEMhash(encrypted_session_key.data, -- cgit From 2ed5a1a340598374a61e9eec9221598c26e749db Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 5 Jan 2004 19:21:06 +0000 Subject: Ensure we set "always sign" flag if set. We don't currently do anything with this but we should log the fact it was negotiated. Jeremy. (This used to be commit 84d34e32be03ec99ce19520f24bb4daaeeddbbc3) --- source3/libsmb/ntlmssp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 0ab51dc960..95fd4c03e5 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -338,6 +338,10 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; } + if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + } + if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) { ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; } -- cgit From cfa4469c1e1a323ac27b502596f88695f463a738 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 5 Jan 2004 21:24:27 +0000 Subject: Fix more cases to ensure that as a server, we don't complain to the client about our server-side lack of session key. Andrew Bartlett (This used to be commit ba33f1e0d5fe2aed3e378c9c23511c0b4d6f7d14) --- source3/libsmb/ntlmssp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 95fd4c03e5..40d7f41109 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -680,7 +680,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { - data_blob_free(&encrypted_session_key); DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n")); session_key = data_blob(NULL, 0); } @@ -699,7 +698,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, session_key = lm_session_key; } } else { - data_blob_free(&encrypted_session_key); DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); session_key = data_blob(NULL, 0); } @@ -737,7 +735,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, encrypted_session_key.data, encrypted_session_key.length); dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, - encrypted_session_key.length); + encrypted_session_key.length); } } else { ntlmssp_state->session_key = session_key; -- cgit From 500c28974ded4c4789d9f197de5860b20447e606 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 9 Jan 2004 14:54:33 +0000 Subject: fix some warnings from the Sun compiler (This used to be commit ebabf72a78f0165521268b73e0fcabe1ea7834fd) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 40d7f41109..a80b4b66b0 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -974,7 +974,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, DEBUG(5, ("NTLMSSP challenge set by NTLM2\n")); DEBUG(5, ("challenge is: \n")); - dump_data(5, session_nonce_hash, 8); + dump_data(5, (const char *)session_nonce_hash, 8); nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); SMBNTencrypt(ntlmssp_state->password, -- cgit From 2f2e5b01919fe4daf60f97430959ebc98e31ce92 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Jan 2004 18:38:48 +0000 Subject: Fix up name canonicalization (needed for krb5 keytab support later). Remove source_env handler (no longer used in any codepath). Jeremy. (This used to be commit 3a3e33603084048e647af86a9badaaf49433c789) --- source3/libsmb/ntlmssp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index a80b4b66b0..60523ddf9d 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -433,12 +433,11 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname[0] = '\0'; - get_mydomname(dnsdomname); + get_mydnsdomname(dnsdomname); strlower_m(dnsdomname); dnsname[0] = '\0'; - get_myfullname(dnsname); - strlower_m(dnsname); + get_mydnsfullname(dnsname); /* This creates the 'blob' of names that appears at the end of the packet */ if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) -- cgit From 873db3f5fd3fbfcf290cea61d7e9f58bf28b3983 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 27 Mar 2004 07:53:47 +0000 Subject: Based on the detective work of Jianliang Lu , allow yet another NTLMv2 combination. We should allow the NTLMv2 response to be calculated with either the domain as supplied, or the domain in UPPER case (as we always did in the past). As a client, we always UPPER case it (as per the spec), but we also make sure to UPPER case the domain, when we send it. This should give us maximum compatability. Andrew Bartlett (This used to be commit 1e91cd0cf87b29899641585f46b0dcecaefd848e) --- source3/libsmb/ntlmssp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 60523ddf9d..82eafc4cd5 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -168,7 +168,9 @@ NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password */ NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain) { - ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain); + /* Possibly make our NTLMv2 client more robust by always having + an uppercase domain */ + ntlmssp_state->domain = talloc_strdup_upper(ntlmssp_state->mem_ctx, domain); if (!ntlmssp_state->domain) { return NT_STATUS_NO_MEMORY; } -- cgit From 63f5167a288043553b7efaf206cf5e4338d07db0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 27 Mar 2004 08:43:09 +0000 Subject: Add a few comments explaining KEY_EXCH Andrew Bartlett (This used to be commit e5422d7413e22775bc81e36559cb69254aedb102) --- source3/libsmb/ntlmssp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 82eafc4cd5..ddc2e0325f 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -1022,16 +1022,19 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, /* Key exchange encryptes a new client-generated session key with the password-derived key */ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { + /* Make up a new session key */ uint8 client_session_key[16]; - - generate_random_buffer(client_session_key, sizeof(client_session_key), False); + generate_random_buffer(client_session_key, sizeof(client_session_key), False); + + /* Encrypt the new session key with the old one */ encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key)); dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length); - SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length); + dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); + + /* Mark the new session key as the 'real' session key */ data_blob_free(&session_key); session_key = data_blob_talloc(ntlmssp_state->mem_ctx, client_session_key, sizeof(client_session_key)); - dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); } /* this generates the actual auth packet */ -- cgit From d17425ed52b086b7046708a207e849271cedc804 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 6 Apr 2004 08:11:16 +0000 Subject: r69: Global rename of 'nt_session_key' -> 'user_session_key'. The session key could be anything, and may not be based on anything 'NT'. This is also what microsoft calls it. (This used to be commit 724e8d3f33719543146280062435c69a835c491e) --- source3/libsmb/ntlmssp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index ddc2e0325f..7f451176ec 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -500,7 +500,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, const DATA_BLOB request, DATA_BLOB *reply) { DATA_BLOB encrypted_session_key = data_blob(NULL, 0); - DATA_BLOB nt_session_key = data_blob(NULL, 0); + DATA_BLOB user_session_key = data_blob(NULL, 0); DATA_BLOB lm_session_key = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); uint32 ntlmssp_command, auth_flags; @@ -663,19 +663,19 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, /* Finally, actually ask if the password is OK */ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, - &nt_session_key, &lm_session_key))) { + &user_session_key, &lm_session_key))) { data_blob_free(&encrypted_session_key); return nt_status; } - dump_data_pw("NT session key:\n", nt_session_key.data, nt_session_key.length); + dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length); dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length); /* Handle the different session key derivation for NTLM2 */ if (doing_ntlm2) { - if (nt_session_key.data && nt_session_key.length == 16) { + if (user_session_key.data && user_session_key.length == 16) { session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); - hmac_md5(nt_session_key.data, session_nonce, + hmac_md5(user_session_key.data, session_nonce, sizeof(session_nonce), session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n")); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); @@ -702,8 +702,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); session_key = data_blob(NULL, 0); } - } else if (nt_session_key.data) { - session_key = nt_session_key; + } else if (user_session_key.data) { + session_key = user_session_key; DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n")); dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } else if (lm_session_key.data) { @@ -958,7 +958,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, uchar nt_hash[16]; uchar session_nonce[16]; uchar session_nonce_hash[16]; - uchar nt_session_key[16]; + uchar user_session_key[16]; E_md4hash(ntlmssp_state->password, nt_hash); lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); @@ -984,8 +984,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); - SMBsesskeygen_ntv1(nt_hash, NULL, nt_session_key); - hmac_md5(nt_session_key, session_nonce, sizeof(session_nonce), session_key.data); + SMBsesskeygen_ntv1(nt_hash, NULL, user_session_key); + hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { -- cgit From 042209871c50e346fdcb9fd3cbeb30c5bf942792 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 20 Apr 2004 16:33:30 +0000 Subject: r296: patch from j.lu -- don't force an upper case domain name in the ntlmssp code (This used to be commit a2e93dda24d079693a220b4551d264cba4c2bc82) --- source3/libsmb/ntlmssp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 7f451176ec..66d48afc46 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -168,9 +168,7 @@ NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password */ NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain) { - /* Possibly make our NTLMv2 client more robust by always having - an uppercase domain */ - ntlmssp_state->domain = talloc_strdup_upper(ntlmssp_state->mem_ctx, domain); + ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain); if (!ntlmssp_state->domain) { return NT_STATUS_NO_MEMORY; } -- cgit From 9d0783bf211dffe58845b36b0669f05bf8bf25b5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 14 Jul 2004 04:36:01 +0000 Subject: r1492: Rework our random number generation system. On systems with /dev/urandom, this avoids a change to secrets.tdb for every fork(). For other systems, we now only re-seed after a fork, and on startup. No need to do it per-operation. This removes the 'need_reseed' parameter from generate_random_buffer(). Andrew Bartlett (This used to be commit 36741d3cf53a7bd17d361251f2bb50851cdb035f) --- source3/libsmb/ntlmssp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 66d48afc46..6e41a61bf1 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -103,7 +103,7 @@ void debug_ntlmssp_flags(uint32 neg_flags) static const uint8 *get_challenge(const struct ntlmssp_state *ntlmssp_state) { static uchar chal[8]; - generate_random_buffer(chal, sizeof(chal), False); + generate_random_buffer(chal, sizeof(chal)); return chal; } @@ -960,7 +960,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, E_md4hash(ntlmssp_state->password, nt_hash); lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); - generate_random_buffer(lm_response.data, 8, False); + generate_random_buffer(lm_response.data, 8); memset(lm_response.data+8, 0, 16); memcpy(session_nonce, challenge_blob.data, 8); @@ -1022,7 +1022,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { /* Make up a new session key */ uint8 client_session_key[16]; - generate_random_buffer(client_session_key, sizeof(client_session_key), False); + generate_random_buffer(client_session_key, sizeof(client_session_key)); /* Encrypt the new session key with the old one */ encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key)); -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/libsmb/ntlmssp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 6e41a61bf1..eb1fce5439 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -766,7 +766,7 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) mem_ctx = talloc_init("NTLMSSP context"); - *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state)); + *ntlmssp_state = TALLOC_ZERO_P(mem_ctx, NTLMSSP_STATE); if (!*ntlmssp_state) { DEBUG(0,("ntlmssp_server_start: talloc failed!\n")); talloc_destroy(mem_ctx); @@ -1075,7 +1075,7 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) mem_ctx = talloc_init("NTLMSSP Client context"); - *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state)); + *ntlmssp_state = TALLOC_ZERO_P(mem_ctx, NTLMSSP_STATE); if (!*ntlmssp_state) { DEBUG(0,("ntlmssp_client_start: talloc failed!\n")); talloc_destroy(mem_ctx); -- cgit From 26dd1bab968d37d9cf9315ead3a71aad759682bb Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 7 Feb 2005 22:42:43 +0000 Subject: r5272: BUG 2132, 2134: patch from Jason Mader to remove unused variables (This used to be commit 82c4e2f37f1f4c581cd7c792808c9a81ef80db94) --- source3/libsmb/ntlmssp.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index eb1fce5439..ec3186255a 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -442,13 +442,6 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This creates the 'blob' of names that appears at the end of the packet */ if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { - const char *target_name_dns = ""; - if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) { - target_name_dns = dnsdomname; - } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) { - target_name_dns = dnsname; - } - msrpc_gen(&struct_blob, "aaaaa", NTLMSSP_NAME_TYPE_DOMAIN, target_name, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), -- cgit From acdf1aa308df48654e63b7072c47e8696ec670b9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 19 Feb 2005 09:27:06 +0000 Subject: r5455: Remove bogus DEBUG messages (dump for a failure to parse NTLMSSP, before trying the alternate format). This only caused confusion and bug reports... Andrew Bartlett (This used to be commit 5cb02b569b39aa7a9dc6692a79ff1d1dfa69aee6) --- source3/libsmb/ntlmssp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index ec3186255a..4d9aaf989b 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -393,7 +393,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, &neg_flags, &cliname, &domname)) { - DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n")); + DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate:\n")); dump_data(2, (const char *)request.data, request.length); return NT_STATUS_INVALID_PARAMETER; } @@ -539,8 +539,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, &workstation, &encrypted_session_key, &auth_flags)) { - DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); - dump_data(2, (const char *)request.data, request.length); SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); @@ -563,7 +561,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, &domain, &user, &workstation)) { - DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); + DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n")); dump_data(2, (const char *)request.data, request.length); SAFE_FREE(domain); SAFE_FREE(user); -- cgit From 46c94b2659fa1f9d7ce2b6fd798e3abb3c7760d8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 10 Jun 2005 22:03:33 +0000 Subject: r7472: fix smbpasswd user password change (still worked by bad error messages) due to trying to strdup a NULL pointer (This used to be commit a48ff479dd4fe99d199ff934aae14ac6e688d8f4) --- source3/libsmb/ntlmssp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 4d9aaf989b..574b37d4a0 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -138,7 +138,7 @@ static NTSTATUS set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *ch NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user) { - ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user); + ntlmssp_state->user = talloc_strdup(ntlmssp_state->mem_ctx, user ? user : "" ); if (!ntlmssp_state->user) { return NT_STATUS_NO_MEMORY; } @@ -168,7 +168,7 @@ NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password */ NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain) { - ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain); + ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain ? domain : "" ); if (!ntlmssp_state->domain) { return NT_STATUS_NO_MEMORY; } -- cgit From a3a85172167eba787a61e0eb8a7c914407e593ea Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 14 Jul 2005 14:40:30 +0000 Subject: r8475: BUG 2872: fix cut-n-paste error when checking pointer value in ntlmssp_set_workstation() (This used to be commit f1763c5decd14eb71ee3d7ea71859a85d5ee0dc1) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 574b37d4a0..b02c2384a8 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -182,7 +182,7 @@ NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain) NTSTATUS ntlmssp_set_workstation(NTLMSSP_STATE *ntlmssp_state, const char *workstation) { ntlmssp_state->workstation = talloc_strdup(ntlmssp_state->mem_ctx, workstation); - if (!ntlmssp_state->domain) { + if (!ntlmssp_state->workstation) { return NT_STATUS_NO_MEMORY; } return NT_STATUS_OK; -- cgit From 54abd2aa66069e6baf7769c496f46d9dba18db39 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 30 Sep 2005 17:13:37 +0000 Subject: r10656: BIG merge from trunk. Features not copied over * \PIPE\unixinfo * winbindd's {group,alias}membership new functions * winbindd's lookupsids() functionality * swat (trunk changes to be reverted as per discussion with Deryck) (This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3) --- source3/libsmb/ntlmssp.c | 84 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 16 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index b02c2384a8..6b551e8774 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 2001 Copyright (C) Andrew Bartlett 2001-2003 + Copyright (C) Andrew Bartlett 2005 (Updated from gensec). This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -217,6 +218,12 @@ NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state, uint32 ntlmssp_command; int i; + if (ntlmssp_state->expected_state == NTLMSSP_DONE) { + /* Called update after negotiations finished. */ + DEBUG(1, ("Called NTLMSSP after state machine was 'done'\n")); + return NT_STATUS_INVALID_PARAMETER; + } + *out = data_blob(NULL, 0); if (!in.length && ntlmssp_state->stored_response.length) { @@ -348,6 +355,13 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) { ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; + if (neg_flags & NTLMSSP_NEGOTIATE_56) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; + } + } + + if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56; } if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { @@ -360,6 +374,34 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, } +/** + Weaken NTLMSSP keys to cope with down-level clients and servers. + + We probably should have some parameters to control this, but as + it only occours for LM_KEY connections, and this is controlled + by the client lanman auth/lanman auth parameters, it isn't too bad. +*/ + +void ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state) +{ + /* Key weakening not performed on the master key for NTLM2 + and does not occour for NTLM1. Therefore we only need + to do this for the LM_KEY. + */ + + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) { + ; + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { + ntlmssp_state->session_key.data[7] = 0xa0; + } else { /* forty bits */ + ntlmssp_state->session_key.data[5] = 0xe5; + ntlmssp_state->session_key.data[6] = 0x38; + ntlmssp_state->session_key.data[7] = 0xb0; + } + ntlmssp_state->session_key.length = 8; + } +} /** * Next state function for the Negotiate packet @@ -398,6 +440,9 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, return NT_STATUS_INVALID_PARAMETER; } + DEBUG(10, ("ntlmssp_server_negotiate: client = %s, domain = %s\n", + cliname ? cliname : "", domname ? domname : "")); + SAFE_FREE(cliname); SAFE_FREE(domname); @@ -495,7 +540,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, DATA_BLOB lm_session_key = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); uint32 ntlmssp_command, auth_flags; - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_OK; /* used by NTLM2 */ BOOL doing_ntlm2 = False; @@ -639,6 +684,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, data_blob_free(&encrypted_session_key); return nt_status; } + + /* LM Key is incompatible. */ + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; } } @@ -710,11 +758,11 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, if (!encrypted_session_key.data || encrypted_session_key.length != 16) { data_blob_free(&encrypted_session_key); DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", - encrypted_session_key.length)); + (unsigned int)encrypted_session_key.length)); return NT_STATUS_INVALID_PARAMETER; } else if (!session_key.data || session_key.length != 16) { DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", - session_key.length)); + (unsigned int)session_key.length)); ntlmssp_state->session_key = session_key; } else { dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); @@ -731,6 +779,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->session_key = session_key; } + /* The client might need us to use a partial-strength session key */ + ntlmssp_weaken_keys(ntlmssp_state); + if (!NT_STATUS_IS_OK(nt_status)) { ntlmssp_state->session_key = data_blob(NULL, 0); } else if (ntlmssp_state->session_key.length) { @@ -739,8 +790,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, data_blob_free(&encrypted_session_key); - /* allow arbitarily many authentications */ - ntlmssp_state->expected_state = NTLMSSP_AUTH; + /* Only one authentication allowed per server state. */ + ntlmssp_state->expected_state = NTLMSSP_DONE; return nt_status; } @@ -784,7 +835,8 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | - NTLMSSP_NEGOTIATE_SIGN; + NTLMSSP_NEGOTIATE_SIGN | + NTLMSSP_NEGOTIATE_SEAL; return NT_STATUS_OK; } @@ -851,7 +903,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB encrypted_session_key = data_blob(NULL, 0); - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_OK; if (!msrpc_parse(&reply, "CdBd", "NTLMSSP", @@ -977,8 +1029,6 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { - - uchar lm_hash[16]; uchar nt_hash[16]; E_deshash(ntlmssp_state->password, lm_hash); @@ -998,8 +1048,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && lp_client_lanman_auth()) { - SMBsesskeygen_lmv1(lm_hash, lm_response.data, - session_key.data); + SMBsesskeygen_lm_sess_key(lm_hash, lm_response.data, + session_key.data); dump_data_pw("LM session key\n", session_key.data, session_key.length); } else { SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); @@ -1045,19 +1095,22 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, data_blob_free(&ntlmssp_state->chal); + ntlmssp_state->session_key = session_key; + + /* The client might be using 56 or 40 bit weakened keys */ + ntlmssp_weaken_keys(ntlmssp_state); + ntlmssp_state->chal = challenge_blob; ntlmssp_state->lm_resp = lm_response; ntlmssp_state->nt_resp = nt_response; - ntlmssp_state->session_key = session_key; - ntlmssp_state->expected_state = NTLMSSP_UNKNOWN; + ntlmssp_state->expected_state = NTLMSSP_DONE; if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) { DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status))); - return nt_status; } - return NT_STATUS_MORE_PROCESSING_REQUIRED; + return nt_status; } NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) @@ -1103,4 +1156,3 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) return NT_STATUS_OK; } - -- cgit From daf33dc4fc888b839aa38d1e757ed066edf06996 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Oct 2005 21:59:36 +0000 Subject: r11075: Still working on bug #1828, PPC hell. The PPC client sends the NTLMSSP client and domain strings as Unicode, even when setting flags as OEM. Cope with this. Jeremy. (This used to be commit 458da8987e8f406cdfd5bd602b3c3cf315675725) --- source3/libsmb/ntlmssp.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 6b551e8774..42a4b95e29 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -429,14 +429,31 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, #endif if (request.length) { - if (!msrpc_parse(&request, "CddAA", + BOOL parse_ok = msrpc_parse(&request, "CddAA", "NTLMSSP", &ntlmssp_command, &neg_flags, &cliname, - &domname)) { + &domname); + + if (!parse_ok) { + /* PocketPC 2003 sends the cliname and domname strings in unicode, + but doesn't set the unicode bit. Try with a parse string of "CddUU" */ + SAFE_FREE(cliname); + SAFE_FREE(domname); + parse_ok = msrpc_parse(&request, "CddUU", + "NTLMSSP", + &ntlmssp_command, + &neg_flags, + &cliname, + &domname); + } + + if (!parse_ok) { DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate:\n")); dump_data(2, (const char *)request.data, request.length); + SAFE_FREE(cliname); + SAFE_FREE(domname); return NT_STATUS_INVALID_PARAMETER; } -- cgit From 1c5c61e3703ffca912f81496324ce82c2f19efa0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 15 Oct 2005 00:46:38 +0000 Subject: r11079: Narrowing down on the #1828 PPC bug. The PPC client sends an initial NTLMSSP negotiate blob of only 16 bytes - no strings added ! (So don't try parsing them). Jeremy. (This used to be commit e15b758f5fa6f500214bb60599a89f3c795c9fed) --- source3/libsmb/ntlmssp.c | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 42a4b95e29..0becc7fdee 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -419,7 +419,6 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, fstring dnsname, dnsdomname; uint32 neg_flags = 0; uint32 ntlmssp_command, chal_flags; - char *cliname=NULL, *domname=NULL; const uint8 *cryptkey; const char *target_name; @@ -429,40 +428,15 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, #endif if (request.length) { - BOOL parse_ok = msrpc_parse(&request, "CddAA", - "NTLMSSP", - &ntlmssp_command, - &neg_flags, - &cliname, - &domname); - - if (!parse_ok) { - /* PocketPC 2003 sends the cliname and domname strings in unicode, - but doesn't set the unicode bit. Try with a parse string of "CddUU" */ - SAFE_FREE(cliname); - SAFE_FREE(domname); - parse_ok = msrpc_parse(&request, "CddUU", - "NTLMSSP", - &ntlmssp_command, - &neg_flags, - &cliname, - &domname); - } - - if (!parse_ok) { - DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate:\n")); + if ((request.length < 16) || !msrpc_parse(&request, "Cdd", + "NTLMSSP", + &ntlmssp_command, + &neg_flags)) { + DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n", + (unsigned int)request.length)); dump_data(2, (const char *)request.data, request.length); - SAFE_FREE(cliname); - SAFE_FREE(domname); return NT_STATUS_INVALID_PARAMETER; } - - DEBUG(10, ("ntlmssp_server_negotiate: client = %s, domain = %s\n", - cliname ? cliname : "", domname ? domname : "")); - - SAFE_FREE(cliname); - SAFE_FREE(domname); - debug_ntlmssp_flags(neg_flags); } -- cgit From 5f4a895cdde15ada0f4155a431cad5ea610740d9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Jan 2006 23:23:09 +0000 Subject: r12920: Fix for #3401 from Andrew Bartlett. Original fix from Yau Lam Yiu . Jeremy. (This used to be commit 4776101107923e425a153fe0457dbf61f4c99935) --- source3/libsmb/ntlmssp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 0becc7fdee..6dd623047a 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -384,6 +384,11 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, void ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state) { + /* Nothing to weaken. We certainly don't want to 'extend' the length... */ + if (!ntlmssp_state->session_key.length < 8) { + return; + } + /* Key weakening not performed on the master key for NTLM2 and does not occour for NTLM1. Therefore we only need to do this for the LM_KEY. -- cgit From ae4a576f680f1c0507ec73f606154ff8ff36a1dd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Jan 2006 23:54:12 +0000 Subject: r12922: Fix typo. Jeremy. (This used to be commit 1c32b352da270370e65d25939fdc56c2a415190f) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 6dd623047a..c891ede9bb 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -385,7 +385,7 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, void ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state) { /* Nothing to weaken. We certainly don't want to 'extend' the length... */ - if (!ntlmssp_state->session_key.length < 8) { + if (ntlmssp_state->session_key.length < 8) { return; } -- cgit From d672d8fd6bd2957f6177c809c77b3d2c1a2fddca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 12 Feb 2006 16:44:30 +0000 Subject: r13473: Back port r13470, r13471, r13472 from Samba4. Thanks Andrew: ----------------------------------- Thanks to a report from VL: We were causing mayhem by weakening the keys at the wrong point in time. I think this is the correct place to do it. The session key for SMB signing, and the 'smb session key' (used for encrypting password sets) is never weakened. The session key used for bulk data encryption/signing is weakened. This also makes more sense, when we look at the NTLM2 code. Andrew Bartlett ----------------------------------- With more 'try all options' testing, I found this 'simple' but in the NTLM2 signing code. Andrew Bartlett ----------------------------------- After Volker's advise, try every combination of parameters. This isn't every parameter on NTLMSSP, but it is most of the important ones. This showed up that we had the '128bit && LM_KEY' case messed up. This isn't supported, so we must look instead at the 56 bit flag. Andrew Bartlett ----------------------------------- We should now try retesting with NT4. This should be standalone enough to port into a SAMBA_3_0_RELEASE branch fix. Jeremy. (This used to be commit b9b8cd1752aeab049983c1a6038edf2231ec10a4) --- source3/libsmb/ntlmssp.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index c891ede9bb..e1ef69aed9 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -72,6 +72,8 @@ void debug_ntlmssp_flags(uint32 neg_flags) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SIGN\n")); if (neg_flags & NTLMSSP_NEGOTIATE_SEAL) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SEAL\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM_STYLE) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_DATAGRAM_STYLE\n")); if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n")); if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE) @@ -86,6 +88,10 @@ void debug_ntlmssp_flags(uint32 neg_flags) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n")); if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n")); + if (neg_flags & NTLMSSP_CHAL_ACCEPT_RESPONSE) + DEBUGADD(4, (" NTLMSSP_CHAL_ACCEPT_RESPONSE\n")); + if (neg_flags & NTLMSSP_CHAL_NON_NT_SESSION_KEY) + DEBUGADD(4, (" NTLMSSP_CHAL_NON_NT_SESSION_KEY\n")); if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM2\n")); if (neg_flags & NTLMSSP_CHAL_TARGET_INFO) @@ -94,6 +100,8 @@ void debug_ntlmssp_flags(uint32 neg_flags) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_128\n")); if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_56) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_56\n")); } /** @@ -382,11 +390,16 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, by the client lanman auth/lanman auth parameters, it isn't too bad. */ -void ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state) +DATA_BLOB ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state, TALLOC_CTX *mem_ctx) { + DATA_BLOB weakened_key = data_blob_talloc(mem_ctx, + ntlmssp_state->session_key.data, + ntlmssp_state->session_key.length); + /* Nothing to weaken. We certainly don't want to 'extend' the length... */ - if (ntlmssp_state->session_key.length < 8) { - return; + if (weakened_key.length < 16) { + /* perhaps there was no key? */ + return weakened_key; } /* Key weakening not performed on the master key for NTLM2 @@ -395,17 +408,19 @@ void ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state) */ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { - if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) { - ; - } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { - ntlmssp_state->session_key.data[7] = 0xa0; + /* LM key doesn't support 128 bit crypto, so this is + * the best we can do. If you negotiate 128 bit, but + * not 56, you end up with 40 bit... */ + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { + weakened_key.data[7] = 0xa0; } else { /* forty bits */ - ntlmssp_state->session_key.data[5] = 0xe5; - ntlmssp_state->session_key.data[6] = 0x38; - ntlmssp_state->session_key.data[7] = 0xb0; + weakened_key.data[5] = 0xe5; + weakened_key.data[6] = 0x38; + weakened_key.data[7] = 0xb0; } - ntlmssp_state->session_key.length = 8; + weakened_key.length = 8; } + return weakened_key; } /** @@ -775,9 +790,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->session_key = session_key; } - /* The client might need us to use a partial-strength session key */ - ntlmssp_weaken_keys(ntlmssp_state); - if (!NT_STATUS_IS_OK(nt_status)) { ntlmssp_state->session_key = data_blob(NULL, 0); } else if (ntlmssp_state->session_key.length) { @@ -1093,9 +1105,6 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->session_key = session_key; - /* The client might be using 56 or 40 bit weakened keys */ - ntlmssp_weaken_keys(ntlmssp_state); - ntlmssp_state->chal = challenge_blob; ntlmssp_state->lm_resp = lm_response; ntlmssp_state->nt_resp = nt_response; -- cgit From 0498f3b8890ec62eeb9275a6bf685a6c3d81fce5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 18 Apr 2006 18:00:57 +0000 Subject: r15129: Separate out mechanism and policy for NTLMSSP auth/sign/seal. With this change (and setting lanman auth = no in smb.conf) we have *identical* NTLMSSP flags to W2K3 in SPNEGO auth. Jeremy (This used to be commit 93ca3eee55297eb7fdd38fca38103ce129987e2a) --- source3/libsmb/ntlmssp.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index e1ef69aed9..986fa8cce9 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -363,9 +363,6 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) { ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; - if (neg_flags & NTLMSSP_NEGOTIATE_56) { - ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; - } } if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) { @@ -376,10 +373,23 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH; } + if (!(neg_flags & NTLMSSP_NEGOTIATE_SIGN)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN; + } + + if (!(neg_flags & NTLMSSP_NEGOTIATE_SEAL)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL; + } + + /* Woop Woop - unknown flag for Windows compatibility... + What does this really do ? JRA. */ + if (!(neg_flags & NTLMSSP_UNKNOWN_02000000)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_UNKNOWN_02000000; + } + if ((neg_flags & NTLMSSP_REQUEST_TARGET)) { ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET; } - } /** @@ -840,6 +850,8 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) (*ntlmssp_state)->neg_flags = NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_56 | + NTLMSSP_UNKNOWN_02000000 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | -- cgit From fe348fdb28624428269bffeb1ff796ec3857ff66 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Jul 2006 05:02:38 +0000 Subject: r17216: From Kai Blin : A patch to make ntlm_auth recognize three new commands in ntlmssp-client-1 and squid-2.5-ntlmssp: The commands are the following: Command: SF Reply: OK Description: Takes feature request flags similar to samba4's gensec_want_feature() call. So far, only NTLMSSP_FEATURE_SESSION_KEY, NTLMSSP_FEATURE_SIGN and NTLMSSP_FEATURE_SEAL are implemented, using the same values as the corresponding GENSEC_FEATURE_* flags in samba4. Command: GF Reply: GF Description: Returns the negotiated flags. Command: GK Reply: GK Description: Returns the negotiated session key. (These commands assist a wine project to use ntlm_auth for signing and sealing of bulk data). Andrew Bartlett (This used to be commit bd3e06a0e4435f1c48fa3b7862333efe273119ee) --- source3/libsmb/ntlmssp.c | 50 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 986fa8cce9..a6fb3b426b 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -210,6 +210,50 @@ NTSTATUS ntlmssp_store_response(NTLMSSP_STATE *ntlmssp_state, return NT_STATUS_OK; } +/** + * Request features for the NTLMSSP negotiation + * + * @param ntlmssp_state NTLMSSP state + * @param feature_list List of space seperated features requested from NTLMSSP. + */ +void ntlmssp_want_feature_list(NTLMSSP_STATE *ntlmssp_state, char *feature_list) +{ + /* + * We need to set this to allow a later SetPassword + * via the SAMR pipe to succeed. Strange.... We could + * also add NTLMSSP_NEGOTIATE_SEAL here. JRA. + */ + if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, True)) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, True)) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if(in_list("NTLMSSP_FEATURE_SEAL", feature_list, True)) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; + } +} + +/** + * Request a feature for the NTLMSSP negotiation + * + * @param ntlmssp_state NTLMSSP state + * @param feature Bit flag specifying the requested feature + */ +void ntlmssp_want_feature(NTLMSSP_STATE *ntlmssp_state, uint32 feature) +{ + /* As per JRA's comment above */ + if (feature & NTLMSSP_FEATURE_SESSION_KEY) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if (feature & NTLMSSP_FEATURE_SIGN) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + if (feature & NTLMSSP_FEATURE_SEAL) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; + } +} + /** * Next state function for the NTLMSSP state machine * @@ -1163,12 +1207,6 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | - /* - * We need to set this to allow a later SetPassword - * via the SAMR pipe to succeed. Strange.... We could - * also add NTLMSSP_NEGOTIATE_SEAL here. JRA. - * */ - NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_REQUEST_TARGET; return NT_STATUS_OK; -- cgit From ffa590854ab5f2563c3398ae9ae3182e6abe3f82 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Aug 2006 20:42:04 +0000 Subject: r17612: Modify NTLMSSP session code so that it doesn't store a copy of the plaintext password, only the NT and LM hashes (all it needs). Fix smbencrypt to expose hash verions of plaintext function. Andrew Bartlett, you might want to look at this for gensec. This should make it easier for winbindd to store cached credentials without having to store plaintext passwords in an NTLM-only environment (non krb5). Jeremy. (This used to be commit 629faa530f0422755823644f1c23bea74830912f) --- source3/libsmb/ntlmssp.c | 56 +++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 22 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index a6fb3b426b..fd639ffd9f 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -155,18 +155,37 @@ NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user) } /** - * Set a password on an NTLMSSP context - ensures it is talloc()ed + * Store NT and LM hashes on an NTLMSSP context - ensures they are talloc()ed + * + */ +NTSTATUS ntlmssp_set_hashes(NTLMSSP_STATE *ntlmssp_state, + const unsigned char lm_hash[16], + const unsigned char nt_hash[16]) +{ + ntlmssp_state->lm_hash = TALLOC_MEMDUP(ntlmssp_state->mem_ctx, lm_hash, 16); + ntlmssp_state->nt_hash = TALLOC_MEMDUP(ntlmssp_state->mem_ctx, nt_hash, 16); + if (!ntlmssp_state->lm_hash || !ntlmssp_state->nt_hash) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; +} + +/** + * Converts a password to the hashes on an NTLMSSP context. * */ NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password) { if (!password) { - ntlmssp_state->password = NULL; + ntlmssp_state->lm_hash = NULL; + ntlmssp_state->nt_hash = NULL; } else { - ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password); - if (!ntlmssp_state->password) { - return NT_STATUS_NO_MEMORY; - } + unsigned char lm_hash[16]; + unsigned char nt_hash[16]; + + E_deshash(password, lm_hash); + E_md4hash(password, nt_hash); + return ntlmssp_set_hashes(ntlmssp_state, lm_hash, nt_hash); } return NT_STATUS_OK; } @@ -1029,7 +1048,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, return NT_STATUS_INVALID_PARAMETER; } - if (!ntlmssp_state->password) { + if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) { static const uchar zeros[16]; /* do nothing - blobs are zero length */ @@ -1049,9 +1068,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, /* TODO: if the remote server is standalone, then we should replace 'domain' with the server name as supplied above */ - if (!SMBNTLMv2encrypt(ntlmssp_state->user, + if (!SMBNTLMv2encrypt_hash(ntlmssp_state->user, ntlmssp_state->domain, - ntlmssp_state->password, &challenge_blob, + ntlmssp_state->nt_hash, &challenge_blob, &struct_blob, &lm_response, &nt_response, &session_key)) { data_blob_free(&challenge_blob); @@ -1060,11 +1079,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, } } 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 user_session_key[16]; - E_md4hash(ntlmssp_state->password, nt_hash); lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); generate_random_buffer(lm_response.data, 8); @@ -1083,40 +1100,35 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, dump_data(5, (const char *)session_nonce_hash, 8); nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); - SMBNTencrypt(ntlmssp_state->password, + SMBNTencrypt_hash(ntlmssp_state->nt_hash, session_nonce_hash, nt_response.data); session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); - SMBsesskeygen_ntv1(nt_hash, NULL, user_session_key); + SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, user_session_key); hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { - uchar lm_hash[16]; - uchar nt_hash[16]; - E_deshash(ntlmssp_state->password, lm_hash); - E_md4hash(ntlmssp_state->password, nt_hash); - /* lanman auth is insecure, it may be disabled */ if (lp_client_lanman_auth()) { lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); - SMBencrypt(ntlmssp_state->password,challenge_blob.data, + SMBencrypt_hash(ntlmssp_state->lm_hash,challenge_blob.data, lm_response.data); } nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); - SMBNTencrypt(ntlmssp_state->password,challenge_blob.data, + SMBNTencrypt_hash(ntlmssp_state->nt_hash,challenge_blob.data, nt_response.data); session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && lp_client_lanman_auth()) { - SMBsesskeygen_lm_sess_key(lm_hash, lm_response.data, + SMBsesskeygen_lm_sess_key(ntlmssp_state->lm_hash, lm_response.data, session_key.data); dump_data_pw("LM session key\n", session_key.data, session_key.length); } else { - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + SMBsesskeygen_ntv1(ntlmssp_state->nt_hash, NULL, session_key.data); dump_data_pw("NT session key:\n", session_key.data, session_key.length); } } -- cgit From 711982340390f5dae8b3778d28fc0f4733e25221 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Aug 2006 17:08:37 +0000 Subject: r17620: Fix two C++ Warnings and a memleak (This used to be commit d7246284e0117f7a97b3cbb80ff45b532559bf63) --- source3/libsmb/ntlmssp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index fd639ffd9f..70fcd24e76 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -162,9 +162,13 @@ NTSTATUS ntlmssp_set_hashes(NTLMSSP_STATE *ntlmssp_state, const unsigned char lm_hash[16], const unsigned char nt_hash[16]) { - ntlmssp_state->lm_hash = TALLOC_MEMDUP(ntlmssp_state->mem_ctx, lm_hash, 16); - ntlmssp_state->nt_hash = TALLOC_MEMDUP(ntlmssp_state->mem_ctx, nt_hash, 16); + ntlmssp_state->lm_hash = (unsigned char *) + TALLOC_MEMDUP(ntlmssp_state->mem_ctx, lm_hash, 16); + ntlmssp_state->nt_hash = (unsigned char *) + TALLOC_MEMDUP(ntlmssp_state->mem_ctx, nt_hash, 16); if (!ntlmssp_state->lm_hash || !ntlmssp_state->nt_hash) { + TALLOC_FREE(ntlmssp_state->lm_hash); + TALLOC_FREE(ntlmssp_state->nt_hash); return NT_STATUS_NO_MEMORY; } return NT_STATUS_OK; -- cgit From 27e37eab987d0618c5dd19446369aad59a588dd6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 31 Aug 2006 20:45:29 +0000 Subject: r17977: To be honest, I have NO idea whatsoever what this does, but it fixes what I have been able to reproduce with smbtorture4 for bug number 4059. It's too late here now to check with W2k native, I'll do that tomorrow or over the weekend. I'll then also check in a samba4 torture test to walk this from now on. Abartlet, can you do me a favor and look over this? It is a 1:1 copy of the corresponding Samba4 code. Thanks, Volker (This used to be commit fb5ebab873ba5196f35a9801ab2e21811b0fa8a0) --- source3/libsmb/ntlmssp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 70fcd24e76..6a44809f9e 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -816,13 +816,14 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); - dump_data_pw("LM session key:\n", session_key.data, session_key.length); } else { - /* use the key unmodified - it's - * probably a NULL key from the guest - * login */ - session_key = lm_session_key; + static const uint8 zeros[24] = { 0, }; + SMBsesskeygen_lm_sess_key( + lm_session_key.data, zeros, + session_key.data); } + dump_data_pw("LM session key:\n", session_key.data, + session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); session_key = data_blob(NULL, 0); -- cgit From bd5fca847a33ddef7d73ad8c6932ee2f6685054a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 2 Sep 2006 19:18:49 +0000 Subject: r18005: The ntlmssp fix is not correct yet, working on it (This used to be commit 3e4da5541c24b3c3c5104fc5120a9be8a2f9ae69) --- source3/libsmb/ntlmssp.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 6a44809f9e..70fcd24e76 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -816,14 +816,13 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); + dump_data_pw("LM session key:\n", session_key.data, session_key.length); } else { - static const uint8 zeros[24] = { 0, }; - SMBsesskeygen_lm_sess_key( - lm_session_key.data, zeros, - session_key.data); + /* use the key unmodified - it's + * probably a NULL key from the guest + * login */ + session_key = lm_session_key; } - dump_data_pw("LM session key:\n", session_key.data, - session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); session_key = data_blob(NULL, 0); -- cgit From b7a5e3de1eac86bd460aed341ec17a01f4b82e5f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 2 Sep 2006 21:41:28 +0000 Subject: r18008: Ok, same fix as before. But this time also allocate the session key. This had worked in one test, no idea what memory I've overwritten that time. This time it survives the unpatched w2k password change. Volker (This used to be commit bf7bf8e4e9a279fe3ef1e9ff655b12f65c3c3e67) --- source3/libsmb/ntlmssp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 70fcd24e76..d017bdb76c 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -813,16 +813,25 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, if (lm_session_key.data && lm_session_key.length >= 8) { if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) { session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); + if (session_key.data == NULL) { + return NT_STATUS_NO_MEMORY; + } SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); - dump_data_pw("LM session key:\n", session_key.data, session_key.length); } else { - /* use the key unmodified - it's - * probably a NULL key from the guest - * login */ - session_key = lm_session_key; + static const uint8 zeros[24] = { 0, }; + session_key = data_blob_talloc( + ntlmssp_state->mem_ctx, NULL, 16); + if (session_key.data == NULL) { + return NT_STATUS_NO_MEMORY; + } + SMBsesskeygen_lm_sess_key( + lm_session_key.data, zeros, + session_key.data); } + dump_data_pw("LM session key:\n", session_key.data, + session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); session_key = data_blob(NULL, 0); -- cgit From 6655e1e997fa96408ce257f1c96773db4551f69f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 4 Sep 2006 09:51:47 +0000 Subject: r18029: More C++ stuff (This used to be commit 089b51e28cc5e3674e4edf5464c7a15673c5ec0f) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index d017bdb76c..c1852a1187 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -1062,7 +1062,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, } if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) { - static const uchar zeros[16]; + static const uchar zeros[16] = { 0, }; /* do nothing - blobs are zero length */ /* session key is all zeros */ -- cgit From fb1430d6c93fe25d1f14c62cb82c05c02d12333f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Nov 2006 18:51:49 +0000 Subject: r19936: Patch from Kai Blin to match Windows NTLMSSP flags. Jeremy. (This used to be commit 786318f84bef76c6acffa1ddf7cdba947509fbac) --- source3/libsmb/ntlmssp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index c1852a1187..2f919b3f76 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -420,8 +420,8 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; } - if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) { - ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + if (!(neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN; } if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) { @@ -928,6 +928,7 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_56 | NTLMSSP_UNKNOWN_02000000 | + NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | @@ -1229,6 +1230,7 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) (*ntlmssp_state)->neg_flags = NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | -- cgit From 56ba44766854ed7cda265bdaf85913f2a1008282 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 28 Mar 2007 13:34:59 +0000 Subject: r22001: change prototype of dump_data(), so that it takes unsigned char * now, which matches what samba4 has. also fix all the callers to prevent compiler warnings metze (This used to be commit fa322f0cc9c26a9537ba3f0a7d4e4a25941317e7) --- source3/libsmb/ntlmssp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 2f919b3f76..2bc2183add 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -325,7 +325,7 @@ NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state, "NTLMSSP", &ntlmssp_command)) { DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n")); - dump_data(2, (const char *)input.data, input.length); + dump_data(2, input.data, input.length); return NT_STATUS_INVALID_PARAMETER; } } @@ -531,7 +531,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, &neg_flags)) { DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n", (unsigned int)request.length)); - dump_data(2, (const char *)request.data, request.length); + dump_data(2, request.data, request.length); return NT_STATUS_INVALID_PARAMETER; } debug_ntlmssp_flags(neg_flags); @@ -695,7 +695,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, &user, &workstation)) { DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n")); - dump_data(2, (const char *)request.data, request.length); + dump_data(2, request.data, request.length); SAFE_FREE(domain); SAFE_FREE(user); SAFE_FREE(workstation); @@ -1008,7 +1008,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, &server_domain_blob, &chal_flags)) { DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n")); - dump_data(2, (const char *)reply.data, reply.length); + dump_data(2, reply.data, reply.length); return NT_STATUS_INVALID_PARAMETER; } @@ -1049,7 +1049,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, &unkn1, &unkn2, &struct_blob)) { DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n")); - dump_data(2, (const char *)reply.data, reply.length); + dump_data(2, reply.data, reply.length); return NT_STATUS_INVALID_PARAMETER; } @@ -1111,7 +1111,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, DEBUG(5, ("NTLMSSP challenge set by NTLM2\n")); DEBUG(5, ("challenge is: \n")); - dump_data(5, (const char *)session_nonce_hash, 8); + dump_data(5, session_nonce_hash, 8); nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24); SMBNTencrypt_hash(ntlmssp_state->nt_hash, -- cgit From b4a7b7a8889737e2891fc1176feabd4ce47f2737 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 14 May 2007 12:16:20 +0000 Subject: r22844: Introduce const DATA_BLOB data_blob_null = { NULL, 0, NULL }; and replace all data_blob(NULL, 0) calls. (This used to be commit 3d3d61687ef00181f4f04e001d42181d93ac931e) --- source3/libsmb/ntlmssp.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 2bc2183add..7368070985 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -299,13 +299,13 @@ NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state, return NT_STATUS_INVALID_PARAMETER; } - *out = data_blob(NULL, 0); + *out = data_blob_null; if (!in.length && ntlmssp_state->stored_response.length) { input = ntlmssp_state->stored_response; /* we only want to read the stored response once - overwrite it */ - ntlmssp_state->stored_response = data_blob(NULL, 0); + ntlmssp_state->stored_response = data_blob_null; } else { input = in; } @@ -582,7 +582,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, NTLMSSP_NAME_TYPE_SERVER_DNS, dnsname, 0, ""); } else { - struct_blob = data_blob(NULL, 0); + struct_blob = data_blob_null; } { @@ -623,10 +623,10 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, const DATA_BLOB request, DATA_BLOB *reply) { - DATA_BLOB encrypted_session_key = data_blob(NULL, 0); - DATA_BLOB user_session_key = data_blob(NULL, 0); - DATA_BLOB lm_session_key = data_blob(NULL, 0); - DATA_BLOB session_key = data_blob(NULL, 0); + DATA_BLOB encrypted_session_key = data_blob_null; + DATA_BLOB user_session_key = data_blob_null; + DATA_BLOB lm_session_key = data_blob_null; + DATA_BLOB session_key = data_blob_null; uint32 ntlmssp_command, auth_flags; NTSTATUS nt_status = NT_STATUS_OK; @@ -642,7 +642,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, char *workstation = NULL; /* parse the NTLMSSP packet */ - *reply = data_blob(NULL, 0); + *reply = data_blob_null; #if 0 file_save("ntlmssp_auth.dat", request.data, request.length); @@ -807,7 +807,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n")); - session_key = data_blob(NULL, 0); + session_key = data_blob_null; } } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { if (lm_session_key.data && lm_session_key.length >= 8) { @@ -834,7 +834,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n")); - session_key = data_blob(NULL, 0); + session_key = data_blob_null; } } else if (user_session_key.data) { session_key = user_session_key; @@ -846,7 +846,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, dump_data_pw("unmodified session key:\n", session_key.data, session_key.length); } else { DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n")); - session_key = data_blob(NULL, 0); + session_key = data_blob_null; } /* With KEY_EXCH, the client supplies the proposed session key, @@ -877,7 +877,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, } if (!NT_STATUS_IS_OK(nt_status)) { - ntlmssp_state->session_key = data_blob(NULL, 0); + ntlmssp_state->session_key = data_blob_null; } else if (ntlmssp_state->session_key.length) { nt_status = ntlmssp_sign_init(ntlmssp_state); } @@ -992,14 +992,14 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, uint32 chal_flags, ntlmssp_command, unkn1, unkn2; DATA_BLOB server_domain_blob; DATA_BLOB challenge_blob; - DATA_BLOB struct_blob = data_blob(NULL, 0); + DATA_BLOB struct_blob = data_blob_null; char *server_domain; const char *chal_parse_string; const char *auth_gen_string; - DATA_BLOB lm_response = data_blob(NULL, 0); - DATA_BLOB nt_response = data_blob(NULL, 0); - DATA_BLOB session_key = data_blob(NULL, 0); - DATA_BLOB encrypted_session_key = data_blob(NULL, 0); + DATA_BLOB lm_response = data_blob_null; + DATA_BLOB nt_response = data_blob_null; + DATA_BLOB session_key = data_blob_null; + DATA_BLOB encrypted_session_key = data_blob_null; NTSTATUS nt_status = NT_STATUS_OK; if (!msrpc_parse(&reply, "CdBd", -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 7368070985..fc1ac124b3 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -9,7 +9,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/libsmb/ntlmssp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index fc1ac124b3..0c0744867d 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -18,8 +18,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/libsmb/ntlmssp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 0c0744867d..7205d57a0a 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -121,7 +121,7 @@ static const uint8 *get_challenge(const struct ntlmssp_state *ntlmssp_state) * */ -static BOOL may_set_challenge(const struct ntlmssp_state *ntlmssp_state) +static bool may_set_challenge(const struct ntlmssp_state *ntlmssp_state) { return True; } @@ -400,7 +400,7 @@ static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state, } static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, - uint32 neg_flags, BOOL allow_lm) { + uint32 neg_flags, bool allow_lm) { if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM; @@ -630,7 +630,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, NTSTATUS nt_status = NT_STATUS_OK; /* used by NTLM2 */ - BOOL doing_ntlm2 = False; + bool doing_ntlm2 = False; uchar session_nonce[16]; uchar session_nonce_hash[16]; -- cgit From d40e47db4b5da41c8604a2058f3a0b0a82164f08 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Nov 2007 17:25:45 -0800 Subject: Remove more fstring/pstring bad useage. Go talloc ! Jeremy. (This used to be commit 2a0173743d2cf615d52278f3dd87cc804abe2d16) --- source3/libsmb/ntlmssp.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 7205d57a0a..ed08e8102b 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -501,18 +501,19 @@ DATA_BLOB ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state, TALLOC_CTX *mem_ctx) /** * Next state function for the Negotiate packet - * + * * @param ntlmssp_state NTLMSSP State * @param request The request, as a DATA_BLOB * @param request The reply, as an allocated DATA_BLOB, caller to free. - * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent. + * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent. */ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, const DATA_BLOB request, DATA_BLOB *reply) { DATA_BLOB struct_blob; - fstring dnsname, dnsdomname; + const char *dnsname; + char *dnsdomname = NULL; uint32 neg_flags = 0; uint32 ntlmssp_command, chal_flags; const uint8 *cryptkey; @@ -535,7 +536,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, } debug_ntlmssp_flags(neg_flags); } - + ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth()); /* Ask our caller what challenge they would like in the packet */ @@ -548,31 +549,34 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* The flags we send back are not just the negotiated flags, * they are also 'what is in this packet'. Therfore, we - * operate on 'chal_flags' from here on + * operate on 'chal_flags' from here on */ chal_flags = ntlmssp_state->neg_flags; /* get the right name to fill in as 'target' */ - target_name = ntlmssp_target_name(ntlmssp_state, - neg_flags, &chal_flags); - if (target_name == NULL) + target_name = ntlmssp_target_name(ntlmssp_state, + neg_flags, &chal_flags); + if (target_name == NULL) return NT_STATUS_INVALID_PARAMETER; ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8); ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state->mem_ctx, cryptkey, 8); - /* This should be a 'netbios domain -> DNS domain' mapping */ - dnsdomname[0] = '\0'; - get_mydnsdomname(dnsdomname); + dnsdomname = get_mydnsdomname(ntlmssp_state->mem_ctx); + if (!dnsdomname) { + return NT_STATUS_BAD_NETWORK_NAME; + } strlower_m(dnsdomname); - - dnsname[0] = '\0'; - get_mydnsfullname(dnsname); - + + dnsname = get_mydnsfullname(); + if (!dnsdomname) { + return NT_STATUS_INVALID_COMPUTER_NAME; + } + /* This creates the 'blob' of names that appears at the end of the packet */ - if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) + if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { msrpc_gen(&struct_blob, "aaaaa", NTLMSSP_NAME_TYPE_DOMAIN, target_name, @@ -592,9 +596,9 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, } else { gen_string = "CdAdbddB"; } - + msrpc_gen(reply, gen_string, - "NTLMSSP", + "NTLMSSP", NTLMSSP_CHALLENGE, target_name, chal_flags, @@ -602,7 +606,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, 0, 0, struct_blob.data, struct_blob.length); } - + data_blob_free(&struct_blob); ntlmssp_state->expected_state = NTLMSSP_AUTH; @@ -612,7 +616,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /** * Next state function for the Authenticate packet - * + * * @param ntlmssp_state NTLMSSP State * @param request The request, as a DATA_BLOB * @param request The reply, as an allocated DATA_BLOB, caller to free. -- cgit From 533d6f617efc4dfe1e145785cb9736df07671bdf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 28 Dec 2007 17:02:34 +0100 Subject: Remove static zeros (This used to be commit dbcc213710a9af31b6094d4741a6f68f573dcdad) --- source3/libsmb/ntlmssp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index ed08e8102b..35c20ed647 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -823,7 +823,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, session_key.data); DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n")); } else { - static const uint8 zeros[24] = { 0, }; + uint8 zeros[24]; + ZERO_STRUCT(zeros); session_key = data_blob_talloc( ntlmssp_state->mem_ctx, NULL, 16); if (session_key.data == NULL) { @@ -1066,9 +1067,11 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, } if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) { - static const uchar zeros[16] = { 0, }; + uchar zeros[16]; /* do nothing - blobs are zero length */ + ZERO_STRUCT(zeros); + /* session key is all zeros */ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16); -- cgit From 45615d62838123bdf620a9c409d9868d47977800 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 29 Feb 2008 22:33:35 +0100 Subject: Check the right variable for being NULL (This used to be commit f2c67803792f1fd3929e922c1f626f8247e08992) --- source3/libsmb/ntlmssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 35c20ed647..8355669d9f 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -571,7 +571,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, strlower_m(dnsdomname); dnsname = get_mydnsfullname(); - if (!dnsdomname) { + if (!dnsname) { return NT_STATUS_INVALID_COMPUTER_NAME; } -- cgit From 5e0d86c4076f9b04a2c79ab47b497924248050aa Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 29 Feb 2008 22:38:10 +0100 Subject: Restore 3.0 behaviour with empty /etc/hosts Jeremy, in 3.0 we allowed get_mydnsdomname and get_mydnsfullname to fail without filling in anything useful. Worked fine. Without this patch and a empty /etc/hosts and no DNS configured, session setup would return NT_STATUS_BAD_NETWORK_NAME. This is confusing at best, BAD_NETWORK_NAME afaik is only ever returned from tcon normally. This restores the 3.0 behaviour. Comments? Volker (This used to be commit 2bd3b7d474768f842921945d283eac10da2a1684) --- source3/libsmb/ntlmssp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 8355669d9f..7082ea7e4e 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -566,13 +566,16 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname = get_mydnsdomname(ntlmssp_state->mem_ctx); if (!dnsdomname) { - return NT_STATUS_BAD_NETWORK_NAME; + dnsdomname = talloc_strdup(ntlmssp_state->mem_ctx, ""); + } + if (!dnsdomname) { + return NT_STATUS_NO_MEMORY; } strlower_m(dnsdomname); dnsname = get_mydnsfullname(); if (!dnsname) { - return NT_STATUS_INVALID_COMPUTER_NAME; + dnsname = ""; } /* This creates the 'blob' of names that appears at the end of the packet */ -- cgit From e7142ef180d88e5e0daa6b853a04ff9f1ce4d22a Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 30 Apr 2008 18:47:40 +0200 Subject: ntlmssp: replace UNKNOWN_02000000 with NTLMSSP_NEGOTIATE_VERSION. Guenther (This used to be commit 2c41d69bcf6f0897ef9d444a8f167aff1772d562) --- source3/libsmb/ntlmssp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/libsmb/ntlmssp.c') diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 7082ea7e4e..a0e54ce769 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -95,6 +95,8 @@ void debug_ntlmssp_flags(uint32 neg_flags) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM2\n")); if (neg_flags & NTLMSSP_CHAL_TARGET_INFO) DEBUGADD(4, (" NTLMSSP_CHAL_TARGET_INFO\n")); + if (neg_flags & NTLMSSP_NEGOTIATE_VERSION) + DEBUGADD(4, (" NTLMSSP_NEGOTIATE_VERSION\n")); if (neg_flags & NTLMSSP_NEGOTIATE_128) DEBUGADD(4, (" NTLMSSP_NEGOTIATE_128\n")); if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) @@ -449,8 +451,8 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, /* Woop Woop - unknown flag for Windows compatibility... What does this really do ? JRA. */ - if (!(neg_flags & NTLMSSP_UNKNOWN_02000000)) { - ntlmssp_state->neg_flags &= ~NTLMSSP_UNKNOWN_02000000; + if (!(neg_flags & NTLMSSP_NEGOTIATE_VERSION)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_VERSION; } if ((neg_flags & NTLMSSP_REQUEST_TARGET)) { @@ -934,7 +936,7 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) (*ntlmssp_state)->neg_flags = NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_56 | - NTLMSSP_UNKNOWN_02000000 | + NTLMSSP_NEGOTIATE_VERSION | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | -- cgit