Fix up some of the SMB signing code:
authorAndrew Bartlett <abartlet@samba.org>
Sun, 16 Jun 2002 04:21:56 +0000 (04:21 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Sun, 16 Jun 2002 04:21:56 +0000 (04:21 +0000)
The problem was that *all* packets were being signed, even packets before
signing was set up.  (This broke the session request).

This fixes it to be an 'opt in' measure - that is, we only attempt to sign
things after we have got a valid, non-guest session setup as per the CIFS spec.

I've not tested this against an MS server, becouse my VMware is down, but
at least it doesn't break the build farm any more.

Andrew Bartlett

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

index e2eda54948ff967748aef1f7264651102f95f817..69c74200c103a40d3afa8d63d77fdd546e9a790b 100644 (file)
@@ -59,6 +59,7 @@ struct print_job_info
 
 typedef struct smb_sign_info {
        BOOL use_smb_signing;
+       BOOL negotiated_smb_signing;
        size_t mac_key_len;
        uint8 mac_key[44];
        uint32 send_seq_num;
index 33e2b286095a85b7d8fc85abf9751da08b2717b9..135238b9a7f1f6775c1a7a160c9652576f6579cb 100644 (file)
@@ -144,9 +144,6 @@ static BOOL cli_session_setup_guest(struct cli_state *cli)
        char *p;
        uint32 capabilities = cli_session_setup_capabilities(cli);
 
-       /* Guest cannot use SMB signing. */
-       cli->sign_info.use_smb_signing = False;
-
        set_message(cli->outbuf,13,0,True);
        SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
        cli_setup_packet(cli);
@@ -202,9 +199,6 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
 
        passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE|STR_ASCII);
 
-       /* Plaintext password cannot use SMB signing. */
-       cli->sign_info.use_smb_signing = False;
-
        set_message(cli->outbuf,13,0,True);
        SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
        cli_setup_packet(cli);
@@ -275,12 +269,15 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
                ntpasslen = 24;
                SMBencrypt((uchar *)pass,cli->secblob.data,(uchar *)pword);
                SMBNTencrypt((uchar *)pass,cli->secblob.data,(uchar *)ntpword);
-               cli_calculate_mac_key(cli, (uchar *)pass, (uchar *)ntpword);
        } else {
                memcpy(pword, pass, passlen);
                memcpy(ntpword, ntpass, ntpasslen);
        }
 
+       if (cli->sign_info.negotiated_smb_signing) {
+               cli_calculate_mac_key(cli, (uchar *)pass, (uchar *)ntpword);
+       }
+
        /* send a session setup command */
        memset(cli->outbuf,'\0',smb_size);
 
@@ -311,10 +308,15 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
 
        show_msg(cli->inbuf);
 
+       if (cli_is_error(cli) || SVAL(cli->inbuf,smb_vwv2) /* guest */) {
+               /* We only use it if we have a successful non-guest connect */
+               cli->sign_info.use_smb_signing = False;
+       }
+
        if (cli_is_error(cli)) {
                return False;
        }
-       
+
        /* use the returned vuid from now on */
        cli->vuid = SVAL(cli->inbuf,smb_uid);
        
@@ -346,9 +348,6 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
        /* send a session setup command */
        memset(cli->outbuf,'\0',smb_size);
 
-       /* Extended security cannot use SMB signing (for now). */
-       cli->sign_info.use_smb_signing = False;
-
        set_message(cli->outbuf,12,0,True);
        SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
        cli_setup_packet(cli);
@@ -813,6 +812,11 @@ 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;
        }
@@ -879,10 +883,10 @@ BOOL cli_negprot(struct cli_state *cli)
 
                /* A way to attempt to force SMB signing */
                if (getenv("CLI_FORCE_SMB_SIGNING"))
-                       cli->sign_info.use_smb_signing = True;
-
-               if (cli->sign_info.use_smb_signing && !(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
-                       cli->sign_info.use_smb_signing = False;
+                       cli->sign_info.negotiated_smb_signing = True;
+                                   
+               if (cli->sign_info.negotiated_smb_signing && !(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
+                       cli->sign_info.negotiated_smb_signing = False;
 
        } else if (cli->protocol >= PROTOCOL_LANMAN1) {
                cli->use_spnego = False;
@@ -896,13 +900,11 @@ BOOL cli_negprot(struct cli_state *cli)
                cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
                cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
                cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
-               cli->sign_info.use_smb_signing = False;
        } else {
                /* the old core protocol */
                cli->use_spnego = False;
                cli->sec_mode = 0;
                cli->serverzone = TimeDiff(time(NULL));
-               cli->sign_info.use_smb_signing = False;
        }
 
        cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
@@ -929,6 +931,11 @@ BOOL cli_session_request(struct cli_state *cli,
        /* 445 doesn't have session request */
        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) */
        memcpy(&(cli->calling), calling, sizeof(*calling));
        memcpy(&(cli->called ), called , sizeof(*called ));
index e7e88687b856eb3f22f4490e716806b701f006c7..c9500ead5d23c1a87de7443d60716acbc0872ac8 100644 (file)
@@ -120,8 +120,7 @@ BOOL cli_send_smb(struct cli_state *cli)
        if (cli->fd == -1)
                return False;
 
-       if (SVAL(cli->outbuf,smb_flg2) & FLAGS2_SMB_SECURITY_SIGNATURES)
-               cli_caclulate_sign_mac(cli);
+       cli_caclulate_sign_mac(cli);
 
        len = smb_len(cli->outbuf) + 4;
 
index 6fce1c039b5e8961059e9a522229156de23c794c..756a6cce2f9ef9bf10cdad11670ed470b69fccef 100644 (file)
@@ -128,6 +128,11 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
 }
 
 #if 0  /* relies on client_recieve_smb(), now a static in libsmb/clientgen.c */
+
+/* This call is INCOMPATIBLE with SMB signing.  If you remove the #if 0
+   you must fix ensure you don't attempt to sign the packets - data
+   *will* be currupted */
+
 /****************************************************************************
 Issue a single SMBreadraw and don't wait for a reply.
 ****************************************************************************/
@@ -135,6 +140,12 @@ Issue a single SMBreadraw and don't wait for a reply.
 static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset, 
                           size_t size, int i)
 {
+
+       if (!cli->sign_info.use_smb_signing) {
+               DEBUG(0, ("Cannot use readraw and SMB Signing\n"));
+               return False;
+       }
+       
        memset(cli->outbuf,'\0',smb_size);
        memset(cli->inbuf,'\0',smb_size);
 
index 29e168f7bf4aeb94f604126eb0055e6762d5a57b..9ae6da0ced90947062911a6782ea6148a2f4623d 100644 (file)
@@ -343,6 +343,8 @@ void cli_calculate_mac_key(struct cli_state *cli, const unsigned char *ntpasswd,
        E_md4hash(ntpasswd,&cli->sign_info.mac_key[0]);
        memcpy(&cli->sign_info.mac_key[16],resp,24);
        cli->sign_info.mac_key_len = 40;
+       cli->sign_info.use_smb_signing = True;
+
 }
 
 /***********************************************************
@@ -354,6 +356,14 @@ void cli_caclulate_sign_mac(struct cli_state *cli)
        unsigned char calc_md5_mac[16];
        struct MD5Context md5_ctx;
 
+       if (!cli->sign_info.use_smb_signing) {
+               return;
+       }
+
+       /* These calls are INCONPATIBLE with SMB signing */
+       cli->readbraw_supported = False;
+       cli->writebraw_supported = False;      
+
        /*
         * Firstly put the sequence number into the first 4 bytes.
         * and zero out the next 4 bytes.