Merge from HEAD:
authorAndrew Bartlett <abartlet@samba.org>
Tue, 18 Mar 2003 12:01:47 +0000 (12:01 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 18 Mar 2003 12:01:47 +0000 (12:01 +0000)
A much better SMB signing module, that allows for mulitple signing algorithms
and correctly backs down from signing when the server cannot sign the reply.

This also attempts to enable SMB signing on NTLMSSP connections, but I don't
know what NTLMSSP flags to set yet.

This would allow 'client use signing' to be set by default, for server
compatability.  (A seperate option value should be provided for mandetory
signing, which would not back down).

Andrew Bartlett

source/include/client.h
source/include/ntlmssp.h
source/libsmb/cliconnect.c
source/libsmb/clientgen.c
source/libsmb/smbencrypt.c

index 28d6a8c3302853a1ea38857faa3904c639a3c02e..0ea793de689c4caec3e2af2bf8e2be0d9e22afb5 100644 (file)
@@ -58,14 +58,15 @@ struct print_job_info
 };
 
 typedef struct smb_sign_info {
-       BOOL use_smb_signing;
+       void (*sign_outgoing_message)(struct cli_state *cli);
+       BOOL (*check_incoming_message)(struct cli_state *cli);
+       void (*free_signing_context)(struct cli_state *cli);
+       void *signing_context;
+
        BOOL negotiated_smb_signing;
-       BOOL temp_smb_signing;
-       size_t mac_key_len;
-       uint8 mac_key[64];
-       uint32 send_seq_num;
-       uint32 reply_seq_num;
        BOOL allow_smb_signing;
+       BOOL doing_signing;
+       BOOL mandetory_signing;
 } smb_sign_info;
 
 struct cli_state {
index 2fcefaaef35063e0766dac6c22b17612f1551bb0..f0278ffece899adc653a2ee3a635f1bee3a08656 100644 (file)
@@ -110,6 +110,24 @@ typedef struct ntlmssp_client_state
        DATA_BLOB session_key;
        
        uint32 neg_flags;
+       
+       /* SMB Signing */
+       
+       uint32 ntlmssp_seq_num;
+
+       /* ntlmv2 */
+       char cli_sign_const[16];
+       char cli_seal_const[16];
+       char srv_sign_const[16];
+       char srv_seal_const[16];
+
+       unsigned char cli_sign_hash[258];
+       unsigned char cli_seal_hash[258];
+       unsigned char srv_sign_hash[258];
+       unsigned char srv_seal_hash[258];
+
+       /* ntlmv1 */
+       unsigned char ntlmssp_hash[258];
 
 } NTLMSSP_CLIENT_STATE;
 
index 54a282e805794987c0e3af2ce0c4e0b6d7614940..763878f9b38307d81b66e91f8334c8585d83edf8 100644 (file)
@@ -228,39 +228,11 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
        return True;
 }
 
-static void set_signing_on_cli (struct cli_state *cli, uint8 user_session_key[16], DATA_BLOB response) 
-{
-       uint8 zero_sig[8];
-       ZERO_STRUCT(zero_sig);
-
-       DEBUG(5, ("Server returned security sig:\n"));
-       dump_data(5, &cli->inbuf[smb_ss_field], 8);
-
-       if (cli->sign_info.use_smb_signing) {
-               DEBUG(5, ("smb signing already active on connection\n"));
-       } else if (memcmp(&cli->inbuf[smb_ss_field], zero_sig, 8) != 0) {
-
-               DEBUG(3, ("smb signing enabled!\n"));
-               cli->sign_info.use_smb_signing = True;
-               cli_calculate_mac_key(cli, user_session_key, response);
-       } else {
-               DEBUG(5, ("smb signing NOT enabled!\n"));
-       }
-}
-
 static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key) 
 {
        memcpy(cli->user_session_key, session_key.data, MIN(session_key.length, sizeof(cli->user_session_key)));
 }
 
-
-static void set_temp_signing_on_cli(struct cli_state *cli) 
-{
-       if (cli->sign_info.negotiated_smb_signing)
-               cli->sign_info.temp_smb_signing = True;
-}
-
-
 /****************************************************************************
    do a NT1 NTLM/LM encrypted session setup
    @param cli client state to create do session setup on
@@ -310,8 +282,7 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
                        session_key = data_blob(NULL, 16);
                        SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
                }
-
-               set_temp_signing_on_cli(cli);
+               cli_simple_set_signing(cli, session_key.data, nt_response); 
        } else {
                /* pre-encrypted password supplied.  Only used for 
                   security=server, can't do
@@ -374,26 +345,24 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
        if (session_key.data) {
                /* Have plaintext orginal */
                set_cli_session_key(cli, session_key);
-               set_signing_on_cli(cli, session_key.data, nt_response);
        }
 
+       ret = True;
 end:   
        data_blob_free(&lm_response);
        data_blob_free(&nt_response);
        data_blob_free(&session_key);
-       return True;
+       return ret;
 }
 
 /****************************************************************************
- Send a extended security session setup blob, returning a reply blob.
+ Send a extended security session setup blob
 ****************************************************************************/
 
