Merge NTLMSSP fixes from 3.0 to HEAD.
authorAndrew Bartlett <abartlet@samba.org>
Tue, 6 Jan 2004 08:12:35 +0000 (08:12 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 6 Jan 2004 08:12:35 +0000 (08:12 +0000)
Andrew Bartlett
(This used to be commit f7d39c787771616ddb015bd77e3e6cd33f0c7a15)

source3/include/ntlmssp.h
source3/libsmb/ntlmssp.c
source3/libsmb/ntlmssp_sign.c
source3/libsmb/pwd_cache.c
source3/rpc_client/cli_pipe.c

index 681d4071dbb4ee3dc445213e1b20d8cf0b6c13cb..24ac79676150251d746551e73bd150392e20e7aa 100644 (file)
@@ -147,10 +147,10 @@ typedef struct ntlmssp_state
        uint32 ntlmssp_seq_num;
 
        /* ntlmv2 */
-       char send_sign_const[16];
-       char send_seal_const[16];
-       char recv_sign_const[16];
-       char recv_seal_const[16];
+       unsigned char send_sign_const[16];
+       unsigned char send_seal_const[16];
+       unsigned char recv_sign_const[16];
+       unsigned char recv_seal_const[16];
 
        unsigned char send_sign_hash[258];
        unsigned char send_seal_hash[258];
index 7b821da0fd6254a8a0b76ca388d9b1dbd0eaee88..40d7f4110962451cdf34c9f746c6fa3607c1317f 100644 (file)
@@ -338,6 +338,10 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
                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_NTLM2)) {
                ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
        }
@@ -577,6 +581,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
                }
        }
 
+       if (auth_flags)
+               ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth());
+
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
                SAFE_FREE(domain);
                SAFE_FREE(user);
@@ -654,7 +661,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
 
        /* Finally, actually ask if the password is OK */
 
-       if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, &nt_session_key, &lm_session_key))) {
+       if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, 
+                                                                      &nt_session_key, &lm_session_key))) {
                data_blob_free(&encrypted_session_key);
                return nt_status;
        }
@@ -670,24 +678,28 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
                                 sizeof(session_nonce), session_key.data);
                        DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
                        dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
-
-               }else {
-                       data_blob_free(&encrypted_session_key);
+                       
+               } else {
                        DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
-                       return NT_STATUS_INVALID_PARAMETER;
+                       session_key = data_blob(NULL, 0);
                }
        } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
-               if (lm_session_key.data && lm_session_key.length >= 8 && 
-                   ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
-                       session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
-                       SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, 
-                                          session_key.data);
-                       DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
-                       dump_data_pw("LM session key:\n", session_key.data, session_key.length);
+               if (lm_session_key.data && lm_session_key.length >= 8) {
+                       if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
+                               session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
+                               SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, 
+                                                         session_key.data);
+                               DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
+                               dump_data_pw("LM session key:\n", session_key.data, session_key.length);
+                       } else {
+                               /* use the key unmodified - it's
+                                * probably a NULL key from the guest
+                                * login */
+                               session_key = lm_session_key;
+                       }
                } else {
-                       data_blob_free(&encrypted_session_key);
                        DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
-                       return NT_STATUS_INVALID_PARAMETER;
+                       session_key = data_blob(NULL, 0);
                }
        } else if (nt_session_key.data) {
                session_key = nt_session_key;
@@ -698,9 +710,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
                DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
                dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
        } else {
-               data_blob_free(&encrypted_session_key);
                DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
-               return NT_STATUS_INVALID_PARAMETER;
+               session_key = data_blob(NULL, 0);
        }
 
        /* With KEY_EXCH, the client supplies the proposed session key, 
@@ -714,6 +725,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
                } else if (!session_key.data || session_key.length != 16) {
                        DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", 
                                  session_key.length));
+                       ntlmssp_state->session_key = session_key;
                } else {
                        dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
                        SamOEMhash(encrypted_session_key.data, 
@@ -723,12 +735,18 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
                                                                      encrypted_session_key.data, 
                                                                      encrypted_session_key.length);
                        dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, 
-                               encrypted_session_key.length);
+                                    encrypted_session_key.length);
                }
        } else {
                ntlmssp_state->session_key = session_key;
        }
 
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               ntlmssp_state->session_key = data_blob(NULL, 0);
+       } else if (ntlmssp_state->session_key.length) {
+               nt_status = ntlmssp_sign_init(ntlmssp_state);
+       }
+
        data_blob_free(&encrypted_session_key);
        
        /* allow arbitarily many authentications */
@@ -906,7 +924,14 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
        }
 
        if (!ntlmssp_state->password) {
+               static const uchar zeros[16];
                /* do nothing - blobs are zero length */
+
+               /* session key is all zeros */
+               session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16);
+               
+               /* not doing NLTM2 without a password */
+               ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
        } else if (ntlmssp_state->use_ntlmv2) {
 
                if (!struct_blob.length) {
index ea1a7037c9ccb5af0aef247b9d86a7b8fb136838..6ce7a76743b5f904597c23cbe81510eb8b8fd2e0 100644 (file)
@@ -53,7 +53,7 @@ static void NTLMSSPcalc_ap( unsigned char *hash, unsigned char *data, int len)
     hash[257] = index_j;
 }
 
-static void calc_hash(unsigned char *hash, const char *k2, int k2l)
+static void calc_hash(unsigned char hash[258], const char *k2, int k2l)
 {
        unsigned char j = 0;
        int ind;
@@ -78,7 +78,7 @@ static void calc_hash(unsigned char *hash, const char *k2, int k2l)
        hash[257] = 0;
 }
 
-static void calc_ntlmv2_hash(unsigned char hash[16], char digest[16],
+static void calc_ntlmv2_hash(unsigned char hash[258], unsigned char digest[16],
                             DATA_BLOB session_key, 
                             const char *constant)
 {
@@ -91,8 +91,8 @@ static void calc_ntlmv2_hash(unsigned char hash[16], char digest[16],
 
        MD5Init(&ctx3);
        MD5Update(&ctx3, session_key.data, session_key.length);
-       MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant));
-       MD5Final((unsigned char *)digest, &ctx3);
+       MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant)+1);
+       MD5Final(digest, &ctx3);
 
        calc_hash(hash, digest, 16);
 }
