[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha7-2200-ga18341d

Stefan Metzmacher metze at samba.org
Tue Jun 9 17:54:03 GMT 2009


The branch, master has been updated
       via  a18341dab955dc0ffce6e787de1798f8665c1d92 (commit)
       via  66acfbffeb60cff811e32ddc54f44f63d96bf890 (commit)
       via  4ae8bf09e66094f794cab9e04226d9b26575006b (commit)
       via  3d220f9fce20b5b847c189446766e9bd25726e6c (commit)
       via  c8b3030f4042eb0b5f57415ad23d99d0cb28460e (commit)
       via  c0b64051d3dd715b9fc6192e758695e4202bbb5a (commit)
       via  915892e0daddf69a0d8f6f7dd682d7e5b13f28b3 (commit)
       via  6c44cc11b98c0165007af87cd98525404e573835 (commit)
      from  7c58a2f23734f8931cb822f71277cac7bb7ffe35 (commit)

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


- Log -----------------------------------------------------------------
commit a18341dab955dc0ffce6e787de1798f8665c1d92
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 9 19:48:08 2009 +0200

    s3:smbd: only check the next_status for related requests
    
    metze

commit 66acfbffeb60cff811e32ddc54f44f63d96bf890
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 9 19:46:29 2009 +0200

    s3:smbd: response with the same SMB2 flags as given by the client
    
    ...but also add the response flag.
    
    metze

commit 4ae8bf09e66094f794cab9e04226d9b26575006b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 9 19:31:15 2009 +0200

    s3:smbd: only pass the chained file handle for related compounded SMB2 requests
    
    metze

commit 3d220f9fce20b5b847c189446766e9bd25726e6c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 9 19:21:26 2009 +0200

    s3:smbd: make sure we pad compounded SMB2 responses to 8 bytes
    
    metze

commit c8b3030f4042eb0b5f57415ad23d99d0cb28460e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 9 18:47:26 2009 +0200

    s3:smbd: skip file handle checks for SMB2 compounded requests
    
    metze

commit c0b64051d3dd715b9fc6192e758695e4202bbb5a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 8 13:30:32 2009 +0200

    s3:smbd: more validation of the incoming SMB2 requests
    
    metze

commit 915892e0daddf69a0d8f6f7dd682d7e5b13f28b3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Jun 8 13:15:00 2009 +0200

    s3:smbd: for now ignore all non NBT Session Message requests for SMB2
    
    metze

commit 6c44cc11b98c0165007af87cd98525404e573835
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 9 17:06:40 2009 +0200

    s3:smbd: don't include 1 byte padding for the dynamic buffer of SMB2 responses
    
    It seems that Windows 2008 and Windows 7 doesn't do this anymore.
    
    metze

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

Summary of changes:
 source3/smbd/globals.h     |    2 +
 source3/smbd/smb2_close.c  |    4 +-
 source3/smbd/smb2_flush.c  |    4 +-
 source3/smbd/smb2_ioctl.c  |    6 +-
 source3/smbd/smb2_read.c   |    4 +-
 source3/smbd/smb2_server.c |  196 +++++++++++++++++++++++++++++++++++++------
 source3/smbd/smb2_write.c  |    4 +-
 7 files changed, 186 insertions(+), 34 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 581e5b1..f002a6f 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -229,6 +229,8 @@ struct smbd_smb2_request {
 
 	struct files_struct *compat_chain_fsp;
 
+	NTSTATUS next_status;
+
 	struct {
 		/* the NBT header is not allocated */
 		uint8_t nbt_hdr[4];
diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c
index a600498..6724e5c 100644
--- a/source3/smbd/smb2_close.c
+++ b/source3/smbd/smb2_close.c
@@ -56,7 +56,9 @@ NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
 	in_file_id_persistent	= BVAL(inbody, 0x08);
 	in_file_id_volatile	= BVAL(inbody, 0x10);
 
-	if (in_file_id_persistent != 0) {
+	if (req->compat_chain_fsp) {
+		/* skip check */
+	} else if (in_file_id_persistent != 0) {
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c
index 37a8309..ce560a1 100644
--- a/source3/smbd/smb2_flush.c
+++ b/source3/smbd/smb2_flush.c
@@ -55,7 +55,9 @@ NTSTATUS smbd_smb2_request_process_flush(struct smbd_smb2_request *req)
 	in_file_id_persistent	= BVAL(inbody, 0x08);
 	in_file_id_volatile	= BVAL(inbody, 0x10);
 
-	if (in_file_id_persistent != 0) {
+	if (req->compat_chain_fsp) {
+		/* skip check */
+	} else if (in_file_id_persistent != 0) {
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c
index 9ff6c8e..a1f2885 100644
--- a/source3/smbd/smb2_ioctl.c
+++ b/source3/smbd/smb2_ioctl.c
@@ -83,8 +83,10 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
 	in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
 	in_input_buffer.length = in_input_length;
 
-	if (in_file_id_persistent == UINT64_MAX &&
-	    in_file_id_volatile == UINT64_MAX) {
+	if (req->compat_chain_fsp) {
+		/* skip check */
+	} else if (in_file_id_persistent == UINT64_MAX &&
+		   in_file_id_volatile == UINT64_MAX) {
 		/* without a handle */
 	} else if (in_file_id_persistent != 0) {
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c
index ae6b0f4..5890ca6 100644
--- a/source3/smbd/smb2_read.c
+++ b/source3/smbd/smb2_read.c
@@ -81,7 +81,9 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
-	if (in_file_id_persistent != 0) {
+	if (req->compat_chain_fsp) {
+		/* skip check */
+	} else if (in_file_id_persistent != 0) {
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 0413832..101ccc9 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -186,6 +186,79 @@ static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *conn,
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
+{
+	int count;
+	int idx;
+	bool compound_related = false;
+
+	count = req->in.vector_count;
+
+	if (count < 4) {
+		/* It's not a SMB2 request */
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	for (idx=1; idx < count; idx += 3) {
+		const uint8_t *inhdr = NULL;
+		uint32_t flags;
+
+		if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		if (req->in.vector[idx+1].iov_len < 2) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
+
+		/* setup the SMB2 header */
+		if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
+			return NT_STATUS_INVALID_PARAMETER;
+		}
+
+		flags = IVAL(inhdr, SMB2_HDR_FLAGS);
+		if (idx == 1) {
+			/*
+			 * the 1st request should never have the
+			 * SMB2_HDR_FLAG_CHAINED flag set
+			 */
+			if (flags & SMB2_HDR_FLAG_CHAINED) {
+				req->next_status = NT_STATUS_INVALID_PARAMETER;
+				return NT_STATUS_OK;
+			}
+		} else if (idx == 4) {
+			/*
+			 * the 2nd request triggers related vs. unrelated
+			 * compounded requests
+			 */
+			if (flags & SMB2_HDR_FLAG_CHAINED) {
+				compound_related = true;
+			}
+		} else if (idx > 4) {
+			/*
+			 * all other requests should match the 2nd one
+			 */
+			if (flags & SMB2_HDR_FLAG_CHAINED) {
+				if (!compound_related) {
+					req->next_status =
+						NT_STATUS_INVALID_PARAMETER;
+					return NT_STATUS_OK;
+				}
+			} else {
+				if (compound_related) {
+					req->next_status =
+						NT_STATUS_INVALID_PARAMETER;
+					return NT_STATUS_OK;
+				}
+			}
+		}
+	}
+
+	return NT_STATUS_OK;
+}
+
 static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 {
 	struct iovec *vector;
@@ -204,29 +277,27 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 
 	for (idx=1; idx < count; idx += 3) {
 		const uint8_t *inhdr = NULL;
+		uint32_t in_flags;
 		uint8_t *outhdr = NULL;
 		uint8_t *outbody = NULL;
-		uint8_t *outdyn = NULL;
-		size_t outdyn_size = 1;
 		uint32_t next_command_ofs = 0;
 		struct iovec *current = &vector[idx];
 
 		if ((idx + 3) < count) {
 			/* we have a next command */
-			next_command_ofs = SMB2_HDR_BODY + 8 + 8;
-			outdyn_size = 8;
+			next_command_ofs = SMB2_HDR_BODY + 8;
 		}
 
 		inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
+		in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
 
 		outhdr = talloc_array(vector, uint8_t,
-				      SMB2_HDR_BODY + 8 + outdyn_size);
+				      SMB2_HDR_BODY + 8);
 		if (outhdr == NULL) {
 			return NT_STATUS_NO_MEMORY;
 		}
 
 		outbody = outhdr + SMB2_HDR_BODY;
-		outdyn = outbody + 8;
 
 		current[0].iov_base	= (void *)outhdr;
 		current[0].iov_len	= SMB2_HDR_BODY;
@@ -234,8 +305,8 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 		current[1].iov_base	= (void *)outbody;
 		current[1].iov_len	= 8;
 
-		current[2].iov_base	= (void *)outdyn;
-		current[2].iov_len	= outdyn_size;
+		current[2].iov_base	= NULL;
+		current[2].iov_len	= 0;
 
 		/* setup the SMB2 header */
 		SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID,	SMB2_MAGIC);
@@ -247,7 +318,8 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 		      SVAL(inhdr, SMB2_HDR_OPCODE));
 		/* Make up a number for now... JRA. FIXME ! FIXME !*/
 		SSVAL(outhdr, SMB2_HDR_CREDIT,		20);
-		SIVAL(outhdr, SMB2_HDR_FLAGS,		SMB2_HDR_FLAG_REDIRECT);
+		SIVAL(outhdr, SMB2_HDR_FLAGS,
+		      IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
 		SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND,	next_command_ofs);
 		SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
 		      BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
@@ -260,12 +332,9 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 		memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
 
 		/* setup error body header */
-		SSVAL(outbody, 0x00, 9);
+		SSVAL(outbody, 0x00, 0x08 + 1);
 		SSVAL(outbody, 0x02, 0);
 		SIVAL(outbody, 0x04, 0);
-
-		/* setup the dynamic part */
-		SCVAL(outdyn, 0x00, 0);
 	}
 
 	req->out.vector = vector;
@@ -330,6 +399,21 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
 	}
 
+	if (flags & SMB2_HDR_FLAG_CHAINED) {
+		/*
+		 * This check is mostly for giving the correct error code
+		 * for compounded requests.
+		 *
+		 * TODO: we may need to move this after the session
+		 *       and tcon checks.
+		 */
+		if (!NT_STATUS_IS_OK(req->next_status)) {
+			return smbd_smb2_request_error(req, req->next_status);
+		}
+	} else {
+		req->compat_chain_fsp = NULL;
+	}
+
 	switch (opcode) {
 	case SMB2_OP_NEGPROT:
 		return smbd_smb2_request_process_negprot(req);
@@ -612,13 +696,15 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
 		req->out.vector[i+2].iov_base	= (void *)info->data;
 		req->out.vector[i+2].iov_len	= info->length;
 	} else {
-		req->out.vector[i+2].iov_base = (void *)(outbody + 8);
-		req->out.vector[i+2].iov_len = 1;
+		req->out.vector[i+2].iov_base = NULL;
+		req->out.vector[i+2].iov_len = 0;
 	}
 
-	/* the error packet is the last response in the chain */
-	SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, 0);
-	req->out.vector_count = req->current_idx + 3;
+	/*
+	 * if a request fails, all other remaining
+	 * compounded requests should fail too
+	 */
+	req->next_status = NT_STATUS_INVALID_PARAMETER;
 
 	return smbd_smb2_request_reply(req);
 }
@@ -659,12 +745,8 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
 	req->out.vector[i+1].iov_len = body.length;
 
 	if (dyn) {
-		if (dyn->length > 0) {
-			req->out.vector[i+2].iov_base	= (void *)dyn->data;
-			req->out.vector[i+2].iov_len	= dyn->length;
-		} else {
-			/* the dyn section is already initialized */
-		}
+		req->out.vector[i+2].iov_base	= (void *)dyn->data;
+		req->out.vector[i+2].iov_len	= dyn->length;
 	} else {
 		req->out.vector[i+2].iov_base = NULL;
 		req->out.vector[i+2].iov_len = 0;
@@ -677,12 +759,56 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
 		next_command_ofs += req->out.vector[i+2].iov_len;
 	}
 
-	/* TODO: we need to add padding ... */
 	if ((next_command_ofs % 8) != 0) {
-		return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
+		size_t pad_size = 8 - (next_command_ofs % 8);
+		if (req->out.vector[i+2].iov_len == 0) {
+			/*
+			 * if the dyn buffer is empty
+			 * we can use it to add padding
+			 */
+			uint8_t *pad;
+
+			pad = talloc_zero_array(req->out.vector,
+						uint8_t, pad_size);
+			if (pad == NULL) {
+				return smbd_smb2_request_error(req,
+						NT_STATUS_NO_MEMORY);
+			}
+
+			req->out.vector[i+2].iov_base = (void *)pad;
+			req->out.vector[i+2].iov_len = pad_size;
+		} else {
+			/*
+			 * For now we copy the dynamic buffer
+			 * and add the padding to the new buffer
+			 */
+			size_t old_size;
+			uint8_t *old_dyn;
+			size_t new_size;
+			uint8_t *new_dyn;
+
+			old_size = req->out.vector[i+2].iov_len;
+			old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
+
+			new_size = old_size + pad_size;
+			new_dyn = talloc_array(req->out.vector,
+					       uint8_t, new_size);
+			if (new_dyn == NULL) {
+				return smbd_smb2_request_error(req,
+						NT_STATUS_NO_MEMORY);
+			}
+
+			memcpy(new_dyn, old_dyn, old_size);
+			memset(new_dyn + old_size, 0, pad_size);
+
+			req->out.vector[i+2].iov_base = (void *)new_dyn;
+			req->out.vector[i+2].iov_len = new_size;
+
+			TALLOC_FREE(old_dyn);
+		}
+		next_command_ofs += pad_size;
 	}
 
-	/* the error packet is the last response in the chain */
 	SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
 
 	return smbd_smb2_request_reply(req);
@@ -1119,12 +1245,25 @@ static void smbd_smb2_request_incoming(struct tevent_req *subreq)
 		return;
 	}
 
-	/* TODO: validate the incoming request */
+	if (req->in.nbt_hdr[0] != 0x00) {
+		DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
+			 req->in.nbt_hdr[0]));
+		talloc_free(req->mem_pool);
+		req = NULL;
+		goto next;
+	}
+
 	req->current_idx = 1;
 
 	DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
 		 req->current_idx, req->in.vector_count));
 
+	status = smbd_smb2_request_validate(req);
+	if (!NT_STATUS_IS_OK(status)) {
+		smbd_server_connection_terminate(conn, nt_errstr(status));
+		return;
+	}
+
 	status = smbd_smb2_request_setup_out(req);
 	if (!NT_STATUS_IS_OK(status)) {
 		smbd_server_connection_terminate(conn, nt_errstr(status));
@@ -1137,6 +1276,7 @@ static void smbd_smb2_request_incoming(struct tevent_req *subreq)
 		return;
 	}
 
+next:
 	/* ask for the next request (this constructs the main loop) */
 	subreq = smbd_smb2_request_read_send(conn,conn->smb2.event_ctx, conn);
 	if (subreq == NULL) {
diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c
index 43a312a..ccfe3b3 100644
--- a/source3/smbd/smb2_write.c
+++ b/source3/smbd/smb2_write.c
@@ -90,7 +90,9 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req)
 	in_data_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
 	in_data_buffer.length = in_data_length;
 
-	if (in_file_id_persistent != 0) {
+	if (req->compat_chain_fsp) {
+		/* skip check */
+	} else if (in_file_id_persistent != 0) {
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list