[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Mon Oct 31 14:41:03 MDT 2011


The branch, master has been updated
       via  c90870f s4:torture/smb2: fix compound.invalid2 against windows
       via  09d3df6 s4:smb_server/smb2: correctly implement related compound requests
       via  95ca064 s4:smb_server/smb2: always grant the requested credits
       via  f30fe1d s4:smb_server/smb2: echo back more header fields
       via  91648ae s3:smb2_server: FLAG_CHAINED means we always use the last session_id and tid
       via  8d07d71 s3:smb2_server: don't reset the tid and session id in the out hdr of compound requests
       via  c7d3b6b s3:smb2_server: echo the SMB2_HDR_CREDIT_CHARGE and SMB2_HDR_SIGNATURE fields
      from  6c2c189 s4-torture: smb2 copychunk data integrity checks

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


- Log -----------------------------------------------------------------
commit c90870f9b728dfb827ebc2fe8ad67a7ca3a50c43
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 27 21:41:11 2011 +0200

    s4:torture/smb2: fix compound.invalid2 against windows
    
    Tested against w2k8r2 with signing and win8pre0 without signing.
    
    metze
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Mon Oct 31 21:40:25 CET 2011 on sn-devel-104

commit 09d3df6e7e6aef03a306413e74ecd127215e1921
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Oct 31 15:23:00 2011 +0100

    s4:smb_server/smb2: correctly implement related compound requests
    
    We need to remember the session id and tree id.
    
    metze

commit 95ca06410310589ef2ccf95f25b089dae756b1d0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Oct 31 13:43:01 2011 +0100

    s4:smb_server/smb2: always grant the requested credits
    
    At least one credit, if the client asked for 0.
    
    metze

commit f30fe1decdad3090655a759aeecd027bd59c386c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 27 20:46:12 2011 +0200

    s4:smb_server/smb2: echo back more header fields
    
    metze

commit 91648aeb6409787c7766943225f5c7a9c695aa0b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 27 16:35:28 2011 +0200

    s3:smb2_server: FLAG_CHAINED means we always use the last session_id and tid
    
    metze

commit 8d07d7148bf47ea14e62d39ed8a8cc4f1366810e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 27 13:01:22 2011 +0200

    s3:smb2_server: don't reset the tid and session id in the out hdr of compound requests
    
    Windows also leaves tid (0xFFFFFFFF) and session id (0xFFFFFFFFFFFFFFFF)
    as the client requested them.
    
    metze

commit c7d3b6b2c38711943910aebff72b0188b0c346db
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Oct 27 16:42:44 2011 +0200

    s3:smb2_server: echo the SMB2_HDR_CREDIT_CHARGE and SMB2_HDR_SIGNATURE fields
    
    Windows just echos back the given values by default.
    
    metze

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

Summary of changes:
 source3/smbd/globals.h                |    2 +
 source3/smbd/smb2_server.c            |   71 ++++++++++----------------------
 source4/smb_server/smb2/receive.c     |   47 +++++++++++++++++----
 source4/smb_server/smb2/sesssetup.c   |    7 +--
 source4/smb_server/smb2/smb2_server.h |    2 +
 source4/smb_server/smb2/tcon.c        |    9 ----
 source4/torture/smb2/compound.c       |    4 +-
 7 files changed, 68 insertions(+), 74 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 14337e0..2e94b55 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -339,9 +339,11 @@ struct smbd_smb2_request {
 
 	/* the session the request operates on, maybe NULL */
 	struct smbd_smb2_session *session;
+	uint64_t last_session_id;
 
 	/* the tcon the request operates on, maybe NULL */
 	struct smbd_smb2_tcon *tcon;
+	uint32_t last_tid;
 
 	int current_idx;
 	bool do_signing;
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 84b55cc..5b41c3b 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -209,6 +209,9 @@ static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
 	req->mem_pool	= mem_pool;
 	req->parent	= parent;
 
+	req->last_session_id = UINT64_MAX;
+	req->last_tid = UINT32_MAX;
+
 	talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
 	talloc_set_destructor(req, smbd_smb2_request_destructor);
 
@@ -577,7 +580,8 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 		/* setup the SMB2 header */
 		SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,	SMB2_MAGIC);
 		SSVAL(outhdr, SMB2_HDR_LENGTH,		SMB2_HDR_BODY);
-		SSVAL(outhdr, SMB2_HDR_EPOCH,		0);
+		SSVAL(outhdr, SMB2_HDR_CREDIT_CHARGE,
+		      SVAL(inhdr, SMB2_HDR_CREDIT_CHARGE));
 		SIVAL(outhdr, SMB2_HDR_STATUS,
 		      NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
 		SSVAL(outhdr, SMB2_HDR_OPCODE,
@@ -593,7 +597,8 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 		      IVAL(inhdr, SMB2_HDR_TID));
 		SBVAL(outhdr, SMB2_HDR_SESSION_ID,
 		      BVAL(inhdr, SMB2_HDR_SESSION_ID));
-		memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
+		memcpy(outhdr + SMB2_HDR_SIGNATURE,
+		       inhdr + SMB2_HDR_SIGNATURE, 16);
 
 		/* setup error body header */
 		SSVAL(outbody, 0x00, 0x08 + 1);
@@ -1139,32 +1144,20 @@ static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
 	const uint8_t *inhdr;
 	const uint8_t *outhdr;
 	int i = req->current_idx;
+	uint32_t in_flags;
 	uint32_t in_tid;
 	void *p;
 	struct smbd_smb2_tcon *tcon;
-	bool chained_fixup = false;
+
+	req->tcon = NULL;
 
 	inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
 
+	in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
 	in_tid = IVAL(inhdr, SMB2_HDR_TID);
 
-	if (in_tid == (0xFFFFFFFF)) {
-		if (req->async) {
-			/*
-			 * async request - fill in tid from
-			 * already setup out.vector[].iov_base.
-			 */
-			outhdr = (const uint8_t *)req->out.vector[i].iov_base;
-			in_tid = IVAL(outhdr, SMB2_HDR_TID);
-		} else if (i > 2) {
-			/*
-			 * Chained request - fill in tid from
-			 * the previous request out.vector[].iov_base.
-			 */
-			outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
-			in_tid = IVAL(outhdr, SMB2_HDR_TID);
-			chained_fixup = true;
-		}
+	if (in_flags & SMB2_HDR_FLAG_CHAINED) {
+		in_tid = req->last_tid;
 	}
 
 	/* lookup an existing session */
@@ -1184,12 +1177,7 @@ static NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
 	}
 
 	req->tcon = tcon;
-
-	if (chained_fixup) {
-		/* Fix up our own outhdr. */
-		outhdr = (const uint8_t *)req->out.vector[i].iov_base;
-		SIVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_TID, in_tid);
-	}
+	req->last_tid = in_tid;
 
 	return NT_STATUS_OK;
 }
