The branch, master has been updated
       via  c301691 s3:smb2_server: fix SMB2 signing of compound responses
       via  40f771e s3:smb2_server: there's no need to copy req->out.vector 
when we just keep the last request
       via  8d63efe s3:smb2_server: use memmove instead of copying single 
vector elements
       via  9b8973d s3:smb2_server: make use of SMBD_SMB2_OUT_HDR_PTR() 
smbd_smb2_request_pending_queue()
       via  bfc87a4 s3:smb2_server: check for compound based on 
SMBD_SMB2_NUM_IOV_PER_REQ
       via  5730272 s3:smb2_server: make use of SMBD_SMB2_OUT_*_IOV 
smbd_smb2_request_reply()
       via  727b1d1 s3:smb2_server: check for compound based on 
SMBD_SMB2_NUM_IOV_PER_REQ
       via  2da6217 s3:smb2_server: make use of SMBD_SMB2_*_IOV_OFS
       via  d609bb9 s3:smb2_server: make use of helper macros in 
smb2_calculate_credits()
       via  efaea8e s3:smb2_server: make use of helper macros in 
smbd_smb2_request_validate()
       via  4e6e1ec s3:smb2_server: make use of SMBD_SMB2_NUM_IOV_PER_REQ
       via  337604a s3:smb2_server: add some more SMBD_SMB2_* defines/macros
      from  d825adf s3-param: Remove never-reached condition for popts == NULL

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


- Log -----------------------------------------------------------------
commit c3016915a1ea381976b747c4e185d4046e7995ca
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 14:24:28 2012 +0200

    s3:smb2_server: fix SMB2 signing of compound responses
    
    We need to defer the signing until we know the response
    doesn't change anymore before it goes over the wire.
    
    metze
    
    Autobuild-User(master): Stefan Metzmacher <me...@samba.org>
    Autobuild-Date(master): Tue Aug  7 20:29:30 CEST 2012 on sn-devel-104

commit 40f771e0105a0d13d83d66d99d9412acf6b73978
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 13:02:14 2012 +0200

    s3:smb2_server: there's no need to copy req->out.vector when we just keep 
the last request
    
    metze

commit 8d63efe27397f0f45b774e04e6146f87a84ba799
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 13:00:50 2012 +0200

    s3:smb2_server: use memmove instead of copying single vector elements
    
    metze

commit 9b8973d3b528169bf70a57f3cc17f35e51dfc81e
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:57:14 2012 +0200

    s3:smb2_server: make use of SMBD_SMB2_OUT_HDR_PTR() 
smbd_smb2_request_pending_queue()
    
    metze

commit bfc87a4a76294b26f6031547e18228afd4d535e5
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:56:23 2012 +0200

    s3:smb2_server: check for compound based on SMBD_SMB2_NUM_IOV_PER_REQ
    
    metze

commit 5730272690b5f4d854a4c7e8b0d68040b159d6aa
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:55:28 2012 +0200

    s3:smb2_server: make use of SMBD_SMB2_OUT_*_IOV smbd_smb2_request_reply()
    
    metze

commit 727b1d1fa867e1421cc01f4eee95f8001d315a12
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:47:44 2012 +0200

    s3:smb2_server: check for compound based on SMBD_SMB2_NUM_IOV_PER_REQ
    
    metze

commit 2da62179de7d2547703ff6ae78f80518abed91b8
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:41:07 2012 +0200

    s3:smb2_server: make use of SMBD_SMB2_*_IOV_OFS
    
    metze

commit d609bb9b4201f50322278e949fe036fe70c1e77f
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:31:36 2012 +0200

    s3:smb2_server: make use of helper macros in smb2_calculate_credits()
    
    metze

commit efaea8e0e1ca389ac7bd82f2d9a3401f92094fe4
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:30:54 2012 +0200

    s3:smb2_server: make use of helper macros in smbd_smb2_request_validate()
    
    metze