-static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
+static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
 {
        uint32 capabilities = cli_session_setup_capabilities(cli);
        char *p;
-       DATA_BLOB blob2 = data_blob(NULL, 0);
-       uint32 len;
 
        capabilities |= CAP_EXTENDED_SECURITY;
 
@@ -403,8 +372,6 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
        set_message(cli->outbuf,12,0,True);
        SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
 
-       set_temp_signing_on_cli(cli);
-
        cli_setup_packet(cli);
                        
        SCVAL(cli->outbuf,smb_vwv0,0xFF);
@@ -420,7 +387,18 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
        p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
        p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
        cli_setup_bcc(cli, p);
-       cli_send_smb(cli);
+       return cli_send_smb(cli);
+}
+
+/****************************************************************************
+ Send a extended security session setup blob, returning a reply blob.
+****************************************************************************/
+
+static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
+{
+       DATA_BLOB blob2 = data_blob(NULL, 0);
+       char *p;
+       size_t len;
 
        if (!cli_receive_smb(cli))
                return blob2;
@@ -449,6 +427,20 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
        return blob2;
 }
 
+/****************************************************************************
+ Send a extended security session setup blob, returning a reply blob.
+****************************************************************************/
+
+static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
+{
+       DATA_BLOB blob2 = data_blob(NULL, 0);
+       if (!cli_session_setup_blob_send(cli, blob)) {
+               return blob2;
+       }
+               
+       return cli_session_setup_blob_receive(cli);
+}
+
 #ifdef HAVE_KRB5
 /****************************************************************************
  Use in-memory credentials cache
@@ -502,6 +494,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
        DATA_BLOB blob_in = data_blob(NULL, 0);
        DATA_BLOB blob_out;
 
+       cli_temp_set_signing(cli);
+
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
                return False;
        }
@@ -532,8 +526,15 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
                        }
                
                        /* now send that blob on its way */
-                       blob = cli_session_setup_blob(cli, msg1);
+                       if (!cli_session_setup_blob_send(cli, msg1)) {
+                               return False;
+                       }
                        data_blob_free(&msg1);
+                       
+                       cli_ntlmssp_set_signing(cli, ntlmssp_state);
+                       
+                       blob = cli_session_setup_blob_receive(cli);
+
                        nt_status = cli_nt_error(cli);
                }
                
@@ -570,6 +571,9 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
                set_cli_session_key(cli, ntlmssp_state->session_key);
        }
 
+       /* we have a reference conter on ntlmssp_state, if we are signing
+          then the state will be kept by the signing engine */
+
        if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) {
                return False;
        }
@@ -883,11 +887,6 @@ BOOL cli_negprot(struct cli_state *cli)
        int numprots;
        int plength;
 
-       if (cli->sign_info.use_smb_signing) {
-               DEBUG(0, ("Cannot send negprot again, particularly after setting up SMB Signing\n"));
-               return False;
-       }
-
        if (cli->protocol < PROTOCOL_NT1)
                cli->use_spnego = False;
 
