The branch, master has been updated
       via  abb24bf s3:smbd: make use of better SMB signing negotiation
       via  c682472 s3:libsmb: make use of new advanded SMB signing
       via  0a6d0f8 s3:smb_signing: add support for easier negotiation of SMB 
signing
       via  f205e4c s3:smbd: echo FLAGS2_SMB_SECURITY_SIGNATURES* and the 
signature field in the reply
      from  cb064f2 tdb2: remove bogus leftover .orig file.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit abb24bf8e874d525382e994af7ae432212775153
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 12 09:19:06 2011 +0200

    s3:smbd: make use of better SMB signing negotiation
    
    metze
    
    Autobuild-User: Stefan Metzmacher <[email protected]>
    Autobuild-Date: Wed Sep 14 09:41:02 CEST 2011 on sn-devel-104

commit c682472fdf28894858d14eb95b13cb4214847ecd
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 12 09:16:27 2011 +0200

    s3:libsmb: make use of new advanded SMB signing
    
    metze

commit 0a6d0f8edaa198898f50f274275efba8de41d843
Author: Stefan Metzmacher <[email protected]>
Date:   Mon Sep 12 09:04:53 2011 +0200

    s3:smb_signing: add support for easier negotiation of SMB signing
    
    We don't make use of it yet, but it will follow.
    
    metze

commit f205e4cada0a2e5d1289b5a1482dd670c65b1dfd
Author: Stefan Metzmacher <[email protected]>
Date:   Fri Sep 9 22:44:44 2011 +0200

    s3:smbd: echo FLAGS2_SMB_SECURITY_SIGNATURES* and the signature field in 
the reply
    
    This matches what windows is doing.
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 source3/include/smb_signing.h |    5 ++-
 source3/libsmb/cliconnect.c   |   59 +++++++++++-------------
 source3/libsmb/clientgen.c    |   46 ++++++++++++-------
 source3/libsmb/clisigning.c   |   11 ++---
 source3/libsmb/proto.h        |    4 +-
 source3/libsmb/smb_signing.c  |  100 ++++++++++++++++++++++++++++-------------
 source3/smbd/negprot.c        |    1 -
 source3/smbd/process.c        |   12 ++++-
 source3/smbd/proto.h          |    3 +-
 source3/smbd/sesssetup.c      |   18 +++++++
 source3/smbd/signing.c        |   21 +++++++--
 11 files changed, 183 insertions(+), 97 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/smb_signing.h b/source3/include/smb_signing.h
index d2eda9b..481be1d 100644
--- a/source3/include/smb_signing.h
+++ b/source3/include/smb_signing.h
@@ -26,9 +26,11 @@ struct smb_signing_state;
 
 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
                                           bool allowed,
+                                          bool desired,
                                           bool mandatory);
 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
                                              bool allowed,
+                                             bool desired,
                                              bool mandatory,
                                              void *(*alloc_fn)(TALLOC_CTX *, 
size_t),
                                              void (*free_fn)(TALLOC_CTX *, 
void *));
@@ -45,7 +47,8 @@ bool smb_signing_activate(struct smb_signing_state *si,
 bool smb_signing_is_active(struct smb_signing_state *si);
 bool smb_signing_is_allowed(struct smb_signing_state *si);
 bool smb_signing_is_mandatory(struct smb_signing_state *si);
-bool smb_signing_set_negotiated(struct smb_signing_state *si);
+bool smb_signing_set_negotiated(struct smb_signing_state *si,
+                               bool allowed, bool mandatory);
 bool smb_signing_is_negotiated(struct smb_signing_state *si);
 
 #endif /* _SMB_SIGNING_H_ */
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 4ebabce..54cd669 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -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) {
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index db5e545..c22cd30 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -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,30 +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,
+                                             desire_smb_signing,
                                              mandatory_signing);
        if (!cli->signing_state) {
                goto error;
diff --git a/source3/libsmb/clisigning.c b/source3/libsmb/clisigning.c
index ac4db76..acdc24f 100644
--- a/source3/libsmb/clisigning.c
+++ b/source3/libsmb/clisigning.c
@@ -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 smb_signing_set_bsrspyl(cli->signing_state);
-}
-
 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);