@@ -1203,32 +1191,21 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
 	const uint8_t *inhdr;
 	const uint8_t *outhdr;
 	int i = req->current_idx;
+	uint32_t in_flags;
 	uint64_t in_session_id;
 	void *p;
 	struct smbd_smb2_session *session;
-	bool chained_fixup = false;
+
+	req->session = NULL;
+	req->tcon = NULL;
 
 	inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
 
+	in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
 	in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
 
-	if (in_session_id == (0xFFFFFFFFFFFFFFFFLL)) {
-		if (req->async) {
-			/*
-			 * async request - fill in session_id from
-			 * already setup request out.vector[].iov_base.
-			 */
-			outhdr = (const uint8_t *)req->out.vector[i].iov_base;
-			in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
-		} else if (i > 2) {
-			/*
-			 * Chained request - fill in session_id from
-			 * the previous request out.vector[].iov_base.
-			 */
-			outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
-			in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
-			chained_fixup = true;
-		}
+	if (in_flags & SMB2_HDR_FLAG_CHAINED) {
+		in_session_id = req->last_session_id;
 	}
 
 	/* lookup an existing session */
@@ -1247,12 +1224,8 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
 			      session->session_info->info->domain_name);
 
 	req->session = session;
+	req->last_session_id = in_session_id;
 
-	if (chained_fixup) {
-		/* Fix up our own outhdr. */
-		outhdr = (const uint8_t *)req->out.vector[i].iov_base;
-		SBVAL(discard_const_p(uint8_t, outhdr), SMB2_HDR_SESSION_ID, in_session_id);
-	}
 	return NT_STATUS_OK;
 }
 
diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c
index b51e2b0..0ebf8f3 100644
--- a/source4/smb_server/smb2/receive.c
+++ b/source4/smb_server/smb2/receive.c
@@ -69,6 +69,9 @@ struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn)
 
 	req->smb_conn = smb_conn;
 
+	req->chained_session_id = UINT64_MAX;
+	req->chained_tree_id = UINT32_MAX;
+
 	talloc_set_destructor(req, smb2srv_request_destructor);
 
 	return req;
