[SCM] Samba Shared Repository - branch master updated

Volker Lendecke vlendec at samba.org
Sat Mar 10 09:15:01 MST 2012


The branch, master has been updated
       via  8f93068 s3: Add smb_request_done
       via  2c1caf5 s3: Remove unused smb_request->done
       via  3a7bc3a s3: Remove unused smb_request->chain_outbuf
       via  572bc64 s3: Remove "req_wct_ofs()"
       via  12068d4 s3: Fix the read&x offset within a chain
       via  11d087a s3: Remove chain_reply
       via  3b2c9be s3: Replace chain_reply
       via  c9870a6 s3: Add a new set of andx chain handling routines
       via  90b33a0 s3: Make sure the andX chains are ended correctly
      from  a28a740 s3: Fix a 64-bit warning

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


- Log -----------------------------------------------------------------
commit 8f93068cf8fc3d282e0975cc5cbdcd2098b10d52
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Mar 4 12:10:04 2012 +0100

    s3: Add smb_request_done
    
    This is used to enable async chained command sequences. A synchronous
    reply_xxx command does not need to take are anymore about and_x
    chaining. The async commands (pipe r/w at this moment) must do so
    however. When finished, they must inform the main chain engine that
    they are finished with a smb_request_done call.
    
    Autobuild-User: Volker Lendecke <vl at samba.org>
    Autobuild-Date: Sat Mar 10 17:14:05 CET 2012 on sn-devel-104

commit 2c1caf5fcb002f5a4e049fcb812c98c435d0f2c9
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Mar 3 00:59:56 2012 +0100

    s3: Remove unused smb_request->done

commit 3a7bc3abb837b8c9df2c156440eb8a6f7e60c8d9
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Mar 3 00:34:27 2012 +0100

    s3: Remove unused smb_request->chain_outbuf

commit 572bc64b594d0d30cb64976579a55e74f01800d2
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Mar 3 00:33:15 2012 +0100

    s3: Remove "req_wct_ofs()"
    
    This is fixed up in construct_reply_chain

commit 12068d4aaca0579b58bbb121df4d1e947f8ea032
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Feb 29 23:44:36 2012 +0100

    s3: Fix the read&x offset within a chain

commit 11d087aa04f436147e7a9dd1748a43bde24de8e3
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Feb 28 01:21:44 2012 +0100

    s3: Remove chain_reply
    
    <insert your favourite tombstone ascii art here>

commit 3b2c9bebc0aa08fe9a65afe5870bea490c5fb33a
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Feb 28 00:56:10 2012 +0100

    s3: Replace chain_reply
    
    This is a new implementation of our andx handling code. The old
    code was quite involved in that it was called from within the reply_
    handlers. This leads to pretty complex faking of smb_request
    structures to give them the same environment, independent of whether
    they are called directly or from within chain_reply.
    
    chain_reply needs to go because it blocks really async handling of
    chained requests.

commit c9870a62f5d8865e67ae519db3f8e890afb6ee70
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Feb 28 00:19:48 2012 +0100

    s3: Add a new set of andx chain handling routines
    
    This is in preparation of getting rid of chain_reply.

commit 90b33a05e967e9e29c4584bed188ef6fa5a3fbf0
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Feb 26 16:49:09 2012 +0100

    s3: Make sure the andX chains are ended correctly
    
    Normally chain_reply took care of this. This will go away soon.

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

Summary of changes:
 source3/Makefile.in             |    3 +-
 source3/include/smb.h           |   12 +-
 source3/smbd/blocking.c         |   11 +-
 source3/smbd/nttrans.c          |    9 +-
 source3/smbd/pipes.c            |   20 +-
 source3/smbd/process.c          |  638 ++++++++++++++++++++++++---------------
 source3/smbd/proto.h            |   15 +-
 source3/smbd/reply.c            |   23 +-
 source3/smbd/sesssetup.c        |    5 +-
 source3/torture/cmd_vfs.c       |    2 +
 source3/torture/vfstest.h       |    3 +
 source3/torture/vfstest_chain.c |  342 +++++++++++++++++++++
 source3/wscript_build           |    3 +-
 13 files changed, 804 insertions(+), 282 deletions(-)
 create mode 100644 source3/torture/vfstest_chain.c


