s3:libsmb: make use of new advanded SMB signing
authorStefan Metzmacher <metze@samba.org>
Mon, 12 Sep 2011 07:16:27 +0000 (09:16 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 14 Sep 2011 06:09:15 +0000 (08:09 +0200)
metze

source3/libsmb/cliconnect.c
source3/libsmb/clientgen.c
source3/libsmb/clisigning.c
source3/libsmb/proto.h

index 4ebabceaa7d533f8abc2a9b45a136fea8dbe382c..54cd669c1073664dd30b2e39473c253488916139 100644 (file)
@@ -944,7 +944,6 @@ static struct tevent_req *cli_session_setup_nt1_send(
                        SMBsesskeygen_ntv1(nt_hash, session_key.data);
 #endif
                }
-               cli_temp_set_signing(cli);
        } else {
                /* pre-encrypted password supplied.  Only used for 
                   security=server, can't do
@@ -1444,8 +1443,6 @@ static struct tevent_req *cli_session_setup_kerberos_send(
        state->cli = cli;
        state->ads_status = ADS_SUCCESS;
 
-       cli_temp_set_signing(cli);
-
        /*
         * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
         * we have to acquire a ticket. To be fixed later :-)
@@ -1590,8 +1587,6 @@ static struct tevent_req *cli_session_setup_ntlmssp_send(
        talloc_set_destructor(
                state, cli_session_setup_ntlmssp_state_destructor);
 
-       cli_temp_set_signing(cli);
-
        status = ntlmssp_client_start(state,
                                      lp_netbios_name(),
                                      lp_workgroup(),
@@ -2643,7 +2638,11 @@ static void cli_negprot_done(struct tevent_req *subreq)
 
        if (cli_state_protocol(cli) >= PROTOCOL_NT1) {
                struct timespec ts;
-               bool negotiated_smb_signing = false;
+               const char *client_signing = NULL;
+               bool server_mandatory;
+               bool server_allowed;
+               const char *server_signing = NULL;
+               bool ok;
 
                if (wct != 0x11) {
                        tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
@@ -2678,35 +2677,33 @@ static void cli_negprot_done(struct tevent_req *subreq)
                        }
                }
 
-               /*
-                * As signing is slow we only turn it on if either the client or
-                * the server require it. JRA.
-                */
+               client_signing = "disabled";
+               if (client_is_signing_allowed(cli)) {
+                       client_signing = "allowed";
+               }
+               if (client_is_signing_mandatory(cli)) {
+                       client_signing = "required";
+               }
 
+               server_signing = "not supported";
+               if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
+                       server_signing = "supported";
+                       server_allowed = true;
+               }
                if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
-                       /* Fail if server says signing is mandatory and we don't want to support it. */
-                       if (!client_is_signing_allowed(cli)) {
-                               DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
-                               tevent_req_nterror(req,
-                                                  NT_STATUS_ACCESS_DENIED);
-                               return;
-                       }
-                       negotiated_smb_signing = true;
-               } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
-                       /* Fail if client says signing is mandatory and the server doesn't support it. */
-                       if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
-                               DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
-                               tevent_req_nterror(req,
-                                                  NT_STATUS_ACCESS_DENIED);
-                               return;
-                       }
-                       negotiated_smb_signing = true;
-               } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
-                       negotiated_smb_signing = true;
+                       server_signing = "required";
+                       server_mandatory = true;
                }
 
-               if (negotiated_smb_signing) {
-                       cli_set_signing_negotiated(cli);
+               ok = cli_set_signing_negotiated(cli,
+                                               server_allowed,
+                                               server_mandatory);
+               if (!ok) {
+                       DEBUG(1,("cli_negprot: SMB signing is required, "
+                                "but client[%s] and server[%s] mismatch\n",
+                                client_signing, server_signing));
+                       tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+                       return;
                }
 
        } else if (cli_state_protocol(cli) >= PROTOCOL_LANMAN1) {
index 15e450a8029a0e54145e32f71d2c8e13e22645c4..c22cd303e514c86a7ac32042162e3fa25fc042f9 100644 (file)
@@ -168,8 +168,9 @@ struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx,
                                   int signing_state, int flags)
 {
        struct cli_state *cli = NULL;
-       bool allow_smb_signing = false;
-       bool mandatory_signing = false;
+       bool allow_smb_signing;
+       bool desire_smb_signing;
+       bool mandatory_signing;
        socklen_t ss_length;
        int ret;
 
@@ -236,31 +237,43 @@ struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx,
                cli->use_level_II_oplocks = true;
        }
 
