r13473: Back port r13470, r13471, r13472 from Samba4. Thanks Andrew:
authorJeremy Allison <jra@samba.org>
Sun, 12 Feb 2006 16:44:30 +0000 (16:44 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:10:05 +0000 (11:10 -0500)
-----------------------------------
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
source3/libsmb/ntlmssp_sign.c

index c891ede9bb7d7c02aaaa7443e876599cd0abdb87..e1ef69aed9911eda45757f9bc7718512c1487a54 100644 (file)
@@ -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;
index cc6323718b34b7964c71755ad05f326a10a442ca..1cdb2d1e00dd8dffcac877a3f1a8a00473e5156c 100644 (file)
@@ -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;
 }