Changeset truncated at 500 lines:

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 2b0002b..dc02b6a 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -1299,7 +1299,8 @@ PDBTEST_OBJ = torture/pdbtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
 		$(SMBLDAP_OBJ) $(POPT_LIB_OBJ) \
 		$(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ)
 
-VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ)
+VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ) \
+		torture/vfstest_chain.o
 
 LOG2PCAP_OBJ = utils/log2pcaphex.o
 
diff --git a/source3/include/smb.h b/source3/include/smb.h
index d93f30d..382926c 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -481,17 +481,10 @@ struct smb_request {
 	struct files_struct *chain_fsp;
 
 	/*
-	 * Here we collect the outbufs from the chain handlers
-	 */
-	uint8_t *chain_outbuf;
-
-	/*
 	 * state information for async smb handling
 	 */
 	void *async_priv;
 
-	bool done;
-
 	/*
 	 * Back pointer to smb2 request.
 	 */
@@ -502,6 +495,11 @@ struct smb_request {
 	 * under privilege.
 	 */
 	struct privilege_paths *priv_paths;
+
+	/*
+	 * Request list for chained requests, we're part of it.
+	 */
+	struct smb_request **chain;
 };
 
 /* Defines for the sent_oplock_break field above. */
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index 6496e43..d512b96 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -271,6 +271,8 @@ static void reply_lockingX_success(struct blocking_lock_record *blr)
 	struct smb_request *req = blr->req;
 
 	reply_outbuf(req, 2, 0);
+	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
 
 	/*
 	 * As this message is a lockingX call we must handle
@@ -280,7 +282,14 @@ static void reply_lockingX_success(struct blocking_lock_record *blr)
 	 * that here and must set up the chain info manually.
 	 */
 
-	chain_reply(req);
+	if (!srv_send_smb(req->sconn,
+			(char *)req->outbuf,
+			true, req->seqnum+1,
+			IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
+			&req->pcd)) {
+		exit_server_cleanly("construct_reply: srv_send_smb failed.");
+	}
+
 	TALLOC_FREE(req->outbuf);
 }
 
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index cfa048b..fc52ee5 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -352,6 +352,9 @@ static void do_ntcreate_pipe_open(connection_struct *conn,
 		reply_outbuf(req, 34, 0);
 	}
 
+	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
+
 	p = (char *)req->outbuf + smb_vwv2;
 	p++;
 	SSVAL(p,0,pnum);
@@ -379,8 +382,6 @@ static void do_ntcreate_pipe_open(connection_struct *conn,
 	}
 
 	DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname));
-
-	chain_reply(req);
 }
 
 struct case_semantics_state {
@@ -634,6 +635,9 @@ void reply_ntcreate_and_X(struct smb_request *req)
 		reply_outbuf(req, 34, 0);
 	}
 
+	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
+
 	p = (char *)req->outbuf + smb_vwv2;
 
 	SCVAL(p, 0, oplock_granted);
@@ -728,7 +732,6 @@ void reply_ntcreate_and_X(struct smb_request *req)
 	DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n",
 		fsp->fnum, smb_fname_str_dbg(smb_fname)));
 
-	chain_reply(req);
  out:
 	END_PROFILE(SMBntcreateX);
 	return;
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index 9e5dfc3..c3a5cb3 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -146,6 +146,9 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
 	/* Prepare the reply */
 	reply_outbuf(req, 15, 0);
 
+	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
+
 	/* Mark the opened file as an existing named pipe in message mode. */
 	SSVAL(req->outbuf,smb_vwv9,2);
 	SSVAL(req->outbuf,smb_vwv10,0xc700);