@@ -1013,11 +1012,6 @@ BOOL cli_session_request(struct cli_state *cli,
        if (cli->port == 445)
                return True;
 
-       if (cli->sign_info.use_smb_signing) {
-               DEBUG(0, ("Cannot send session resquest again, particularly after setting up SMB Signing\n"));
-               return False;
-       }
-
        /* send a session request (RFC 1002) */
        /* setup the packet length
          * Remove four bytes from the length count, since the length
index 9598f4ac9642da4c55b72b72e8bd64f12e7e72b1..3cae643c382985b6a842b4cbc1be1d2d72623b95 100644 (file)
@@ -177,9 +177,6 @@ void cli_setup_packet(struct cli_state *cli)
                        flags2 |= FLAGS2_32_BIT_ERROR_CODES;
                if (cli->use_spnego)
                        flags2 |= FLAGS2_EXTENDED_SECURITY;
-               if (cli->sign_info.use_smb_signing 
-                   || cli->sign_info.temp_smb_signing)
-                       flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
                SSVAL(cli->outbuf,smb_flg2, flags2);
        }
 }
@@ -200,8 +197,8 @@ void cli_setup_bcc(struct cli_state *cli, void *p)
 void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
 {
         /* copy_nt_creds(&cli->usr, usr); */
-       safe_strcpy(cli->domain   , usr->domain   , sizeof(usr->domain   )-1);
-       safe_strcpy(cli->user_name, usr->user_name, sizeof(usr->user_name)-1);
+       fstrcpy(cli->domain   , usr->domain);
+       fstrcpy(cli->user_name, usr->user_name);
        memcpy(&cli->pwd, &usr->pwd, sizeof(usr->pwd));
         cli->ntlmssp_flags = usr->ntlmssp_flags;
         cli->ntlmssp_cli_flgs = usr != NULL ? usr->ntlmssp_flags : 0;
@@ -262,6 +259,9 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        if (getenv("CLI_FORCE_DOSERR"))
                cli->force_dos_errors = True;
 
+       /* initialise signing */
+       cli_null_set_signing(cli);
+
        if (lp_client_signing()) 
                cli->sign_info.allow_smb_signing = True;
                                    
@@ -303,6 +303,7 @@ void cli_close_connection(struct cli_state *cli)
        SAFE_FREE(cli->outbuf);
        SAFE_FREE(cli->inbuf);
 
+       cli_free_signing_context(cli);
        data_blob_free(&cli->secblob);
 
        if (cli->mem_ctx) {
@@ -314,6 +315,7 @@ void cli_close_connection(struct cli_state *cli)
                close(cli->fd);
        cli->fd = -1;
        cli->smb_rw_error = 0;
+
 }
 
 /****************************************************************************
index aa9391325fa5fc8b75b7b0f5890e50489102e134..28160d96094d14b245ba53a6840941893c7de4ff 100644 (file)
@@ -295,7 +295,7 @@ void SMBsesskeygen_ntv1(const uchar kr[16],
 #endif
 }
 
-DATA_BLOB NTLMv2_generate_response(uchar ntlm_v2_hash[16],
+static DATA_BLOB NTLMv2_generate_response(uchar ntlm_v2_hash[16],
                                   DATA_BLOB server_chal, size_t client_chal_length)
 {
        uchar ntlmv2_response[16];
@@ -416,101 +416,3 @@ BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
        
        return True;
 }
-
-/***********************************************************
- SMB signing - setup the MAC key.
-************************************************************/
-
-void cli_calculate_mac_key(struct cli_state *cli, const uchar user_session_key[16], const DATA_BLOB response)
-{
-       
-       memcpy(&cli->sign_info.mac_key[0], user_session_key, 16);
-       memcpy(&cli->sign_info.mac_key[16],response.data, MIN(response.length, 40 - 16));
-       cli->sign_info.mac_key_len = MIN(response.length + 16, 40);
-       cli->sign_info.use_smb_signing = True;
-
-       /* These calls are INCONPATIBLE with SMB signing */
-       cli->readbraw_supported = False;
-       cli->writebraw_supported = False;
-
-       /* Reset the sequence number in case we had a previous (aborted) attempt */
-       cli->sign_info.send_seq_num = 2;
-}
-
-/***********************************************************
- SMB signing - calculate a MAC to send.
-************************************************************/
-
-void cli_caclulate_sign_mac(struct cli_state *cli)
-{
-       unsigned char calc_md5_mac[16];
-       struct MD5Context md5_ctx;
-
-       if (cli->sign_info.temp_smb_signing) {
-               memcpy(&cli->outbuf[smb_ss_field], "SignRequest", 8);
-               cli->sign_info.temp_smb_signing = False;
-               return;
-       }
-
-       if (!cli->sign_info.use_smb_signing) {
-               return;
-       }
-
-       /*
-        * Firstly put the sequence number into the first 4 bytes.
-        * and zero out the next 4 bytes.
-        */
-       SIVAL(cli->outbuf, smb_ss_field, cli->sign_info.send_seq_num);
-       SIVAL(cli->outbuf, smb_ss_field + 4, 0);
-
-       /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
-       MD5Init(&md5_ctx);
-       MD5Update(&md5_ctx, cli->sign_info.mac_key, cli->sign_info.mac_key_len);
-       MD5Update(&md5_ctx, cli->outbuf + 4, smb_len(cli->outbuf));
-       MD5Final(calc_md5_mac, &md5_ctx);
-
-       memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
-
-/*     cli->outbuf[smb_ss_field+2]=0; 
-       Uncomment this to test if the remote server actually verifies signitures...*/
-       cli->sign_info.send_seq_num++;
-       cli->sign_info.reply_seq_num = cli->sign_info.send_seq_num;
-       cli->sign_info.send_seq_num++;
-}
-
-/***********************************************************
- SMB signing - check a MAC sent by server.
-************************************************************/
-
-BOOL cli_check_sign_mac(struct cli_state *cli)
-{
-       unsigned char calc_md5_mac[16];
-       unsigned char server_sent_mac[8];
-       struct MD5Context md5_ctx;
-
-       if (cli->sign_info.temp_smb_signing) {
-               return True;
-       }
-
-       if (!cli->sign_info.use_smb_signing) {
-               return True;
-       }
-
-       /*
-        * Firstly put the sequence number into the first 4 bytes.
-        * and zero out the next 4 bytes.
-        */
-
-       memcpy(server_sent_mac, &cli->inbuf[smb_ss_field], sizeof(server_sent_mac));
-
-       SIVAL(cli->inbuf, smb_ss_field, cli->sign_info.reply_seq_num);
-       SIVAL(cli->inbuf, smb_ss_field + 4, 0);
-
-       /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
-       MD5Init(&md5_ctx);
-       MD5Update(&md5_ctx, cli->sign_info.mac_key, cli->sign_info.mac_key_len);
-       MD5Update(&md5_ctx, cli->inbuf + 4, smb_len(cli->inbuf));
-       MD5Final(calc_md5_mac, &md5_ctx);
-
-       return (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
-}