[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