You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
7.6 KiB
255 lines
7.6 KiB
From 202d69267c8550b850438877fb51c3d2c992949d Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Tue, 1 Dec 2015 08:46:45 +0100
|
|
Subject: [PATCH 01/10] CVE-2016-2110: s3:ntlmssp: set and use
|
|
ntlmssp_state->allow_lm_key
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11644
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Günther Deschner <gd@samba.org>
|
|
---
|
|
source3/libsmb/ntlmssp.c | 4 +++-
|
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
|
--- a/source3/libsmb/ntlmssp.c
|
|
+++ b/source3/libsmb/ntlmssp.c
|
|
@@ -176,17 +176,19 @@ void ntlmssp_want_feature_list(struct nt
|
|
* also add NTLMSSP_NEGOTIATE_SEAL here. JRA.
|
|
*/
|
|
if (in_list("NTLMSSP_FEATURE_SESSION_KEY", feature_list, True)) {
|
|
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
+ ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
}
|
|
if (in_list("NTLMSSP_FEATURE_SIGN", feature_list, True)) {
|
|
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
+ ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
}
|
|
if(in_list("NTLMSSP_FEATURE_SEAL", feature_list, True)) {
|
|
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
|
|
+ ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
|
|
}
|
|
if (in_list("NTLMSSP_FEATURE_CCACHE", feature_list, true)) {
|
|
ntlmssp_state->use_ccache = true;
|
|
}
|
|
+
|
|
+ ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
|
|
}
|
|
|
|
/**
|
|
@@ -199,17 +201,20 @@ void ntlmssp_want_feature(struct ntlmssp
|
|
{
|
|
/* As per JRA's comment above */
|
|
if (feature & NTLMSSP_FEATURE_SESSION_KEY) {
|
|
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
+ ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
}
|
|
if (feature & NTLMSSP_FEATURE_SIGN) {
|
|
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
+ ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
}
|
|
if (feature & NTLMSSP_FEATURE_SEAL) {
|
|
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
|
|
+ ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
|
+ ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_SEAL;
|
|
}
|
|
if (feature & NTLMSSP_FEATURE_CCACHE) {
|
|
ntlmssp_state->use_ccache = true;
|
|
}
|
|
+
|
|
+ ntlmssp_state->neg_flags |= ntlmssp_state->required_flags;
|
|
}
|
|
|
|
/**
|
|
@@ -387,7 +392,12 @@ static NTSTATUS ntlmssp_client_initial(s
|
|
}
|
|
|
|
if (ntlmssp_state->use_ntlmv2) {
|
|
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
|
|
+ ntlmssp_state->required_flags |= NTLMSSP_NEGOTIATE_NTLM2;
|
|
+ ntlmssp_state->allow_lm_key = false;
|
|
+ }
|
|
+
|
|
+ if (ntlmssp_state->allow_lm_key) {
|
|
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
|
|
}
|
|
|
|
/* generate the ntlmssp negotiate packet */
|
|
@@ -422,6 +432,86 @@ static NTSTATUS ntlmssp_client_initial(s
|
|
return NT_STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
+static NTSTATUS ntlmssp3_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
|
|
+ uint32_t flags)
|
|
+{
|
|
+ uint32_t missing_flags = ntlmssp_state->required_flags;
|
|
+
|
|
+ if (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;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * NTLMSSP_NEGOTIATE_NTLM2 (NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)
|
|
+ * has priority over NTLMSSP_NEGOTIATE_LM_KEY
|
|
+ */
|
|
+ if (!(flags & NTLMSSP_NEGOTIATE_NTLM2)) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
|
|
+ }
|
|
+
|
|
+ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
|
|
+ }
|
|
+
|
|
+ if (!(flags & NTLMSSP_NEGOTIATE_LM_KEY)) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
|
|
+ }
|
|
+
|
|
+ if (!(flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
|
|
+ }
|
|
+
|
|
+ if (!(flags & NTLMSSP_NEGOTIATE_128)) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
|
|
+ }
|
|
+
|
|
+ if (!(flags & NTLMSSP_NEGOTIATE_56)) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56;
|
|
+ }
|
|
+
|
|
+ if (!(flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
|
|
+ }
|
|
+
|
|
+ if (!(flags & NTLMSSP_NEGOTIATE_SIGN)) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
|
|
+ }
|
|
+
|
|
+ if (!(flags & NTLMSSP_NEGOTIATE_SEAL)) {
|
|
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL;
|
|
+ }
|
|
+
|
|
+ if ((flags & NTLMSSP_REQUEST_TARGET)) {
|
|
+ ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET;
|
|
+ }
|
|
+
|
|
+ missing_flags &= ~ntlmssp_state->neg_flags;
|
|
+ if (missing_flags != 0) {
|
|
+ NTSTATUS status = NT_STATUS_RPC_SEC_PKG_ERROR;
|
|
+ DEBUG(1, ("%s: Got challenge flags[0x%08x] "
|
|
+ "- possible downgrade detected! "
|
|
+ "missing_flags[0x%08x] - %s\n",
|
|
+ __func__,
|
|
+ (unsigned)flags,
|
|
+ (unsigned)missing_flags,
|
|
+ nt_errstr(status)));
|
|
+ debug_ntlmssp_flags(missing_flags);
|
|
+ DEBUGADD(4, ("neg_flags[0x%08x]\n",
|
|
+ (unsigned)ntlmssp_state->neg_flags));
|
|
+ debug_ntlmssp_flags(ntlmssp_state->neg_flags);
|
|
+
|
|
+ return status;
|
|
+ }
|
|
+
|
|
+ return NT_STATUS_OK;
|
|
+}
|
|
+
|
|
/**
|
|
* Next state function for the Challenge Packet. Generate an auth packet.
|
|
*
|
|
@@ -448,6 +538,26 @@ static NTSTATUS ntlmssp_client_challenge
|
|
DATA_BLOB encrypted_session_key = data_blob_null;
|
|
NTSTATUS nt_status = NT_STATUS_OK;
|
|
|
|
+ if (!msrpc_parse(ntlmssp_state, &reply, "CdBd",
|
|
+ "NTLMSSP",
|
|
+ &ntlmssp_command,
|
|
+ &server_domain_blob,
|
|
+ &chal_flags)) {
|
|
+ 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);
|
|
+
|
|
+ nt_status = ntlmssp3_handle_neg_flags(ntlmssp_state, chal_flags);
|
|
+ if (!NT_STATUS_IS_OK(nt_status)) {
|
|
+ return nt_status;
|
|
+ }
|
|
+
|
|
if (ntlmssp_state->use_ccache) {
|
|
struct wbcCredentialCacheParams params;
|
|
struct wbcCredentialCacheInfo *info = NULL;
|
|
@@ -498,17 +608,6 @@ static NTSTATUS ntlmssp_client_challenge
|
|
|
|
noccache:
|
|
|
|
- if (!msrpc_parse(ntlmssp_state, &reply, "CdBd",
|
|
- "NTLMSSP",
|
|
- &ntlmssp_command,
|
|
- &server_domain_blob,
|
|
- &chal_flags)) {
|
|
- DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
|
|
- dump_data(2, reply.data, reply.length);
|
|
-
|
|
- return NT_STATUS_INVALID_PARAMETER;
|
|
- }
|
|
-
|
|
if (DEBUGLEVEL >= 10) {
|
|
struct CHALLENGE_MESSAGE *challenge = talloc(
|
|
talloc_tos(), struct CHALLENGE_MESSAGE);
|
|
@@ -525,13 +624,6 @@ noccache:
|
|
}
|
|
}
|
|
|
|
- data_blob_free(&server_domain_blob);
|
|
-
|
|
- DEBUG(3, ("Got challenge flags:\n"));
|
|
- debug_ntlmssp_flags(chal_flags);
|
|
-
|
|
- ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth());
|
|
-
|
|
if (ntlmssp_state->unicode) {
|
|
if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
|
|
chal_parse_string = "CdUdbddB";
|
|
@@ -769,6 +861,7 @@ NTSTATUS ntlmssp_client_start(TALLOC_CTX
|
|
ntlmssp_state->unicode = True;
|
|
|
|
ntlmssp_state->use_ntlmv2 = use_ntlmv2;
|
|
+ ntlmssp_state->allow_lm_key = lp_client_lanman_auth();
|
|
|
|
ntlmssp_state->expected_state = NTLMSSP_INITIAL;
|
|
|
|
@@ -780,6 +873,10 @@ NTSTATUS ntlmssp_client_start(TALLOC_CTX
|
|
NTLMSSP_NEGOTIATE_KEY_EXCH |
|
|
NTLMSSP_REQUEST_TARGET;
|
|
|
|
+ if (ntlmssp_state->use_ntlmv2) {
|
|
+ ntlmssp_state->allow_lm_key = false;
|
|
+ }
|
|
+
|
|
ntlmssp_state->client.netbios_name = talloc_strdup(ntlmssp_state, netbios_name);
|
|
if (!ntlmssp_state->client.netbios_name) {
|
|
talloc_free(ntlmssp_state);
|
|
--- a/libcli/auth/ntlmssp.h
|
|
+++ b/libcli/auth/ntlmssp.h
|
|
@@ -83,6 +83,7 @@ struct ntlmssp_state
|
|
DATA_BLOB nt_resp;
|
|
DATA_BLOB session_key;
|
|
|
|
+ uint32_t required_flags;
|
|
uint32_t neg_flags; /* the current state of negotiation with the NTLMSSP partner */
|
|
|
|
/**
|
|
|