--- a/source/include/nterr.h 2009-09-30 14:24:50.000000000 +0200 +++ b/source/include/nterr.h 2016-04-14 21:52:47.000000000 +0200 @@ -567,5 +567,6 @@ #define NT_STATUS_NO_SUCH_JOB NT_STATUS(0xC0000000 | 0xEDE) /* scheduler */ #define NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED NT_STATUS(0xC0000000 | 0x20004) #define NT_STATUS_RPC_CANNOT_SUPPORT NT_STATUS(0xC0000000 | 0x20041) +#define NT_STATUS_RPC_SEC_PKG_ERROR NT_STATUS(0xC0000000 | 0x20057) #endif /* _NTERR_H */ --- a/source/include/ntlmssp.h 2009-09-30 14:24:50.000000000 +0200 +++ b/source/include/ntlmssp.h 2016-04-15 00:07:13.000000000 +0200 @@ -85,6 +85,7 @@ bool unicode; bool use_ntlmv2; + bool allow_lm_key; char *user; char *domain; char *workstation; @@ -98,7 +99,8 @@ DATA_BLOB lm_resp; DATA_BLOB nt_resp; DATA_BLOB session_key; - + + uint32 required_flags; uint32 neg_flags; /* the current state of negotiation with the NTLMSSP partner */ void *auth_context; --- a/source/libsmb/ntlmssp.c 2009-09-30 14:24:50.000000000 +0200 +++ b/source/libsmb/ntlmssp.c 2016-04-14 22:36:58.000000000 +0200 @@ -246,14 +246,16 @@ * 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; } + + ntlmssp_state->neg_flags |= ntlmssp_state->required_flags; } /** @@ -266,14 +268,17 @@ { /* 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; } + + ntlmssp_state->neg_flags |= ntlmssp_state->required_flags; } /** @@ -969,6 +974,12 @@ 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 */ @@ -984,6 +995,93 @@ return NT_STATUS_MORE_PROCESSING_REQUIRED; } +static NTSTATUS ntlmssp3_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, + uint32 neg_flags) + +{ + uint32 missing_flags = ntlmssp_state->required_flags; + + 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; + } + + /* + * NTLMSSP_NEGOTIATE_NTLM2 (NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) + * has priority over NTLMSSP_NEGOTIATE_LM_KEY + */ + if (!(neg_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 (!(neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)) { + 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_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_KEY_EXCH)) { + 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; + } + + 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)neg_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. * @@ -1025,7 +1123,10 @@ DEBUG(3, ("Got challenge flags:\n")); debug_ntlmssp_flags(chal_flags); - ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth()); + nt_status = ntlmssp3_handle_neg_flags(ntlmssp_state, chal_flags); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } if (ntlmssp_state->unicode) { if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { @@ -1232,6 +1333,7 @@ (*ntlmssp_state)->unicode = True; (*ntlmssp_state)->use_ntlmv2 = lp_client_ntlmv2_auth(); + (*ntlmssp_state)->allow_lm_key = lp_client_lanman_auth(); (*ntlmssp_state)->expected_state = NTLMSSP_INITIAL; @@ -1245,5 +1347,9 @@ NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_REQUEST_TARGET; + if ((*ntlmssp_state)->use_ntlmv2) { + (*ntlmssp_state)->allow_lm_key = False; + } + return NT_STATUS_OK; }