Refactor signing code to remove most dependencies on 'struct cli'.
authorJeremy Allison <jra@samba.org>
Wed, 16 Jul 2003 22:57:56 +0000 (22:57 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 16 Jul 2003 22:57:56 +0000 (22:57 +0000)
Ensure a server can't do a downgrade attack if client signing is mandatory.
Add a lp_server_signing() function and a 'server signing' parameter that
will act as the client one does.
Jeremy
(This used to be commit 203e4bf0bfb66fd9239e9a0656438a71280113cb)

source3/include/client.h
source3/include/smb.h
source3/libsmb/cliconnect.c
source3/libsmb/smb_signing.c
source3/param/loadparm.c

index fad2c099b9677e68de61e885f529837d4cd3863e..598e6c0bda521ef72251cddabc20238c377e4a52 100644 (file)
@@ -57,18 +57,6 @@ struct print_job_info
        time_t t;
 };
 
-typedef struct smb_sign_info {
-       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 allow_smb_signing;
-       BOOL doing_signing;
-       BOOL mandatory_signing;
-} smb_sign_info;
-
 struct cli_state {
        int port;
        int fd;
index d2714e78bc87ca6782201dcf8d3e397fbf75cba1..85ee5cdfc69d4ee0294a1466dcca8bcc441f3002 100644 (file)
@@ -1630,4 +1630,18 @@ struct ip_service {
        unsigned port;
 };
 
+/* Used by the SMB signing functions. */
+
+typedef struct smb_sign_info {
+       void (*sign_outgoing_message)(char *outbuf, struct smb_sign_info *si);
+       BOOL (*check_incoming_message)(char *inbuf, struct smb_sign_info *si);
+       void (*free_signing_context)(struct smb_sign_info *si);
+       void *signing_context;
+
+       BOOL negotiated_smb_signing;
+       BOOL allow_smb_signing;
+       BOOL doing_signing;
+       BOOL mandatory_signing;
+} smb_sign_info;
+
 #endif /* _SMB_H */
index 0dcc9e28459f22ec8f8250b2b8ff24a124a70135..49430616b324366212fe03580495e4de2b61960f 100644 (file)
@@ -989,6 +989,11 @@ BOOL cli_negprot(struct cli_state *cli)
 
        cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;  
 
+       if ((cli->protocol < PROTOCOL_NT1) && (lp_client_signing() == Required)) {
+               DEBUG(1,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
+               return False;
+       }
+
        if (cli->protocol >= PROTOCOL_NT1) {    
                /* NT protocol */
                cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
index e18d1ed42aaa7febe6a8f4735e6ecd9619ab5b46..683a3823698033f316f1a562022928e493772313 100644 (file)
@@ -81,7 +81,7 @@ static BOOL cli_set_smb_signing_common(struct cli_state *cli)
        }
        
        if (cli->sign_info.free_signing_context)
-               cli->sign_info.free_signing_context(cli);
+               cli->sign_info.free_signing_context(&cli->sign_info);
 
        /* These calls are INCOMPATIBLE with SMB signing */
        cli->readbraw_supported = False;
@@ -94,11 +94,11 @@ static BOOL cli_set_smb_signing_common(struct cli_state *cli)
  SMB signing - Common code for 'real' implementations
 ************************************************************/
 
-static BOOL cli_set_smb_signing_real_common(struct cli_state *cli) 
+static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
 {
-       if (cli->sign_info.mandatory_signing) {
+       if (si->mandatory_signing) {
                DEBUG(5, ("Mandatory SMB signing enabled!\n"));
-               cli->sign_info.doing_signing = True;
+               si->doing_signing = True;
        }
 
        DEBUG(5, ("SMB signing enabled!\n"));
@@ -114,22 +114,85 @@ static void mark_packet_signed(char *outbuf)
        SSVAL(outbuf,smb_flg2, flags2);
 }
 
-static BOOL cli_signing_good(struct cli_state *cli, BOOL good) 
+/***********************************************************
+ SMB signing - NULL implementation - calculate a MAC to send.
+************************************************************/
+
+static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
+{
+       /* we can't zero out the sig, as we might be trying to send a
+          session request - which is NBT-level, not SMB level and doesn't
+          have the field */
+       return;
+}
+
+/***********************************************************
+ SMB signing - NULL implementation - check a MAC sent by server.
+************************************************************/
+
+static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si)
+{
+       return True;
+}
+
+/***********************************************************
+ SMB signing - NULL implementation - free signing context
+************************************************************/
+
+static void null_free_signing_context(struct smb_sign_info *si)
+{
+       return;
+}
+
+/**
+ SMB signing - NULL implementation - setup the MAC key.
+
+ @note Used as an initialisation only - it will not correctly
+       shut down a real signing mechanism
+*/
+
+static BOOL null_set_signing(struct smb_sign_info *si)
+{
+       si->signing_context = NULL;
+       
+       si->sign_outgoing_message = null_sign_outgoing_message;
+       si->check_incoming_message = null_check_incoming_message;
+       si->free_signing_context = null_free_signing_context;
+
+       return True;
+}
+
+/**
+ * Free the signing context
+ */
+static void free_signing_context(struct smb_sign_info *si)
+{
+       if (si->free_signing_context) {
+               si->free_signing_context(si);
+               si->signing_context = NULL;
+       }
+
+       null_set_signing(si);
+}
+
+
+static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good) 
 {
        DEBUG(10, ("got SMB signature of\n"));
-       dump_data(10,&cli->inbuf[smb_ss_field] , 8);
+       dump_data(10,&inbuf[smb_ss_field] , 8);
 
-       if (good && !cli->sign_info.doing_signing) {
-               cli->sign_info.doing_signing = True;
+       if (good && !si->doing_signing) {
+               si->doing_signing = True;
        }
 
        if (!good) {
-               if (cli->sign_info.doing_signing) {
+               if (si->doing_signing) {
                        DEBUG(1, ("SMB signature check failed!\n"));
                        return False;
                } else {
                        DEBUG(3, ("Server did not sign reply correctly\n"));
-                       cli_free_signing_context(cli);
+                       free_signing_context(si);
                        return False;
                }
        }
@@ -188,28 +251,27 @@ static void simple_packet_signature(struct smb_basic_signing_context *data,
  SMB signing - Simple implementation - send the MAC.
 ************************************************************/
 
-static void cli_simple_sign_outgoing_message(struct cli_state *cli)
+static void cli_simple_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
 {
        unsigned char calc_md5_mac[16];
-       struct smb_basic_signing_context *data = cli->sign_info.signing_context;
+       struct smb_basic_signing_context *data = si->signing_context;
 
        /* mark the packet as signed - BEFORE we sign it...*/
-       mark_packet_signed(cli->outbuf);
+       mark_packet_signed(outbuf);
 
-       simple_packet_signature(data, cli->outbuf, data->send_seq_num, 
-                               calc_md5_mac);
+       simple_packet_signature(data, outbuf, data->send_seq_num, calc_md5_mac);
 
        DEBUG(10, ("sent SMB signature of\n"));
        dump_data(10, calc_md5_mac, 8);
 
-       memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
+       memcpy(&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 signatures...*/
 
        data->send_seq_num++;
        store_sequence_for_reply(&data->outstanding_packet_list, 
-                                cli->mid, 
+                                SVAL(outbuf,smb_mid),
                                 data->send_seq_num);
        data->send_seq_num++;
 }
@@ -218,24 +280,24 @@ static void cli_simple_sign_outgoing_message(struct cli_state *cli)
  SMB signing - Simple implementation - check a MAC sent by server.
 ************************************************************/
 
-static BOOL cli_simple_check_incoming_message(struct cli_state *cli)
+static BOOL cli_simple_check_incoming_message(char *inbuf, struct smb_sign_info *si)
 {
        BOOL good;
        uint32 reply_seq_number;
        unsigned char calc_md5_mac[16];
        unsigned char *server_sent_mac;
 
-       struct smb_basic_signing_context *data = cli->sign_info.signing_context;
+       struct smb_basic_signing_context *data = si->signing_context;
 
        if (!get_sequence_for_reply(&data->outstanding_packet_list, 
-                                   SVAL(cli->inbuf, smb_mid), 
+                                   SVAL(inbuf, smb_mid), 
                                    &reply_seq_number)) {
                return False;
        }
 
-       simple_packet_signature(data, cli->inbuf, reply_seq_number, calc_md5_mac);
+       simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac);
 
-       server_sent_mac = &cli->inbuf[smb_ss_field];
+       server_sent_mac = &inbuf[smb_ss_field];
        good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
        
        if (!good) {
@@ -245,16 +307,16 @@ static BOOL cli_simple_check_incoming_message(struct cli_state *cli)
                DEBUG(5, ("BAD SIG: got SMB signature of\n"));
                dump_data(5, server_sent_mac, 8);
        }
-       return cli_signing_good(cli, good);
+       return signing_good(inbuf, si, good);
 }
 
 /***********************************************************
  SMB signing - Simple implementation - free signing context
 ************************************************************/
 
-static void cli_simple_free_signing_context(struct cli_state *cli)
+static void cli_simple_free_signing_context(struct smb_sign_info *si)
 {
-       struct smb_basic_signing_context *data = cli->sign_info.signing_context;
+       struct smb_basic_signing_context *data = si->signing_context;
        struct outstanding_packet_lookup *list = data->outstanding_packet_list;
        
        while (list) {
@@ -264,7 +326,7 @@ static void cli_simple_free_signing_context(struct cli_state *cli)
        }
 
        data_blob_free(&data->mac_key);
-       SAFE_FREE(cli->sign_info.signing_context);
+       SAFE_FREE(si->signing_context);
 
        return;
 }
@@ -284,7 +346,7 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
                return False;
        }
 
-       if (!cli_set_smb_signing_real_common(cli)) {
+       if (!set_smb_signing_real_common(&cli->sign_info)) {
                return False;
        }
 
@@ -310,66 +372,18 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
        return True;
 }
 
-/***********************************************************
- SMB signing - NULL implementation - calculate a MAC to send.
-************************************************************/
-
-static void cli_null_sign_outgoing_message(struct cli_state *cli)
-{
-       /* we can't zero out the sig, as we might be trying to send a
-          session request - which is NBT-level, not SMB level and doesn't
-          have the field */
-       return;
-}
-
-/***********************************************************
- SMB signing - NULL implementation - check a MAC sent by server.
-************************************************************/
-
-static BOOL cli_null_check_incoming_message(struct cli_state *cli)
-{
-       return True;
-}
-
-/***********************************************************
- SMB signing - NULL implementation - free signing context
-************************************************************/
-
-static void cli_null_free_signing_context(struct cli_state *cli)
-{
-       return;
-}
-
-/**
- SMB signing - NULL implementation - setup the MAC key.
-
- @note Used as an initialisation only - it will not correctly
-       shut down a real signing mechanism
-*/
-
-BOOL cli_null_set_signing(struct cli_state *cli)
-{
-       cli->sign_info.signing_context = NULL;
-       
-       cli->sign_info.sign_outgoing_message = cli_null_sign_outgoing_message;
-       cli->sign_info.check_incoming_message = cli_null_check_incoming_message;
-       cli->sign_info.free_signing_context = cli_null_free_signing_context;
-
-       return True;
-}
-
 /***********************************************************
  SMB signing - TEMP implementation - calculate a MAC to send.
 ************************************************************/
 
-static void cli_temp_sign_outgoing_message(struct cli_state *cli)
+static void cli_temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
 {
        /* mark the packet as signed - BEFORE we sign it...*/
-       mark_packet_signed(cli->outbuf);
+       mark_packet_signed(outbuf);
 
        /* I wonder what BSRSPYL stands for - but this is what MS 
           actually sends! */
-       memcpy(&cli->outbuf[smb_ss_field], "BSRSPYL ", 8);
+       memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
        return;
 }
 
@@ -377,7 +391,7 @@ static void cli_temp_sign_outgoing_message(struct cli_state *cli)
  SMB signing - TEMP implementation - check a MAC sent by server.
 ************************************************************/
 
-static BOOL cli_temp_check_incoming_message(struct cli_state *cli)
+static BOOL cli_temp_check_incoming_message(char *inbuf, struct smb_sign_info *si)
 {
        return True;
 }
@@ -386,7 +400,7 @@ static BOOL cli_temp_check_incoming_message(struct cli_state *cli)
  SMB signing - TEMP implementation - free signing context
 ************************************************************/
 
-static void cli_temp_free_signing_context(struct cli_state *cli)
+static void cli_temp_free_signing_context(struct smb_sign_info *si)
 {
        return;
 }
@@ -395,6 +409,15 @@ static void cli_temp_free_signing_context(struct cli_state *cli)
  SMB signing - NULL implementation - setup the MAC key.
 ************************************************************/
 
+BOOL cli_null_set_signing(struct cli_state *cli)
+{
+       return null_set_signing(&cli->sign_info);
+}
+
+/***********************************************************
+ SMB signing - temp implementation - setup the MAC key.
+************************************************************/
+
 BOOL cli_temp_set_signing(struct cli_state *cli)
 {
        if (!cli_set_smb_signing_common(cli)) {
@@ -410,16 +433,9 @@ BOOL cli_temp_set_signing(struct cli_state *cli)
        return True;
 }
 
-/**
- * Free the signing context
- */
-void cli_free_signing_context(struct cli_state *cli) 
+void cli_free_signing_context(struct cli_state *cli)
 {
-       if (cli->sign_info.free_signing_context) 
-               cli->sign_info.free_signing_context(cli);
-
-       cli_null_set_signing(cli);
+       free_signing_context(&cli->sign_info);
 }
 
 /**
@@ -428,7 +444,7 @@ void cli_free_signing_context(struct cli_state *cli)
  
 void cli_calculate_sign_mac(struct cli_state *cli)
 {
-       cli->sign_info.sign_outgoing_message(cli);
+       cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
 }
 
 /**
@@ -445,14 +461,14 @@ BOOL cli_check_sign_mac(struct cli_state *cli)
                DEBUG(cli->sign_info.doing_signing ? 1 : 10, ("Can't check signature on short packet! smb_len = %u\n", smb_len(cli->inbuf)));
                good = False;
        } else {
-               good = cli->sign_info.check_incoming_message(cli);
+               good = cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info);
        }
 
        if (!good) {
                if (cli->sign_info.doing_signing) {
                        return False;
                } else {
-                       cli_free_signing_context(cli);  
+                       free_signing_context(&cli->sign_info);  
                }
        }
 
@@ -479,3 +495,8 @@ BOOL srv_check_sign_mac(char *buf)
 void srv_calculate_sign_mac(char *buf)
 {
 }
+
+BOOL allow_sendfile(void)
+{
+       return True;
+}
index dd429fa6889421c19dc3290f58bed8fea3e15f99..373940781054721bfcd9e848e4dc76212f40f77c 100644 (file)
@@ -292,6 +292,7 @@ typedef struct
        int restrict_anonymous;
        int name_cache_timeout;
        int client_signing;
+       int server_signing;
        param_opt_struct *param_opt;
 }
 global;
@@ -693,15 +694,17 @@ static const struct enum_list enum_smb_signing_vals[] = {
        {False, "False"},
        {False, "0"},
        {False, "Off"},
+       {False, "disabled"},
        {True, "Yes"},
        {True, "True"},
        {True, "1"},
        {True, "On"},
-       {Required, "Required"},
-       {Required, "Mandatory"},
-       {Required, "Force"},
-       {Required, "Forced"},
-       {Required, "Enforced"},
+       {True, "enabled"},
+       {Required, "required"},
+       {Required, "mandatory"},
+       {Required, "force"},
+       {Required, "forced"},
+       {Required, "enforced"},
        {-1, NULL}
 };
 
@@ -894,6 +897,7 @@ static struct parm_struct parm_table[] = {
        {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
        {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_DEVELOPER},
 
        {"Tuning Options", P_SEP, P_SEPARATOR},
@@ -1885,7 +1889,8 @@ FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
 FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
-FN_GLOBAL_BOOL(lp_client_signing, &Globals.client_signing)
+FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
+FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
 
 /* local prototypes */