From d672d8fd6bd2957f6177c809c77b3d2c1a2fddca Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 12 Feb 2006 16:44:30 +0000 Subject: [PATCH] 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 ++++++++++++++++++++++++++----------------- source3/libsmb/ntlmssp_sign.c | 31 +++++++++++++++++++------------ 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index c891ede9bb7..e1ef69aed99 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; diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c index cc6323718b3..1cdb2d1e00d 100644 --- a/source3/libsmb/ntlmssp_sign.c +++ b/source3/libsmb/ntlmssp_sign.c @@ -328,17 +328,22 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) { unsigned char p24[24]; ZERO_STRUCT(p24); + TALLOC_CTX *mem_ctx = talloc_init("weak_keys"); + + if (!mem_ctx) { + return NT_STATUS_NO_MEMORY; + } DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n")); debug_ntlmssp_flags(ntlmssp_state->neg_flags); - if (!ntlmssp_state->session_key.length) { + if (ntlmssp_state->session_key.length < 8) { + talloc_free(mem_ctx); DEBUG(3, ("NO session key, cannot intialise signing\n")); return NT_STATUS_NO_USER_SESSION_KEY; } - if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) - { + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { DATA_BLOB weak_session_key = ntlmssp_state->session_key; const char *send_sign_const; const char *send_seal_const; @@ -359,11 +364,8 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) recv_seal_const = CLI_SEAL; break; default: - send_sign_const = "unknown role"; - send_seal_const = "unknown role"; - recv_sign_const = "unknown role"; - recv_seal_const = "unknown role"; - break; + talloc_free(mem_ctx); + return NT_STATUS_INTERNAL_ERROR; } /** @@ -374,7 +376,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) { ; } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { - weak_session_key.length = 6; + weak_session_key.length = 7; } else { /* forty bits */ weak_session_key.length = 5; } @@ -383,12 +385,13 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) weak_session_key.data, weak_session_key.length); - /* SEND */ + /* SEND: sign key */ calc_ntlmv2_key(ntlmssp_state->send_sign_key, ntlmssp_state->session_key, send_sign_const); dump_data_pw("NTLMSSP send sign key:\n", ntlmssp_state->send_sign_key, 16); + /* SEND: seal ARCFOUR pad */ calc_ntlmv2_key(ntlmssp_state->send_seal_key, weak_session_key, send_seal_const); dump_data_pw("NTLMSSP send seal key:\n", @@ -401,12 +404,13 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) ntlmssp_state->send_seal_arc4_state, sizeof(ntlmssp_state->send_seal_arc4_state)); - /* RECV */ + /* RECV: sign key */ calc_ntlmv2_key(ntlmssp_state->recv_sign_key, ntlmssp_state->session_key, recv_sign_const); dump_data_pw("NTLMSSP recv send sign key:\n", ntlmssp_state->recv_sign_key, 16); + /* RECV: seal ARCFOUR pad */ calc_ntlmv2_key(ntlmssp_state->recv_seal_key, weak_session_key, recv_seal_const); @@ -446,10 +450,12 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) weak_session_key.length); #endif + DATA_BLOB weak_session_key = ntlmssp_weaken_keys(ntlmssp_state, mem_ctx); + DEBUG(5, ("NTLMSSP Sign/Seal - using NTLM1\n")); smb_arc4_init(ntlmssp_state->ntlmv1_arc4_state, - ntlmssp_state->session_key.data, ntlmssp_state->session_key.length); + weak_session_key.data, weak_session_key.length); dump_data_pw("NTLMv1 arc4 state:\n", ntlmssp_state->ntlmv1_arc4_state, sizeof(ntlmssp_state->ntlmv1_arc4_state)); @@ -457,5 +463,6 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) ntlmssp_state->ntlmv1_seq_num = 0; } + talloc_free(mem_ctx); return NT_STATUS_OK; } -- 2.11.4.GIT