@@ -77,14 +80,22 @@ struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn)
 NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_size,
 			     bool body_dynamic_present, uint32_t body_dynamic_size)
 {
-	uint32_t flags = SMB2_HDR_FLAG_REDIRECT;
+	uint32_t flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS);
 	uint32_t pid = IVAL(req->in.hdr, SMB2_HDR_PID);
 	uint32_t tid = IVAL(req->in.hdr, SMB2_HDR_TID);
+	uint16_t credits = SVAL(req->in.hdr, SMB2_HDR_CREDIT);
+
+	if (credits == 0) {
+		credits = 1;
+	}
+
+	flags |= SMB2_HDR_FLAG_REDIRECT;
 
 	if (req->pending_id) {
 		flags |= SMB2_HDR_FLAG_ASYNC;
 		pid = req->pending_id;
 		tid = 0;
+		credits = 0;
 	}
 
 	if (body_dynamic_present) {
@@ -110,17 +121,19 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si
 
 	SIVAL(req->out.hdr, 0,				SMB2_MAGIC);
 	SSVAL(req->out.hdr, SMB2_HDR_LENGTH,		SMB2_HDR_BODY);
-	SSVAL(req->out.hdr, SMB2_HDR_EPOCH,		0);
+	SSVAL(req->out.hdr, SMB2_HDR_CREDIT_CHARGE,
+	      SVAL(req->in.hdr, SMB2_HDR_CREDIT_CHARGE));
 	SIVAL(req->out.hdr, SMB2_HDR_STATUS,		NT_STATUS_V(req->status));
 	SSVAL(req->out.hdr, SMB2_HDR_OPCODE,		SVAL(req->in.hdr, SMB2_HDR_OPCODE));
-	SSVAL(req->out.hdr, SMB2_HDR_CREDIT,		0x0001);
+	SSVAL(req->out.hdr, SMB2_HDR_CREDIT,		credits);
 	SIVAL(req->out.hdr, SMB2_HDR_FLAGS,		flags);
 	SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND,	0);
 	SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID,	req->seqnum);
 	SIVAL(req->out.hdr, SMB2_HDR_PID,		pid);
 	SIVAL(req->out.hdr, SMB2_HDR_TID,		tid);
 	SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID,	BVAL(req->in.hdr, SMB2_HDR_SESSION_ID));
-	memset(req->out.hdr+SMB2_HDR_SIGNATURE, 0, 16);
+	memcpy(req->out.hdr+SMB2_HDR_SIGNATURE,
+	       req->in.hdr+SMB2_HDR_SIGNATURE, 16);
 
 	/* set the length of the fixed body part and +1 if there's a dynamic part also */
 	SSVAL(req->out.body, 0, body_fixed_size + (body_dynamic_size?1:0));
@@ -223,6 +236,8 @@ static void smb2srv_chain_reply(struct smb2srv_request *p_req)
 			       sizeof(req->_chained_file_handle));
 			req->chained_file_handle = req->_chained_file_handle;
 		}
+		req->chained_session_id = p_req->chained_session_id;
+		req->chained_tree_id = p_req->chained_tree_id;
 		req->chain_status = p_req->chain_status;
 	}
 
@@ -332,9 +347,17 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req)
 		req->smb_conn->highest_smb2_seqnum = req->seqnum;
 	}
 
+	if (flags & SMB2_HDR_FLAG_CHAINED) {
+		uid = req->chained_session_id;
+		tid = req->chained_tree_id;
+	}
+
 	req->session	= smbsrv_session_find(req->smb_conn, uid, req->request_time);
 	req->tcon	= smbsrv_smb2_tcon_find(req->session, tid, req->request_time);
 
+	req->chained_session_id = uid;
+	req->chained_tree_id = tid;
+
 	errno = 0;
 
 	/* supporting signing is mandatory in SMB2, and is per-packet. So we 
@@ -569,11 +592,21 @@ NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req)
 	NTSTATUS status;
 	bool signing_used = false;
 	int id;
+	uint16_t credits = SVAL(req->in.hdr, SMB2_HDR_CREDIT);
+
+	if (credits == 0) {
+		credits = 1;
+	}
 
 	if (req->pending_id) {
 		return NT_STATUS_INTERNAL_ERROR;
 	}
 
+	if (req->smb_conn->connection->event.fde == NULL) {
+		/* the socket has been destroyed - no point trying to send an error! */
+		return NT_STATUS_REMOTE_DISCONNECT;
+	}
+
 	id = idr_get_new_above(req->smb_conn->requests2.idtree_req, req, 
 			       1, req->smb_conn->requests2.idtree_limit);
 	if (id == -1) {
@@ -583,11 +616,6 @@ NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req)
 	DLIST_ADD_END(req->smb_conn->requests2.list, req, struct smb2srv_request *);
 	req->pending_id = id;
 