commit 4e6e1ecb6eb948c9651c6a1e17319c75191a1bac
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:26:38 2012 +0200

    s3:smb2_server: make use of SMBD_SMB2_NUM_IOV_PER_REQ
    
    metze

commit 337604a0cff2c4a09b4e29b88650149db897b8b2
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 12:22:06 2012 +0200

    s3:smb2_server: add some more SMBD_SMB2_* defines/macros
    
    metze

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

Summary of changes:
 source3/smbd/globals.h     |   34 ++++++-
 source3/smbd/smb2_server.c |  228 +++++++++++++++++++++++++++-----------------
 2 files changed, 169 insertions(+), 93 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 967fe85..7b2d31d 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -460,6 +460,12 @@ struct smbd_smb2_request {
        bool cancelled;
        bool compound_related;
 
+       /*
+        * the signing/encryption key for the last
+        * request/response of a compound chain
+        */
+       DATA_BLOB last_key;
+
        struct timeval request_time;
 
        /* fake smb1 request. */
@@ -474,21 +480,37 @@ struct smbd_smb2_request {
         */
        struct tevent_req *subreq;
 
-#define SMBD_SMB2_IN_HDR_IOV(req)    (&req->in.vector[req->current_idx+0])
+#define SMBD_SMB2_HDR_IOV_OFS 0
+#define SMBD_SMB2_BODY_IOV_OFS 1
+#define SMBD_SMB2_DYN_IOV_OFS 2
+
+#define SMBD_SMB2_NUM_IOV_PER_REQ 3
+
+#define SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,ofs) \
+       (&req->dir.vector[(idx)+(ofs)])
+
+#define SMBD_SMB2_IDX_HDR_IOV(req,dir,idx) \
+       SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_HDR_IOV_OFS)
+#define SMBD_SMB2_IDX_BODY_IOV(req,dir,idx) \
+       SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_BODY_IOV_OFS)
+#define SMBD_SMB2_IDX_DYN_IOV(req,dir,idx) \
+       SMBD_SMB2_IOV_IDX_OFS(req,dir,idx,SMBD_SMB2_DYN_IOV_OFS)
+
+#define SMBD_SMB2_IN_HDR_IOV(req)    
SMBD_SMB2_IDX_HDR_IOV(req,in,req->current_idx)
 #define SMBD_SMB2_IN_HDR_PTR(req)    (uint8_t 
*)(SMBD_SMB2_IN_HDR_IOV(req)->iov_base)
-#define SMBD_SMB2_IN_BODY_IOV(req)   (&req->in.vector[req->current_idx+1])
+#define SMBD_SMB2_IN_BODY_IOV(req)   
SMBD_SMB2_IDX_BODY_IOV(req,in,req->current_idx)
 #define SMBD_SMB2_IN_BODY_PTR(req)   (uint8_t 
*)(SMBD_SMB2_IN_BODY_IOV(req)->iov_base)
 #define SMBD_SMB2_IN_BODY_LEN(req)   (SMBD_SMB2_IN_BODY_IOV(req)->iov_len)
-#define SMBD_SMB2_IN_DYN_IOV(req)    (&req->in.vector[req->current_idx+2])
+#define SMBD_SMB2_IN_DYN_IOV(req)    
SMBD_SMB2_IDX_DYN_IOV(req,in,req->current_idx)
 #define SMBD_SMB2_IN_DYN_PTR(req)    (uint8_t 
*)(SMBD_SMB2_IN_DYN_IOV(req)->iov_base)
 #define SMBD_SMB2_IN_DYN_LEN(req)    (SMBD_SMB2_IN_DYN_IOV(req)->iov_len)
 
-#define SMBD_SMB2_OUT_HDR_IOV(req)   (&req->out.vector[req->current_idx+0])
+#define SMBD_SMB2_OUT_HDR_IOV(req)   
SMBD_SMB2_IDX_HDR_IOV(req,out,req->current_idx)
 #define SMBD_SMB2_OUT_HDR_PTR(req)   (uint8_t 