@@ -109,12 +109,12 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
 {
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
                HMACMD5Context ctx;
-               char seq_num[4];
+               uchar seq_num[4];
                uchar digest[16];
                SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
 
                hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
-               hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
+               hmac_md5_update(seq_num, 4, &ctx);
                hmac_md5_update(data, length, &ctx);
                hmac_md5_final(digest, &ctx);
 
@@ -122,13 +122,16 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
                               , ntlmssp_state->ntlmssp_seq_num)) {
                        return NT_STATUS_NO_MEMORY;
                }
-               switch (direction) {
-               case NTLMSSP_SEND:
-                       NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
-                       break;
-               case NTLMSSP_RECEIVE:
-                       NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash,  sig->data+4, sig->length-4);
-                       break;
+
+               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+                       switch (direction) {
+                       case NTLMSSP_SEND:
+                               NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
+                               break;
+                       case NTLMSSP_RECEIVE:
+                               NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash,  sig->data+4, sig->length-4);
+                               break;
+                       }
                }
        } else {
                uint32 crc;
@@ -148,7 +151,13 @@ NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
                                    const uchar *data, size_t length, 
                                    DATA_BLOB *sig) 
 {
-       NTSTATUS nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig);
+       NTSTATUS nt_status;
+       if (!ntlmssp_state->session_key.length) {
+               DEBUG(3, ("NO session key, cannot check sign packet\n"));
+               return NT_STATUS_NO_USER_SESSION_KEY;
+       }
+
+       nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig);
 
        /* increment counter on send */
        ntlmssp_state->ntlmssp_seq_num++;
@@ -168,6 +177,11 @@ NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
        DATA_BLOB local_sig;
        NTSTATUS nt_status;
 
+       if (!ntlmssp_state->session_key.length) {
+               DEBUG(3, ("NO session key, cannot check packet signature\n"));
+               return NT_STATUS_NO_USER_SESSION_KEY;
+       }
+
        if (sig->length < 8) {
                DEBUG(0, ("NTLMSSP packet check failed due to short signature (%lu bytes)!\n", 
                          (unsigned long)sig->length));
@@ -208,6 +222,11 @@ NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
                             uchar *data, size_t length,
                             DATA_BLOB *sig)
 {      
+       if (!ntlmssp_state->session_key.length) {
+               DEBUG(3, ("NO session key, cannot seal packet\n"));
+               return NT_STATUS_NO_USER_SESSION_KEY;
+       }
+
        DEBUG(10,("ntlmssp_seal_data: seal\n"));
        dump_data_pw("ntlmssp clear data\n", data, length);
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
@@ -270,6 +289,11 @@ NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
                                      uchar *data, size_t length,
                                      DATA_BLOB *sig)
 {
+       if (!ntlmssp_state->session_key.length) {
+               DEBUG(3, ("NO session key, cannot unseal packet\n"));
+               return NT_STATUS_NO_USER_SESSION_KEY;
+       }
+
        DEBUG(10,("ntlmssp__unseal_data: seal\n"));
        dump_data_pw("ntlmssp sealed data\n", data, length);
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
@@ -295,6 +319,11 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
        DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n"));
        debug_ntlmssp_flags(ntlmssp_state->neg_flags);
 
+       if (!ntlmssp_state->session_key.length) {
+               DEBUG(3, ("NO session key, cannot intialise signing\n"));
+               return NT_STATUS_NO_USER_SESSION_KEY;
+       }
+
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
        {
                const char *send_sign_const;
index f45832d7d75a16a4f7d3b8e29070d852cca8d114..7ba6cfc96f0a86ec58fde26a2870e22290403644 100644 (file)
@@ -45,8 +45,14 @@ static void pwd_make_lm_nt_16(struct pwd_info *pwd, const char *clr)
 {
        pwd_init(pwd);
 
-       nt_lm_owf_gen(clr, pwd->smb_nt_pwd, pwd->smb_lm_pwd);
-       pwd->null_pwd  = False;
+       if (!clr) {
+               ZERO_STRUCT(pwd->smb_nt_pwd);
+               ZERO_STRUCT(pwd->smb_lm_pwd);
+               pwd->null_pwd  = True;
+       } else {
+               nt_lm_owf_gen(clr, pwd->smb_nt_pwd, pwd->smb_lm_pwd);
+               pwd->null_pwd  = False;
+       }
        pwd->crypted = False;
 }
 
index 49abf787eed590562fb7c150f49cc645d219401e..3213e955b682bfbca1ac3525c022628339aba7bc 100644 (file)
@@ -1342,11 +1342,18 @@ static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_na
                if (!NT_STATUS_IS_OK(nt_status))
                        return False;
 
-               pwd_get_cleartext(&cli->pwd, password);
-               nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
-                                                password);
-               if (!NT_STATUS_IS_OK(nt_status))
-                       return False;
+               if (cli->pwd.null_pwd) {
+                       nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
+                                                        NULL);
+                       if (!NT_STATUS_IS_OK(nt_status))
+                               return False;
+               } else {
+                       pwd_get_cleartext(&cli->pwd, password);
+                       nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
+                                                        password);
+                       if (!NT_STATUS_IS_OK(nt_status))
+                               return False;
+               }
 
                if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
                        cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;