@@ -156,9 +159,6 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
 	SIVAL(req->outbuf, smb_vwv6, 0);	/* size */
 	SSVAL(req->outbuf, smb_vwv8, 0);	/* rmode */
 	SSVAL(req->outbuf, smb_vwv11, 0x0001);
-
-	chain_reply(req);
-	return;
 }
 
 /****************************************************************************
@@ -354,18 +354,20 @@ static void pipe_write_andx_done(struct tevent_req *subreq)
 
 	reply_outbuf(req, 6, 0);
 
+	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
+
 	nwritten = (state->pipe_start_message_raw ? nwritten + 2 : nwritten);
 	SSVAL(req->outbuf,smb_vwv2,nwritten);
 
 	DEBUG(3,("writeX-IPC nwritten=%d\n", (int)nwritten));
 
  done:
-	chain_reply(req);
 	/*
 	 * We must free here as the ownership of req was
 	 * moved to the connection struct in reply_pipe_write_and_X().
 	 */
-	TALLOC_FREE(req);
+	smb_request_done(req);
 }
 
 /****************************************************************************
@@ -417,6 +419,9 @@ void reply_pipe_read_and_X(struct smb_request *req)
 	state->smb_mincnt = SVAL(req->vwv+6, 0);
 
 	reply_outbuf(req, 12, state->smb_maxcnt);
+	SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
+	SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
+
 	data = (uint8_t *)smb_buf(req->outbuf);
 
 	/*
@@ -474,7 +479,7 @@ static void pipe_read_andx_done(struct tevent_req *subreq)
 
 	SSVAL(req->outbuf,smb_vwv5,nread);
 	SSVAL(req->outbuf,smb_vwv6,
-	      req_wct_ofs(req)
+	      (smb_wct - 4)	/* offset from smb header to wct */
 	      + 1 		/* the wct field */
 	      + 12 * sizeof(uint16_t) /* vwv */
 	      + 2);		/* the buflen field */
@@ -484,10 +489,9 @@ static void pipe_read_andx_done(struct tevent_req *subreq)
 		 state->smb_mincnt, state->smb_maxcnt, (int)nread));
 
  done:
-	chain_reply(req);
 	/*
 	 * We must free here as the ownership of req was
 	 * moved to the connection struct in reply_pipe_read_and_X().
 	 */
-	TALLOC_FREE(req);
+	smb_request_done(req);
 }
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index f87eccf..8b15ac8 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -60,6 +60,7 @@ static void construct_reply_common(struct smb_request *req, const char *inbuf,
 				   char *outbuf);
 static struct pending_message_list *get_deferred_open_message_smb(
 	struct smbd_server_connection *sconn, uint64_t mid);
