smb2srv: correctly hold the signing state per session
authorStefan Metzmacher <metze@samba.org>
Mon, 9 Jun 2008 19:45:19 +0000 (21:45 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 28 Jul 2008 12:09:45 +0000 (14:09 +0200)
metze

source/smb_server/smb2/negprot.c
source/smb_server/smb2/receive.c
source/smb_server/smb2/sesssetup.c
source/smb_server/smb_server.h

index 3e6e2e1a43c9b2a222f91062bc37bc605788ec72..d64b36d659c010a98edca7b04ef68acad47fc0dd 100644 (file)
@@ -122,7 +122,7 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
        case SMB_SIGNING_REQUIRED:
                io->out.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED;
                /* force signing on immediately */
-               req->smb_conn->doing_signing = true;
+               req->smb_conn->smb2_signing_required = true;
                break;
        }
        io->out.dialect_revision   = SMB2_DIALECT_REVISION;
index 2f4e9df2b6ab9cb4c8692290db1348841709e324..cfd6c1d01a7f75b1571a83c647356e1996834f2c 100644 (file)
@@ -235,11 +235,8 @@ void smb2srv_send_reply(struct smb2srv_request *req)
                _smb2_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
        }
 
-       /* if the request was signed or doing_signing is true, then we
-          must sign the reply */
-       if (req->session &&
-           (req->smb_conn->doing_signing ||
-            (IVAL(req->in.hdr, SMB2_HDR_FLAGS) & SMB2_HDR_FLAG_SIGNED))) {
+       /* if signing is active on the session then sign the packet */
+       if (req->session && req->session->smb2_signing.active) {
                status = smb2_sign_message(&req->out, 
                                           req->session->session_info->session_key);
                if (!NT_STATUS_IS_OK(status)) {
@@ -310,18 +307,22 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req)
           should give a signed reply to any signed request */
        if (flags & SMB2_HDR_FLAG_SIGNED) {
                NTSTATUS status;
-               if (req->session == NULL) {
-                       /* we can't check signing with no session */
-                       smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED);
-                       return NT_STATUS_OK;                    
+
+               if (!req->session) goto nosession;
+
+               if (!req->session->smb2_signing.active) {
+                       /* TODO: workout the correct error code */
+                       smb2srv_send_error(req, NT_STATUS_FOOBAR);
+                       return NT_STATUS_OK;
                }
+
                status = smb2_check_signature(&req->in, 
                                              req->session->session_info->session_key);
                if (!NT_STATUS_IS_OK(status)) {
                        smb2srv_send_error(req, status);
                        return NT_STATUS_OK;                    
                }
-       } else if (req->smb_conn->doing_signing && req->session != NULL) {
+       } else if (req->session && req->session->smb2_signing.active) {
                /* we require signing and this request was not signed */
                smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED);
                return NT_STATUS_OK;                                    
index 9fb3220005563ab0fe65eba28f3a8d70cb812d67..6e3e96379457e1056d8089c0aead212afd4a710a 100644 (file)
@@ -90,6 +90,10 @@ static void smb2srv_sesssetup_callback(struct gensec_update_request *greq, void
        }
        req->session = smb_sess;
 
+       if (smb_sess->smb2_signing.required) {
+               /* activate smb2 signing on the session */
+               smb_sess->smb2_signing.active = true;
+       }
 done:
        io->smb2.out.uid = smb_sess->vuid;
 failed:
@@ -182,7 +186,15 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
           This is deliberate as windows does not set it even when it does 
           set SMB2_NEGOTIATE_SIGNING_REQUIRED */
        if (io->smb2.in.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
-               req->smb_conn->doing_signing = true;
+               smb_sess->smb2_signing.required = true;
+       } else if (req->smb_conn->smb2_signing_required) {
+               /*
+                * if required signing was negotiates in SMB2 Negotiate
+                * then the client made an error not using it here
+                */
+               DEBUG(1, ("SMB2 signing required on the connection but not used on session\n"));
+               req->status = NT_STATUS_FOOBAR;
+               goto failed;
        }
 
        return;
index dd4ec3281bdf4d794a5197903f7b73a5c70ffa6a..4676fc3e9cfb1f8ffe80a4f60c70be735340223b 100644 (file)
@@ -100,6 +100,11 @@ struct smbsrv_session {
 
        struct auth_session_info *session_info;
 
+       struct {
+               bool required;
+               bool active;
+       } smb2_signing;
+
        /* some statistics for the management tools */
        struct {
                /* the time when the session setup started */
@@ -380,7 +385,7 @@ struct smbsrv_connection {
 
        struct loadparm_context *lp_ctx;
 
-       bool doing_signing;
+       bool smb2_signing_required;
 };
 
 struct model_ops;