From 202d69267c8550b850438877fb51c3d2c992949d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher 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 Reviewed-by: Günther Deschner --- 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 */ /**