+static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf);
 
 static bool smbd_lock_socket_internal(struct smbd_server_connection *sconn)
 {
@@ -537,10 +538,9 @@ static bool init_smb_request(struct smb_request *req,
 	req->sconn = sconn;
 	req->conn = conn_find(sconn,req->tid);
 	req->chain_fsp = NULL;
-	req->chain_outbuf = NULL;
-	req->done = false;
 	req->smb2req = NULL;
 	req->priv_paths = NULL;
+	req->chain = NULL;
 	smb_init_perfcount_data(&req->pcd);
 
 	/* Ensure we have at least wct words and 2 bytes of bcc. */
@@ -1537,11 +1537,6 @@ static void construct_reply(struct smbd_server_connection *sconn,
 
 	conn = switch_message(req->cmd, req);
 
-	if (req->done) {
-		TALLOC_FREE(req);
-		return;
-	}
-
 	if (req->outbuf == NULL) {
 		return;
 	}
@@ -1563,6 +1558,162 @@ static void construct_reply(struct smbd_server_connection *sconn,
 	return;
 }
 
+static void construct_reply_chain(struct smbd_server_connection *sconn,
+				  char *inbuf, int size, uint32_t seqnum,
+				  bool encrypted,
+				  struct smb_perfcount_data *deferred_pcd)
+{
+	struct smb_request **reqs = NULL;
+	struct smb_request *req;
+	unsigned num_reqs;
+	bool ok;
+
+	ok = smb1_parse_chain(talloc_tos(), (uint8_t *)inbuf, sconn, encrypted,
+			      seqnum, &reqs, &num_reqs);
+	if (!ok) {
+		char errbuf[smb_size];
+		error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
+			     __LINE__, __FILE__);
+		if (!srv_send_smb(sconn, errbuf, true, seqnum, encrypted,
+				  NULL)) {
+			exit_server_cleanly("construct_reply_chain: "
+					    "srv_send_smb failed.");
+		}
+		return;
+	}
+
+	req = reqs[0];
+	req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
+
+	req->conn = switch_message(req->cmd, req);
+
+	if (req->outbuf == NULL) {
+		/*
+		 * Request has suspended itself, will come
+		 * back here.
+		 */
+		return;
+	}
+	smb_request_done(req);
+}
+
+/*
+ * To be called from an async SMB handler that is potentially chained
+ * when it is finished for shipping.
+ */
+
+void smb_request_done(struct smb_request *req)
+{
+	struct smb_request **reqs = NULL;
+	struct smb_request *first_req;
+	size_t i, num_reqs, next_index;
+	NTSTATUS status;
+
+	if (req->chain == NULL) {
+		first_req = req;
+		goto shipit;
+	}
+
+	reqs = req->chain;
+	num_reqs = talloc_array_length(reqs);
+
+	for (i=0; i<num_reqs; i++) {
+		if (reqs[i] == req) {
+			break;
+		}
+	}
+	if (i == num_reqs) {
+		/*
+		 * Invalid chain, should not happen
+		 */
+		status = NT_STATUS_INTERNAL_ERROR;
+		goto error;
+	}
+	next_index = i+1;
+
+	while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
+		struct smb_request *next = reqs[next_index];
+
+		next->vuid = SVAL(req->outbuf, smb_uid);
+		next->tid  = SVAL(req->outbuf, smb_tid);
+		next->conn = conn_find(req->sconn, req->tid);
+		next->chain_fsp = req->chain_fsp;
+		next->inbuf = (uint8_t *)req->inbuf;
+
+		req = next;
+		req->conn = switch_message(req->cmd, req);
+
+		if (req->outbuf == NULL) {
+			/*
+			 * Request has suspended itself, will come
+			 * back here.
+			 */
+			return;
+		}
+		next_index += 1;
+	}
+
+	first_req = reqs[0];
+
+	for (i=1; i<next_index; i++) {
+		bool ok;
+
+		ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
+		if (!ok) {
+			status = NT_STATUS_INTERNAL_ERROR;
+			goto error;
+		}
+	}
+
+	SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
+	SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
+
+	/*
+	 * This scary statement intends to set the
+	 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
+	 * to the value last_req->outbuf carries
+	 */
+	SSVAL(first_req->outbuf, smb_flg2,
+	      (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
+	      |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
+
+	/*
+	 * Transfer the error codes from the subrequest to the main one
+	 */
+	SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
+	SSVAL(first_req->outbuf, smb_err,  SVAL(req->outbuf, smb_err));
+
+	_smb_setlen_large(
+		first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
+
+shipit:
+	if (!srv_send_smb(first_req->sconn,
+			  (char *)first_req->outbuf,
+			  true, first_req->seqnum+1,
+			  IS_CONN_ENCRYPTED(req->conn)||first_req->encrypted,
+			  &first_req->pcd)) {
+		exit_server_cleanly("construct_reply_chain: srv_send_smb "
+				    "failed.");
+	}
+	TALLOC_FREE(req);	/* non-chained case */
+	TALLOC_FREE(reqs);	/* chained case */
+	return;
+
+error:
+	{
+		char errbuf[smb_size];
+		error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
+		if (!srv_send_smb(req->sconn, errbuf, true,
+				  req->seqnum+1, req->encrypted,
+				  NULL)) {
+			exit_server_cleanly("construct_reply_chain: "
+					    "srv_send_smb failed.");
+		}
+	}
+	TALLOC_FREE(req);	/* non-chained case */
+	TALLOC_FREE(reqs);	/* chained case */
+}
+
 /****************************************************************************
  Process an smb from the client
 ****************************************************************************/
@@ -1623,8 +1774,14 @@ static void process_smb(struct smbd_server_connection *sconn,
 
 	show_msg((char *)inbuf);
 
-	construct_reply(sconn, (char *)inbuf, nread, unread_bytes, seqnum,
-			encrypted, deferred_pcd);
+	if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
+		construct_reply_chain(sconn, (char *)inbuf, nread,
+				      seqnum, encrypted, deferred_pcd);
+	} else {
+		construct_reply(sconn, (char *)inbuf, nread, unread_bytes,
+				seqnum,	encrypted, deferred_pcd);
+	}
+
 	sconn->trans_num++;
 
 done:
@@ -1702,40 +1859,6 @@ void construct_reply_common_req(struct smb_request *req, char *outbuf)
 	construct_reply_common(req, (const char *)req->inbuf, outbuf);
 }
 
-/*
- * How many bytes have we already accumulated up to the current wct field
- * offset?
- */
-
-size_t req_wct_ofs(struct smb_request *req)
-{
-	size_t buf_size;
-
-	if (req->chain_outbuf == NULL) {
-		return smb_wct - 4;
-	}
-	buf_size = talloc_get_size(req->chain_outbuf);
-	if ((buf_size % 4) != 0) {
-		buf_size += (4 - (buf_size % 4));
-	}
-	return buf_size - 4;
-}
-
-/*
- * Hack around reply_nterror & friends not being aware of chained requests,
- * generating illegal (i.e. wct==0) chain replies.
- */
-
-static void fixup_chain_error_packet(struct smb_request *req)
-{
-	uint8_t *outbuf = req->outbuf;
-	req->outbuf = NULL;
-	reply_outbuf(req, 2, 0);
-	memcpy(req->outbuf, outbuf, smb_wct);
-	TALLOC_FREE(outbuf);
-	SCVAL(req->outbuf, smb_vwv0, 0xff);
-}
-
 /**
  * @brief Find the smb_cmd offset of the last command pushed
  * @param[in] buf	The buffer we're building up
@@ -1862,6 +1985,38 @@ static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
 	 */
 
 	memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
+
+	/*
+	 * HACK ALERT
+	 *
+	 * Read&X has an offset into its data buffer at
+	 * vwv[6]. reply_read_andx has no idea anymore that it's
+	 * running from within a chain, so we have to fix up the
+	 * offset here.
+	 *
+	 * Although it looks disgusting at this place, I want to keep
+	 * it here. The alternative would be to push knowledge about
+	 * the andx chain down into read&x again.
+	 */
+
+	if (smb_command == SMBreadX) {
+		uint8_t *bytes_addr;
+
+		if (wct < 7) {
+			/*
+			 * Invalid read&x response
+			 */
+			return false;
+		}
+
+		bytes_addr = outbuf + ofs	 /* vwv start */
+			+ sizeof(uint16_t) * wct /* vwv array */
+			+ sizeof(uint16_t);	 /* bcc */
+
+		SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
+		      bytes_addr - outbuf - 4);
+	}
+
 	ofs += sizeof(uint16_t) * wct;
 
 	/*
@@ -1880,257 +2035,244 @@ static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
 	return true;
 }
 
-/****************************************************************************
- Construct a chained reply and add it to the already made reply
-****************************************************************************/
-


-- 
Samba Shared Repository


More information about the samba-cvs mailing list