r13470: Thanks to a report from VL:
authorAndrew Bartlett <abartlet@samba.org>
Sun, 12 Feb 2006 12:42:37 +0000 (12:42 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:51:54 +0000 (13:51 -0500)
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

source/auth/ntlmssp/ntlmssp.c
source/auth/ntlmssp/ntlmssp_client.c
source/auth/ntlmssp/ntlmssp_server.c
source/auth/ntlmssp/ntlmssp_sign.c

index e1c748c558eba426813e10c82915b28c2e51ffef..d4edfb97aadecdc56449d41225208431e49c0a0a 100644 (file)
@@ -64,6 +64,8 @@ void debug_ntlmssp_flags(uint32_t 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) 
@@ -78,6 +80,10 @@ void debug_ntlmssp_flags(uint32_t 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) 
@@ -86,6 +92,8 @@ void debug_ntlmssp_flags(uint32_t 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"));
 }
 
 static NTSTATUS gensec_ntlmssp_magic(struct gensec_security *gensec_security, 
@@ -277,11 +285,16 @@ void ntlmssp_handle_neg_flags(struct gensec_ntlmssp_state *gensec_ntlmssp_state,
    by the client lanman auth/lanman auth parameters, it isn't too bad.
 */
 
-void ntlmssp_weaken_keys(struct gensec_ntlmssp_state *gensec_ntlmssp_state) 
+DATA_BLOB ntlmssp_weakend_key(struct gensec_ntlmssp_state *gensec_ntlmssp_state, 
+                             TALLOC_CTX *mem_ctx) 
 {
+       DATA_BLOB weakened_key = data_blob_talloc(mem_ctx, 
+                                                 gensec_ntlmssp_state->session_key.data, 
+                                                 gensec_ntlmssp_state->session_key.length);
        /* Nothing to weaken.  We certainly don't want to 'extend' the length... */
-       if (gensec_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
@@ -292,14 +305,15 @@ void ntlmssp_weaken_keys(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
                if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) {
                        
                } else if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {
-                       gensec_ntlmssp_state->session_key.data[7] = 0xa0;
+                       weakened_key.data[7] = 0xa0;
                } else { /* forty bits */
-                       gensec_ntlmssp_state->session_key.data[5] = 0xe5;
-                       gensec_ntlmssp_state->session_key.data[6] = 0x38;
-                       gensec_ntlmssp_state->session_key.data[7] = 0xb0;
+                       weakened_key.data[5] = 0xe5;
+                       weakened_key.data[6] = 0x38;
+                       weakened_key.data[7] = 0xb0;
                }
-               gensec_ntlmssp_state->session_key.length = 8;
+               weakened_key.length = 8;
        }
+       return weakened_key;
 }
 
 static BOOL gensec_ntlmssp_have_feature(struct gensec_security *gensec_security,
index d058b84a2844dd15f6d65413f6298c9d146869ab..c2a1e1cde8086c397c7c8500db2192261f42ae0e 100644 (file)
@@ -259,9 +259,6 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
 
        talloc_steal(out_mem_ctx, out->data);
 
-       /* The client might be using 56 or 40 bit weakened keys */
-       ntlmssp_weaken_keys(gensec_ntlmssp_state);
-
        gensec_ntlmssp_state->chal = challenge_blob;
        gensec_ntlmssp_state->lm_resp = lm_response;
        talloc_steal(gensec_ntlmssp_state->lm_resp.data, lm_response.data);
index de44d40a50342419057f73e289953df595b1c280..65956d0580101a1e5337a178a5e26caea1dde073 100644 (file)
@@ -554,9 +554,6 @@ static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,
        /* keep the session key around on the new context */
        talloc_steal(gensec_ntlmssp_state, session_key.data);
 
-       /* The server might need us to use a partial-strength session key */
-       ntlmssp_weaken_keys(gensec_ntlmssp_state);
-
        if ((gensec_security->want_features & GENSEC_FEATURE_SIGN)
            || (gensec_security->want_features & GENSEC_FEATURE_SEAL)) {
                nt_status = ntlmssp_sign_init(gensec_ntlmssp_state);
index 41075cd25b2f1478c23666fd21e6e029abaa520b..de1720be4cdb85c8ef653fc2300a4cf7cb9baa00 100644 (file)
@@ -299,13 +299,17 @@ NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security,
 */
 NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
 {
-       uint8_t p24[24];
-       ZERO_STRUCT(p24);
+       TALLOC_CTX *mem_ctx = talloc_new(gensec_ntlmssp_state);
+
+       if (!mem_ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n"));
        debug_ntlmssp_flags(gensec_ntlmssp_state->neg_flags);
 
-       if (!gensec_ntlmssp_state->session_key.length) {
+       if (gensec_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;
        }
@@ -335,6 +339,7 @@ NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
                        recv_seal_const = CLI_SEAL;
                        break;
                default:
+                       talloc_free(mem_ctx);
                        return NT_STATUS_INTERNAL_ERROR;
                }
                
@@ -368,7 +373,7 @@ NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
                             weak_session_key.data, 
                             weak_session_key.length);
 
-               /* SEND */
+               /* SEND: sign key */
                calc_ntlmv2_key(gensec_ntlmssp_state, 
                                &gensec_ntlmssp_state->crypt.ntlm2.send_sign_key, 
                                gensec_ntlmssp_state->session_key, send_sign_const);
@@ -376,21 +381,20 @@ NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
                             gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.data, 
                             gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.length);
                
-               calc_ntlmv2_key(gensec_ntlmssp_state, 
+               /* SEND: seal ARCFOUR pad */
+               calc_ntlmv2_key(mem_ctx, 
                                &send_seal_key, 
                                weak_session_key, send_seal_const);
                dump_data_pw("NTLMSSP send seal key:\n",
                             send_seal_key.data, 
                             send_seal_key.length);
-
                arcfour_init(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, 
                             &send_seal_key);
-
                dump_data_pw("NTLMSSP send sesl hash:\n", 
                             gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state->sbox, 
                             sizeof(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state->sbox));
 
-               /* RECV */
+               /* RECV: sign key */
                calc_ntlmv2_key(gensec_ntlmssp_state, 
                                &gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key, 
                                gensec_ntlmssp_state->session_key, recv_sign_const);
@@ -398,7 +402,8 @@ NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
                             gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.data, 
                             gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.length);
 
-               calc_ntlmv2_key(gensec_ntlmssp_state, 
+               /* RECV: seal ARCFOUR pad */
+               calc_ntlmv2_key(mem_ctx, 
                                &recv_seal_key, 
                                weak_session_key, recv_seal_const);
                dump_data_pw("NTLMSSP recv seal key:\n",
@@ -406,7 +411,6 @@ NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
                             recv_seal_key.length);
                arcfour_init(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state, 
                             &recv_seal_key);
-
                dump_data_pw("NTLMSSP receive seal hash:\n", 
                             gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state->sbox, 
                             sizeof(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state->sbox));
@@ -415,19 +419,21 @@ NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state)
                gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num = 0;
 
        } else {
+               DATA_BLOB weak_session_key = ntlmssp_weakend_key(gensec_ntlmssp_state, mem_ctx);
                DEBUG(5, ("NTLMSSP Sign/Seal - using NTLM1\n"));
 
                gensec_ntlmssp_state->crypt.ntlm.arcfour_state = talloc(gensec_ntlmssp_state, struct arcfour_state);
                NT_STATUS_HAVE_NO_MEMORY(gensec_ntlmssp_state->crypt.ntlm.arcfour_state);
 
                arcfour_init(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, 
-                            &gensec_ntlmssp_state->session_key);
+                            &weak_session_key);
                dump_data_pw("NTLMSSP hash:\n", gensec_ntlmssp_state->crypt.ntlm.arcfour_state->sbox,
                             sizeof(gensec_ntlmssp_state->crypt.ntlm.arcfour_state->sbox));
 
                gensec_ntlmssp_state->crypt.ntlm.seq_num = 0;
        }
 
+       talloc_free(mem_ctx);
        return NT_STATUS_OK;
 }