-       if (lp_client_signing()) {
-               allow_smb_signing = true;
-       }
-
-       if (lp_client_signing() == Required) {
-               mandatory_signing = true;
-       }
-
-       if (signing_state != Undefined) {
-               allow_smb_signing = true;
+       if (signing_state == Undefined) {
+               signing_state = lp_client_signing();
        }
 
-       if (signing_state == false) {
+       switch (signing_state) {
+       case false:
+               /* never */
                allow_smb_signing = false;
+               desire_smb_signing = false;
                mandatory_signing = false;
-       }
-
-       if (signing_state == Required) {
+               break;
+       case true:
+               /* if the server supports it */
+               allow_smb_signing = true;
+               desire_smb_signing = true;
+               mandatory_signing = false;
+               break;
+       default:
+       case Undefined:
+       case Auto:
+               /* if the server requires it */
+               allow_smb_signing = true;
+               desire_smb_signing = false;
+               mandatory_signing = false;
+               break;
+       case Required:
+               /* always */
+               allow_smb_signing = true;
+               desire_smb_signing = true;
                mandatory_signing = true;
+               break;
        }
 
        /* initialise signing */
        cli->signing_state = smb_signing_init(cli,
                                              allow_smb_signing,
-                                             allow_smb_signing,
+                                             desire_smb_signing,
                                              mandatory_signing);
        if (!cli->signing_state) {
                goto error;
index 134938fc89194b88713879f3f0bc9f5fab6e0dd7..acdc24faeb09003dd43068a440fc746c07352b8d 100644 (file)
@@ -42,11 +42,6 @@ bool cli_simple_set_signing(struct cli_state *cli,
        return true;
 }
 
-bool cli_temp_set_signing(struct cli_state *cli)
-{
-       return true;
-}
-
 void cli_calculate_sign_mac(struct cli_state *cli, char *buf, uint32_t *seqnum)
 {
        *seqnum = smb_signing_next_seqnum(cli->signing_state, false);
@@ -68,9 +63,11 @@ bool cli_check_sign_mac(struct cli_state *cli, const char *buf, uint32_t seqnum)
        return true;
 }
 
-void cli_set_signing_negotiated(struct cli_state *cli)
+bool cli_set_signing_negotiated(struct cli_state *cli,
+                               bool allowed, bool mandatory)
 {
-       smb_signing_set_negotiated(cli->signing_state, true, false);
+       return smb_signing_set_negotiated(cli->signing_state,
+                                         allowed, mandatory);
 }
 
 bool client_is_signing_on(struct cli_state *cli)
index fef7ae0502811b9024ec417bf002674e0bed69c3..4992d95c96815e26150e218e694f26e1acc2aa46 100644 (file)
@@ -865,13 +865,13 @@ void cli_free_enc_buffer(struct cli_state *cli, char *buf);
 bool cli_simple_set_signing(struct cli_state *cli,
                            const DATA_BLOB user_session_key,
                            const DATA_BLOB response);
-bool cli_temp_set_signing(struct cli_state *cli);
 void cli_calculate_sign_mac(struct cli_state *cli, char *buf, uint32_t *seqnum);
 bool cli_check_sign_mac(struct cli_state *cli, const char *buf, uint32_t seqnum);
 bool client_is_signing_on(struct cli_state *cli);
 bool client_is_signing_allowed(struct cli_state *cli);
 bool client_is_signing_mandatory(struct cli_state *cli);
-void cli_set_signing_negotiated(struct cli_state *cli);
+bool cli_set_signing_negotiated(struct cli_state *cli,
+                               bool allowed, bool mandatory);
 
 /* The following definitions come from libsmb/reparse_symlink.c  */