[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Tue Aug 7 12:30:03 MDT 2012


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 <metze at 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 <metze at samba.org>
    Autobuild-Date(master): Tue Aug  7 20:29:30 CEST 2012 on sn-devel-104

commit 40f771e0105a0d13d83d66d99d9412acf6b73978
Author: Stefan Metzmacher <metze at 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 <metze at 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 <metze at 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 <metze at 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 <metze at 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 <metze at 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 <metze at 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 <metze at 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 <metze at 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 <metze at 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 <metze at 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


More information about the samba-cvs mailing list