*)(SMBD_SMB2_OUT_HDR_IOV(req)->iov_base)
-#define SMBD_SMB2_OUT_BODY_IOV(req)  (&req->out.vector[req->current_idx+1])
+#define SMBD_SMB2_OUT_BODY_IOV(req)  
SMBD_SMB2_IDX_BODY_IOV(req,out,req->current_idx)
 #define SMBD_SMB2_OUT_BODY_PTR(req)  (uint8_t 
*)(SMBD_SMB2_OUT_BODY_IOV(req)->iov_base)
 #define SMBD_SMB2_OUT_BODY_LEN(req)  (SMBD_SMB2_OUT_BODY_IOV(req)->iov_len)
-#define SMBD_SMB2_OUT_DYN_IOV(req)   (&req->out.vector[req->current_idx+2])
+#define SMBD_SMB2_OUT_DYN_IOV(req)   
SMBD_SMB2_IDX_DYN_IOV(req,out,req->current_idx)
 #define SMBD_SMB2_OUT_DYN_PTR(req)   (uint8_t 
*)(SMBD_SMB2_OUT_DYN_IOV(req)->iov_base)
 #define SMBD_SMB2_OUT_DYN_LEN(req)   (SMBD_SMB2_OUT_DYN_IOV(req)->iov_len)
 
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 4e3259a..afd001c 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -235,6 +235,12 @@ static void smb2_setup_nbt_length(struct iovec *vector, 
int count)
        _smb2_setlen(vector[0].iov_base, len);
 }
 
+static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
+{
+       data_blob_clear_free(&req->last_key);
+       return 0;
+}
+
 static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX 
*mem_ctx)
 {
        TALLOC_CTX *mem_pool;
@@ -261,6 +267,8 @@ static struct smbd_smb2_request 
*smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
        req->last_session_id = UINT64_MAX;
        req->last_tid = UINT32_MAX;
 
+       talloc_set_destructor(req, smbd_smb2_request_destructor);
+
        return req;
 }
 
@@ -292,6 +300,9 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct 
smbXsrv_connection *conn,
                size_t full_size;
                size_t next_command_ofs;
                uint16_t body_size;
+               uint8_t *body = NULL;
+               uint32_t dyn_size;
+               uint8_t *dyn = NULL;
                struct iovec *iov_tmp;
 
                /*
@@ -338,23 +349,26 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct 
smbXsrv_connection *conn,
                         */
                        body_size = full_size - SMB2_HDR_BODY;
                }
+               body = hdr + SMB2_HDR_BODY;
+               dyn = body + body_size;
+               dyn_size = full_size - (SMB2_HDR_BODY + body_size);
 
                iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
-                                        num_iov + 3);
+                                        num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
                if (iov_tmp == NULL) {
                        TALLOC_FREE(iov);
                        return NT_STATUS_NO_MEMORY;
                }
                iov = iov_tmp;
                cur = &iov[num_iov];
-               num_iov += 3;
+               num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
 