+       return smb_signing_set_negotiated(cli->signing_state,
+                                         allowed, mandatory);
 }
 
 bool client_is_signing_on(struct cli_state *cli)
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index fef7ae0..4992d95 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -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  */
 
diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c
index c926b48..ba20723 100644
--- a/source3/libsmb/smb_signing.c
+++ b/source3/libsmb/smb_signing.c
@@ -29,15 +29,15 @@ struct smb_signing_state {
        /* is signing localy allowed */
        bool allowed;
 
+       /* is signing localy desired */
+       bool desired;
+
        /* is signing localy mandatory */
        bool mandatory;
 
        /* is signing negotiated by the peer */
        bool negotiated;
 
-       /* send BSRSPYL signatures */
-       bool bsrspyl;
-
        bool active; /* Have I ever seen a validly signed packet? */
 
        /* mac_key.length > 0 means signing is started */
@@ -54,7 +54,6 @@ struct smb_signing_state {
 static void smb_signing_reset_info(struct smb_signing_state *si)
 {
        si->active = false;
-       si->bsrspyl = false;
        si->seqnum = 0;
 
        if (si->free_fn) {
@@ -68,6 +67,7 @@ static void smb_signing_reset_info(struct smb_signing_state 
*si)
 
 struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
                                              bool allowed,
+                                             bool desired,
                                              bool mandatory,
                                              void *(*alloc_fn)(TALLOC_CTX *, 
size_t),
                                              void (*free_fn)(TALLOC_CTX *, 
void *))
@@ -92,10 +92,15 @@ struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX 
*mem_ctx,
        }
 
        if (mandatory) {
+               desired = true;
+       }
+
+       if (desired) {
                allowed = true;
        }
 
        si->allowed = allowed;
+       si->desired = desired;
        si->mandatory = mandatory;
 
        return si;
@@ -103,9 +108,11 @@ struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX 
*mem_ctx,
 
 struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx,
                                           bool allowed,
+                                          bool desired,
                                           bool mandatory)
 {
-       return smb_signing_init_ex(mem_ctx, allowed, mandatory, NULL, NULL);
+       return smb_signing_init_ex(mem_ctx, allowed, desired, mandatory,
+                                  NULL, NULL);
 }
 
 static bool smb_signing_good(struct smb_signing_state *si,
@@ -210,10 +217,11 @@ void smb_signing_sign_pdu(struct smb_signing_state *si,
                          uint8_t *outbuf, uint32_t seqnum)
 {
        uint8_t calc_md5_mac[16];
-       uint16_t flags2;
+       uint8_t com;
+       uint8_t flags;
 
        if (si->mac_key.length == 0) {
-               if (!si->bsrspyl) {
+               if (!si->negotiated) {
                        return;
                }
        }
@@ -226,15 +234,32 @@ void smb_signing_sign_pdu(struct smb_signing_state *si,
                abort();
        }
 
-       /* mark the packet as signed - BEFORE we sign it...*/
-       flags2 = SVAL(outbuf,smb_flg2);
-       flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
-       SSVAL(outbuf, smb_flg2, flags2);
+       com = SVAL(outbuf,smb_com);
+       flags = SVAL(outbuf,smb_flg);
+
+       if (!(flags & FLAG_REPLY)) {
+               uint16_t flags2 = SVAL(outbuf,smb_flg2);
+               /*
+                * If this is a request, specify what is
+                * supported or required by the client
+                */
+               if (si->negotiated && si->desired) {
+                       flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
+               }
+               if (si->negotiated && si->mandatory) {
+                       flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
+               }
+               SSVAL(outbuf, smb_flg2, flags2);
+       }
 
-       if (si->bsrspyl) {
+       if (si->mac_key.length == 0) {
                /* I wonder what BSRSPYL stands for - but this is what MS
                   actually sends! */
-               memcpy(calc_md5_mac, "BSRSPYL ", 8);
+               if (com == SMBsesssetupX) {
+                       memcpy(calc_md5_mac, "BSRSPYL ", 8);
+               } else {
+                       memset(calc_md5_mac, 0, 8);
+               }
        } else {
                smb_signing_md5(&si->mac_key, outbuf,
                                seqnum, calc_md5_mac);
@@ -305,21 +330,6 @@ bool smb_signing_check_pdu(struct smb_signing_state *si,
        return smb_signing_good(si, good, seqnum);
 }
 
-bool smb_signing_set_bsrspyl(struct smb_signing_state *si)
-{
-       if (!si->negotiated) {
-               return false;
-       }
-
-       if (si->active) {
-               return false;
-       }
-
-       si->bsrspyl = true;
-
-       return true;
-}
-
 bool smb_signing_activate(struct smb_signing_state *si,
                          const DATA_BLOB user_session_key,
                          const DATA_BLOB response)
@@ -398,14 +408,42 @@ bool smb_signing_is_mandatory(struct smb_signing_state 
*si)
        return si->mandatory;
 }
 
-bool smb_signing_set_negotiated(struct smb_signing_state *si)
+bool smb_signing_set_negotiated(struct smb_signing_state *si,
+                               bool allowed, bool mandatory)
 {
-       if (!si->allowed) {
+       if (si->active) {
+               return true;
+       }
+
+       if (!si->allowed && mandatory) {
                return false;
        }
 
-       si->negotiated = true;
+       if (si->mandatory && !allowed) {
+               return false;
+       }
+
+       if (si->mandatory) {
+               si->negotiated = true;
+               return true;
+       }
+
+       if (mandatory) {
+               si->negotiated = true;
+               return true;
+       }
+
+       if (!si->desired) {
+               si->negotiated = false;
+               return true;
+       }
+
+       if (si->desired && allowed) {
+               si->negotiated = true;
+               return true;
+       }
 
+       si->negotiated = false;
        return true;
 }
 
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 71e0291..89ef52c 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -375,7 +375,6 @@ static void reply_nt1(struct smb_request *req, uint16 
choice)
                        capabilities &= ~CAP_RAW_MODE;
                        if (lp_server_signing() == Required)
                                secword 
|=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
-                       srv_set_signing_negotiated(sconn);
                } else {
                        DEBUG(0,("reply_nt1: smb signing is incompatible with 
share level security !\n"));
                        if (lp_server_signing() == Required) {
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index c7f0ade..ab0c147 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1674,15 +1674,21 @@ void remove_from_common_flags2(uint32 v)
 static void construct_reply_common(struct smb_request *req, const char *inbuf,
                                   char *outbuf)
 {
+       uint16_t in_flags2 = SVAL(inbuf,smb_flg2);
+       uint16_t out_flags2 = common_flags2;
+
+       out_flags2 |= in_flags2 & FLAGS2_UNICODE_STRINGS;
+       out_flags2 |= in_flags2 & FLAGS2_SMB_SECURITY_SIGNATURES;
+       out_flags2 |= in_flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
+
        srv_set_message(outbuf,0,0,false);
 
        SCVAL(outbuf, smb_com, req->cmd);
        SIVAL(outbuf,smb_rcls,0);
        SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & 
FLAG_CASELESS_PATHNAMES)); 
-       SSVAL(outbuf,smb_flg2,
-               (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
-               common_flags2);
+       SSVAL(outbuf,smb_flg2, out_flags2);
        memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
+       memcpy(outbuf+smb_ss_field, inbuf+smb_ss_field, 8);
 
        SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
        SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 8edd695..3d0665d 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -54,7 +54,8 @@ void srv_calculate_sign_mac(struct smbd_server_connection 
*conn,
                            char *outbuf, uint32_t seqnum);
 void srv_cancel_sign_response(struct smbd_server_connection *conn);
 bool srv_init_signing(struct smbd_server_connection *conn);
-void srv_set_signing_negotiated(struct smbd_server_connection *conn);
+void srv_set_signing_negotiated(struct smbd_server_connection *conn,
+                               bool allowed, bool mandatory);
 bool srv_is_signing_active(struct smbd_server_connection *conn);
 bool srv_is_signing_negotiated(struct smbd_server_connection *conn);
 void srv_set_signing(struct smbd_server_connection *conn,
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 6dc8609..28ae24e 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c


-- 
Samba Shared Repository

Reply via email to