-	if (req->smb_conn->connection->event.fde == NULL) {
-		/* the socket has been destroyed - no point trying to send an error! */
-		return NT_STATUS_REMOTE_DISCONNECT;
-	}
-
 	talloc_set_destructor(req, smb2srv_request_deny_destructor);
 
 	status = smb2srv_setup_reply(req, 8, true, 0);
@@ -596,6 +624,7 @@ NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req)
 	}
 
 	SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
+	SSVAL(req->out.hdr, SMB2_HDR_CREDIT, credits);
 
 	SSVAL(req->out.body, 0x02, 0);
 	SIVAL(req->out.body, 0x04, 0);
diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c
index 243765f..41f629b 100644
--- a/source4/smb_server/smb2/sesssetup.c
+++ b/source4/smb_server/smb2/sesssetup.c
@@ -31,12 +31,10 @@
 
 static void smb2srv_sesssetup_send(struct smb2srv_request *req, union smb_sesssetup *io)
 {
-	uint16_t credit;
-
 	if (NT_STATUS_IS_OK(req->status)) {
-		credit = 0x0003;
+		/* nothing */
 	} else if (NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		credit = 0x0002;
+		/* nothing */
 	} else {
 		smb2srv_send_error(req, req->status);
 		return;
@@ -44,7 +42,6 @@ static void smb2srv_sesssetup_send(struct smb2srv_request *req, union smb_sessse
 
 	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, io->smb2.out.secblob.length));
 
-	SSVAL(req->out.hdr, SMB2_HDR_CREDIT,	credit);
 	SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID,	io->smb2.out.uid);
 
 	SSVAL(req->out.body, 0x02, io->smb2.out.session_flags);
diff --git a/source4/smb_server/smb2/smb2_server.h b/source4/smb_server/smb2/smb2_server.h
index 7fb09f6..5fe12fe 100644
--- a/source4/smb_server/smb2/smb2_server.h
+++ b/source4/smb_server/smb2/smb2_server.h
@@ -64,6 +64,8 @@ struct smb2srv_request {
 	/* chained file handle */
 	uint8_t _chained_file_handle[16];
 	uint8_t *chained_file_handle;
+	uint64_t chained_session_id;
+	uint32_t chained_tree_id;
 
 	bool is_signed;
 
diff --git a/source4/smb_server/smb2/tcon.c b/source4/smb_server/smb2/tcon.c
index 0dac29c..6ee2eb5 100644
--- a/source4/smb_server/smb2/tcon.c
+++ b/source4/smb_server/smb2/tcon.c
@@ -359,23 +359,14 @@ failed:
 
 static void smb2srv_tcon_send(struct smb2srv_request *req, union smb_tcon *io)
 {
-	uint16_t credit;
-
 	if (!NT_STATUS_IS_OK(req->status)) {
 		smb2srv_send_error(req, req->status);
 		return;
 	}
-	if (io->smb2.out.share_type == NTVFS_IPC) {
-		/* if it's an IPC share vista returns 0x0005 */
-		credit = 0x0005;
-	} else {
-		credit = 0x0001;
-	}
 
 	SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x10, false, 0));
 
 	SIVAL(req->out.hdr,	SMB2_HDR_TID,	io->smb2.out.tid);
-	SSVAL(req->out.hdr,	SMB2_HDR_CREDIT,credit);
 
 	SCVAL(req->out.body,	0x02,		io->smb2.out.share_type);
 	SCVAL(req->out.body,	0x03,		io->smb2.out.reserved);
diff --git a/source4/torture/smb2/compound.c b/source4/torture/smb2/compound.c
index c40c71d..1caa688 100644
--- a/source4/torture/smb2/compound.c
+++ b/source4/torture/smb2/compound.c
@@ -367,9 +367,9 @@ static bool test_compound_invalid2(struct torture_context *tctx,
 	status = smb2_close_recv(req[1], &cl);
 	CHECK_STATUS(status, NT_STATUS_OK);
 	status = smb2_close_recv(req[2], &cl);
-	CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
+	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
 	status = smb2_close_recv(req[3], &cl);
-	CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
+	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
 	status = smb2_close_recv(req[4], &cl);
 	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list