-               cur[0].iov_base = hdr;
-               cur[0].iov_len  = SMB2_HDR_BODY;
-               cur[1].iov_base = hdr + SMB2_HDR_BODY;
-               cur[1].iov_len  = body_size;
-               cur[2].iov_base = hdr + SMB2_HDR_BODY + body_size;
-               cur[2].iov_len  = full_size - (SMB2_HDR_BODY + body_size);
+               cur[SMBD_SMB2_HDR_IOV_OFS].iov_base  = hdr;
+               cur[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
+               cur[SMBD_SMB2_BODY_IOV_OFS].iov_base = body;
+               cur[SMBD_SMB2_BODY_IOV_OFS].iov_len  = body_size;
+               cur[SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
+               cur[SMBD_SMB2_DYN_IOV_OFS].iov_len   = dyn_size;
 
                taken += full_size;
        }
@@ -584,24 +598,26 @@ static NTSTATUS smbd_smb2_request_validate(struct 
smbd_smb2_request *req)
 
        count = req->in.vector_count;
 
-       if (count < 4) {
+       if (count < 1 + SMBD_SMB2_NUM_IOV_PER_REQ) {
                /* It's not a SMB2 request */
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       for (idx=1; idx < count; idx += 3) {
+       for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
+               struct iovec *hdr = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
+               struct iovec *body = SMBD_SMB2_IDX_BODY_IOV(req,in,idx);
                const uint8_t *inhdr = NULL;
                uint32_t flags;
 
-               if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
+               if (hdr->iov_len != SMB2_HDR_BODY) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
-               if (req->in.vector[idx+1].iov_len < 2) {
+               if (body->iov_len < 2) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
-               inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
+               inhdr = (const uint8_t *)hdr->iov_base;
 
                /* Check the SMB2 header */
                if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
@@ -799,16 +815,18 @@ static void smb2_calculate_credits(const struct 
smbd_smb2_request *inreq,
 
        count = outreq->out.vector_count;
 
-       for (idx=1; idx < count; idx += 3) {
-               uint8_t *outhdr = (uint8_t *)outreq->out.vector[idx].iov_base;
-               smb2_set_operation_credit(outreq->sconn,
-                       &inreq->in.vector[idx],
-                       &outreq->out.vector[idx]);
+       for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
+               struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(inreq,in,idx);
+               struct iovec *outhdr_v = SMBD_SMB2_IDX_HDR_IOV(outreq,out,idx);
+               uint8_t *outhdr = (uint8_t *)outhdr_v->iov_base;
+
+               smb2_set_operation_credit(outreq->sconn, inhdr_v, outhdr_v);
+
                /* To match Windows, count up what we
                   just granted. */
                total_credits += SVAL(outhdr, SMB2_HDR_CREDIT);
                /* Set to zero in all but the last reply. */
-               if (idx + 3 < count) {
+               if (idx + SMBD_SMB2_NUM_IOV_PER_REQ < count) {
                        SSVAL(outhdr, SMB2_HDR_CREDIT, 0);
                } else {
                        SSVAL(outhdr, SMB2_HDR_CREDIT, total_credits);
@@ -832,21 +850,20 @@ static NTSTATUS smbd_smb2_request_setup_out(struct 
smbd_smb2_request *req)
        vector[0].iov_len       = 4;
        SIVAL(req->out.nbt_hdr, 0, 0);
 
-       for (idx=1; idx < count; idx += 3) {
-               const uint8_t *inhdr = NULL;
+       for (idx=1; idx < count; idx += SMBD_SMB2_NUM_IOV_PER_REQ) {
+               struct iovec *inhdr_v = SMBD_SMB2_IDX_HDR_IOV(req,in,idx);
+               const uint8_t *inhdr = (const uint8_t *)inhdr_v->iov_base;
                uint8_t *outhdr = NULL;
                uint8_t *outbody = NULL;
                uint32_t next_command_ofs = 0;
                struct iovec *current = &vector[idx];
 
-               if ((idx + 3) < count) {
+               if ((idx + SMBD_SMB2_NUM_IOV_PER_REQ) < count) {
                        /* we have a next command -
                         * setup for the error case. */
                        next_command_ofs = SMB2_HDR_BODY + 9;
                }
 
-               inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
-
                outhdr = talloc_zero_array(vector, uint8_t,
                                      OUTVEC_ALLOC_SIZE);
                if (outhdr == NULL) {
@@ -855,14 +872,14 @@ static NTSTATUS smbd_smb2_request_setup_out(struct 
smbd_smb2_request *req)
 
                outbody = outhdr + SMB2_HDR_BODY;
 
-               current[0].iov_base     = (void *)outhdr;
-               current[0].iov_len      = SMB2_HDR_BODY;
+               current[SMBD_SMB2_HDR_IOV_OFS].iov_base  = (void *)outhdr;
+               current[SMBD_SMB2_HDR_IOV_OFS].iov_len   = SMB2_HDR_BODY;
 
-               current[1].iov_base     = (void *)outbody;
-               current[1].iov_len      = 8;
+               current[SMBD_SMB2_BODY_IOV_OFS].iov_base = (void *)outbody;
+               current[SMBD_SMB2_BODY_IOV_OFS].iov_len  = 8;
 
-               current[2].iov_base     = NULL;
-               current[2].iov_len      = 0;
+               current[SMBD_SMB2_DYN_IOV_OFS].iov_base  = NULL;
+               current[SMBD_SMB2_DYN_IOV_OFS].iov_len   = 0;
 
                /* setup the SMB2 header */
                SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,     SMB2_MAGIC);
@@ -1013,7 +1030,7 @@ static struct smbd_smb2_request *dup_smb2_req(const 
struct smbd_smb2_request *re
        memcpy(newreq->out.nbt_hdr, req->out.nbt_hdr, 4);
 
        /* Setup the vectors identically to the ones in req. */
-       for (i = 1; i < count; i += 3) {
+       for (i = 1; i < count; i += SMBD_SMB2_NUM_IOV_PER_REQ) {
                if (!dup_smb2_vec3(outvec, &outvec[i], &req->out.vector[i])) {
                        break;
                }
@@ -1035,9 +1052,11 @@ static void smbd_smb2_request_writev_done(struct 
tevent_req *subreq);
 
 static NTSTATUS smb2_send_async_interim_response(const struct 
smbd_smb2_request *req)
 {
-       int i = 0;
+       struct smbXsrv_connection *conn = req->sconn->conn;
+       struct iovec *outhdr_v = NULL;
        uint8_t *outhdr = NULL;
        struct smbd_smb2_request *nreq = NULL;
+       NTSTATUS status;
 
        /* Create a new smb2 request we'll use
           for the interim return. */
@@ -1046,36 +1065,37 @@ static NTSTATUS smb2_send_async_interim_response(const 
struct smbd_smb2_request
                return NT_STATUS_NO_MEMORY;
        }
 
-       /* Lose the last 3 out vectors. They're the
+       /* Lose the last X out vectors. They're the
           ones we'll be using for the async reply. */
-       nreq->out.vector_count -= 3;
+       nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
 
        smb2_setup_nbt_length(nreq->out.vector,
                nreq->out.vector_count);
 
        /* Step back to the previous reply. */
-       i = nreq->current_idx - 3;
-       outhdr = (uint8_t *)nreq->out.vector[i].iov_base;
+       nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
+       outhdr_v = SMBD_SMB2_OUT_HDR_IOV(nreq);
+       outhdr = SMBD_SMB2_OUT_HDR_PTR(nreq);
        /* And end the chain. */
        SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
 
        /* Calculate outgoing credits */
        smb2_calculate_credits(req, nreq);
 
-       /* Re-sign if needed. */
-       if (nreq->do_signing) {
-               NTSTATUS status;
-               struct smbXsrv_session *x = nreq->session;
-               struct smbXsrv_connection *conn = x->connection;
-               DATA_BLOB signing_key = x->global->channels[0].signing_key;
-
-               status = smb2_signing_sign_pdu(signing_key,
+       /*
+        * As we have changed the header (SMB2_HDR_NEXT_COMMAND),
+        * we need to sign here with the last signing key we remembered
+        */
+       if (req->last_key.length > 0) {
+               status = smb2_signing_sign_pdu(req->last_key,
                                               conn->protocol,
-                                              &nreq->out.vector[i], 3);
+                                              outhdr_v,
+                                              SMBD_SMB2_NUM_IOV_PER_REQ);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
        }
+
        if (DEBUGLEVEL >= 10) {
                dbgtext("smb2_send_async_interim_response: nreq->current_idx = 
%u\n",
                        (unsigned int)nreq->current_idx );
@@ -1161,7 +1181,7 @@ NTSTATUS smbd_smb2_request_pending_queue(struct 
smbd_smb2_request *req,
                return NT_STATUS_OK;
        }
 
-       if (req->in.vector_count > i + 3) {
+       if (req->in.vector_count > i + SMBD_SMB2_NUM_IOV_PER_REQ) {
                /*
                 * We're trying to go async in a compound
                 * request chain. This is not allowed.
@@ -1178,10 +1198,9 @@ NTSTATUS smbd_smb2_request_pending_queue(struct 
smbd_smb2_request *req,
                print_req_vectors(req);
        }
 
-       if (req->out.vector_count > 4) {
-               struct iovec *outvec = NULL;
-
-               /* This is a compound reply. We
+       if (req->out.vector_count >= (2*SMBD_SMB2_NUM_IOV_PER_REQ)) {
+               /*
+                * This is a compound reply. We
                 * must do an interim response
                 * followed by the async response
                 * to match W2K8R2.
@@ -1205,43 +1224,28 @@ NTSTATUS smbd_smb2_request_pending_queue(struct 
smbd_smb2_request *req,
                req->compound_related = false;
                req->sconn->smb2.compound_related_in_progress = false;
 
+               req->current_idx = 1;
+
                /* Re-arrange the in.vectors. */
-               req->in.vector[1] = req->in.vector[i];
-               req->in.vector[2] = req->in.vector[i+1];
-               req->in.vector[3] = req->in.vector[i+2];
-               req->in.vector_count = 4;
+               memmove(&req->in.vector[req->current_idx],
+                       &req->in.vector[i],
+                       sizeof(req->in.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
+               req->in.vector_count = req->current_idx + 
SMBD_SMB2_NUM_IOV_PER_REQ;
 
                /* Reset the new in size. */
-               smb2_setup_nbt_length(req->in.vector, 4);
-
-               /* Now recreate the out.vectors. */
-               outvec = talloc_zero_array(req, struct iovec, 4);
-               if (!outvec) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               /* 0 is always boilerplate and must
-                * be of size 4 for the length field. */
-
-               outvec[0].iov_base = req->out.nbt_hdr;
-               outvec[0].iov_len = 4;
-               SIVAL(req->out.nbt_hdr, 0, 0);
-
-               if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               TALLOC_FREE(req->out.vector);
+               smb2_setup_nbt_length(req->in.vector, req->in.vector_count);
 
-               req->out.vector = outvec;
-
-               req->current_idx = 1;
-               req->out.vector_count = 4;
+               /* Re-arrange the out.vectors. */
+               memmove(&req->out.vector[req->current_idx],
+                       &req->out.vector[i],
+                       sizeof(req->out.vector[0])*SMBD_SMB2_NUM_IOV_PER_REQ);
+               req->out.vector_count = req->current_idx + 
SMBD_SMB2_NUM_IOV_PER_REQ;
 
-               outhdr = (uint8_t *)req->out.vector[1].iov_base;
+               outhdr = SMBD_SMB2_OUT_HDR_PTR(req);
                flags = (IVAL(outhdr, SMB2_HDR_FLAGS) & ~SMB2_HDR_FLAG_CHAINED);
                SIVAL(outhdr, SMB2_HDR_FLAGS, flags);
        }
+       data_blob_clear_free(&req->last_key);
 
        defer_endtime = timeval_current_ofs_usec(defer_time);
        req->async_te = tevent_add_timer(req->sconn->ev_ctx,
@@ -1749,7 +1753,8 @@ NTSTATUS smbd_smb2_request_dispatch(struct 
smbd_smb2_request *req)
                req->do_signing = true;
                status = smb2_signing_check_pdu(signing_key,
                                                conn->protocol,
-                                               SMBD_SMB2_IN_HDR_IOV(req), 3);
+                                               SMBD_SMB2_IN_HDR_IOV(req),
+                                               SMBD_SMB2_NUM_IOV_PER_REQ);
                if (!NT_STATUS_IS_OK(status)) {
                        return smbd_smb2_request_error(req, status);
                }
@@ -1968,13 +1973,23 @@ NTSTATUS smbd_smb2_request_dispatch(struct 
smbd_smb2_request *req)
 
 static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
 {
+       struct smbXsrv_connection *conn = req->sconn->conn;
        struct tevent_req *subreq;
-       int i = req->current_idx;
+       struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
+       struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
+       struct iovec *lasthdr = NULL;
 
        req->subreq = NULL;
        TALLOC_FREE(req->async_te);
 
-       req->current_idx += 3;
+       if ((req->current_idx > SMBD_SMB2_NUM_IOV_PER_REQ) &&
+           (req->last_key.length > 0)) {
+               int last_idx = req->current_idx - SMBD_SMB2_NUM_IOV_PER_REQ;
+
+               lasthdr = SMBD_SMB2_IDX_HDR_IOV(req,out,last_idx);
+       }
+
+       req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ;
 
        if (req->current_idx < req->out.vector_count) {
                /*
@@ -1989,6 +2004,25 @@ static NTSTATUS smbd_smb2_request_reply(struct 
smbd_smb2_request *req)
                if (!im) {
                        return NT_STATUS_NO_MEMORY;
                }
+
+               data_blob_clear_free(&req->last_key);
+
+               if (req->do_signing) {
+                       struct smbXsrv_session *x = req->session;
+                       DATA_BLOB signing_key = 
x->global->channels[0].signing_key;
+
+                       /*
+                        * we need to remember the signing key
+                        * and defer the signing until
+                        * we are sure that we do not change
+                        * the header again.
+                        */
+                       req->last_key = data_blob_dup_talloc(req, signing_key);
+                       if (req->last_key.data == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+
                tevent_schedule_immediate(im,
                                        req->sconn->ev_ctx,
                                        smbd_smb2_request_dispatch_immediate,
@@ -2006,15 +2040,36 @@ static NTSTATUS smbd_smb2_request_reply(struct 
smbd_smb2_request *req)
           is a final reply for an async operation). */
        smb2_calculate_credits(req, req);
 
+       /*
+        * As we are sure the header of the last request in the
+        * compound chain will not change, we can to sign here
+        * with the last signing key we remembered.
+        */
+       if (lasthdr != NULL) {
+               NTSTATUS status;
+
+               status = smb2_signing_sign_pdu(req->last_key,
+                                              conn->protocol,
+                                              lasthdr,
+                                              SMBD_SMB2_NUM_IOV_PER_REQ);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+       }
+       data_blob_clear_free(&req->last_key);
+
+       /*
+        * now check if we need to sign the current response
+        */
        if (req->do_signing) {
                NTSTATUS status;
                struct smbXsrv_session *x = req->session;
-               struct smbXsrv_connection *conn = x->connection;
                DATA_BLOB signing_key = x->global->channels[0].signing_key;
 
                status = smb2_signing_sign_pdu(signing_key,
                                               conn->protocol,
-                                              &req->out.vector[i], 3);
+                                              outhdr,
+                                              SMBD_SMB2_NUM_IOV_PER_REQ);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -2026,9 +2081,8 @@ static NTSTATUS smbd_smb2_request_reply(struct 
smbd_smb2_request *req)
        }
 
        /* I am a sick, sick man... :-). Sendfile hack ... JRA. */
-       if (req->out.vector_count == 4 &&
-                       req->out.vector[3].iov_base == NULL &&
-                       req->out.vector[3].iov_len != 0) {
+       if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) &&
+           outdyn->iov_base == NULL && outdyn->iov_len != 0) {


-- 
Samba Shared Repository

Reply via email to