[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Tue May 29 10:56:04 MDT 2012


The branch, master has been updated
       via  cee146f s3:smb2_ioctl: verify credit charge
       via  8b4e677 s3:smb2_ioctl: add more validation checks
       via  4ac57a3 s3:smb2_ioctl: add some more validation checks
      from  c17f981 s4-torture: verify #8373 and add ndr nbt tests for LOGON_PRIMARY_QUERY nbt_netlogon_requests.

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


- Log -----------------------------------------------------------------
commit cee146ff7c2250d3c723f19357fd1c8541191d08
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue May 29 14:08:43 2012 +0200

    s3:smb2_ioctl: verify credit charge
    
    Based on a patch from Christian Ambach <ambi at samba.org>.
    
    metze
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Tue May 29 18:55:29 CEST 2012 on sn-devel-104

commit 8b4e6777206d7df4174f9d61830d1c337a46089f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue May 29 13:25:31 2012 +0200

    s3:smb2_ioctl: add more validation checks
    
    metze

commit 4ac57a3c965603684c55dbc6b02d882331d85ede
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue May 29 12:06:22 2012 +0200

    s3:smb2_ioctl: add some more validation checks
    
    Based on a patch from Christian Ambach <ambi at samba.org>.
    
    metze

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

Summary of changes:
 source3/smbd/smb2_ioctl.c |  141 ++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 128 insertions(+), 13 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c
index cd303ed..0d17407 100644
--- a/source3/smbd/smb2_ioctl.c
+++ b/source3/smbd/smb2_ioctl.c
@@ -46,14 +46,27 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
 	NTSTATUS status;
 	const uint8_t *inbody;
 	int i = req->current_idx;
+	uint32_t min_buffer_offset;
+	uint32_t max_buffer_offset;
+	uint32_t min_output_offset;
+	uint32_t allowed_length_in;
+	uint32_t allowed_length_out;
 	uint32_t in_ctl_code;
 	uint64_t in_file_id_persistent;
 	uint64_t in_file_id_volatile;
 	uint32_t in_input_offset;
 	uint32_t in_input_length;
-	DATA_BLOB in_input_buffer;
+	DATA_BLOB in_input_buffer = data_blob_null;
+	uint32_t in_max_input_length;
+	uint32_t in_output_offset;
+	uint32_t in_output_length;
+	DATA_BLOB in_output_buffer = data_blob_null;
 	uint32_t in_max_output_length;
 	uint32_t in_flags;
+	uint32_t data_length_in;
+	uint32_t data_length_out;
+	uint32_t data_length_tmp;
+	uint32_t data_length_max;
 	struct tevent_req *subreq;
 
 	status = smbd_smb2_request_verify_sizes(req, 0x39);
@@ -67,9 +80,16 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
 	in_file_id_volatile	= BVAL(inbody, 0x10);
 	in_input_offset		= IVAL(inbody, 0x18);
 	in_input_length		= IVAL(inbody, 0x1C);
+	in_max_input_length	= IVAL(inbody, 0x20);
+	in_output_offset	= IVAL(inbody, 0x24);
+	in_output_length	= IVAL(inbody, 0x28);
 	in_max_output_length	= IVAL(inbody, 0x2C);
 	in_flags		= IVAL(inbody, 0x30);
 
+	min_buffer_offset = SMB2_HDR_BODY + req->in.vector[i+1].iov_len;
+	max_buffer_offset = min_buffer_offset + req->in.vector[i+2].iov_len;
+	min_output_offset = min_buffer_offset;
+
 	/*
 	 * InputOffset (4 bytes): The offset, in bytes, from the beginning of
 	 * the SMB2 header to the input data buffer. If no input data is
@@ -78,25 +98,120 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
 	 * <49> If no input data is required for the FSCTL/IOCTL command being
 	 * issued, Windows-based clients set this field to any value.
 	 */
-	if ((in_input_length > 0)
-	 && (in_input_offset != (SMB2_HDR_BODY + req->in.vector[i+1].iov_len))) {
+	allowed_length_in = 0;
+	if ((in_input_offset > 0) && (in_input_length > 0)) {
+		uint32_t tmp_ofs;
+
+		if (in_input_offset < min_buffer_offset) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+		if (in_input_offset > max_buffer_offset) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+		allowed_length_in = max_buffer_offset - in_input_offset;
+
+		tmp_ofs = in_input_offset - min_buffer_offset;
+		in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
+		in_input_buffer.data += tmp_ofs;
+		in_input_buffer.length = in_input_length;
+		min_output_offset += tmp_ofs;
+		min_output_offset += in_input_length;
+	}
+
+	if (in_input_length > allowed_length_in) {
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
-	if (in_input_length > req->in.vector[i+2].iov_len) {
+	allowed_length_out = 0;
+	if (in_output_offset > 0) {
+		if (in_output_offset < min_buffer_offset) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+		if (in_output_offset > max_buffer_offset) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+		allowed_length_out = max_buffer_offset - in_output_offset;
+	}
+
+	if (in_output_length > allowed_length_out) {
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
-	in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
-	in_input_buffer.length = in_input_length;
+	if (in_output_length > 0) {
+		uint32_t tmp_ofs;
 
-	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 != in_file_id_volatile) {
-		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+		if (in_output_offset < min_output_offset) {
+			return smbd_smb2_request_error(req,
+					NT_STATUS_INVALID_PARAMETER);
+		}
+
+		tmp_ofs = in_output_offset - min_buffer_offset;
+		in_output_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
+		in_output_buffer.data += tmp_ofs;
+		in_output_buffer.length = in_output_length;
+	}
+
+	/*
+	 * verify the credits and avoid overflows
+	 * in_input_buffer.length and in_output_buffer.length
+	 * are already verified.
+	 */
+	data_length_in = in_input_buffer.length + in_output_buffer.length;
+
+	data_length_out = in_max_input_length;
+	data_length_tmp = UINT32_MAX - data_length_out;
+	if (data_length_tmp < in_max_output_length) {
+		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+	}
+	data_length_out += in_max_output_length;
+
+	data_length_max = MAX(data_length_in, data_length_out);
+
+	status = smbd_smb2_request_verify_creditcharge(req, data_length_max);
+	if (!NT_STATUS_IS_OK(status)) {
+		return smbd_smb2_request_error(req, status);
+	}
+
+	/*
+	 * If the Flags field of the request is not SMB2_0_IOCTL_IS_FSCTL the
+	 * server MUST fail the request with STATUS_NOT_SUPPORTED.
+	 */
+	if (in_flags != SMB2_IOCTL_FLAG_IS_FSCTL) {
+		return smbd_smb2_request_error(req, NT_STATUS_NOT_SUPPORTED);
+	}
+
+	switch (in_ctl_code) {
+	case FSCTL_DFS_GET_REFERRALS:
+	case FSCTL_DFS_GET_REFERRALS_EX:
+	case FSCTL_PIPE_WAIT:
+	case FSCTL_VALIDATE_NEGOTIATE_INFO_224:
+	case FSCTL_VALIDATE_NEGOTIATE_INFO:
+	case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
+		/*
+		 * Some SMB2 specific CtlCodes like FSCTL_DFS_GET_REFERRALS or
+		 * FSCTL_PIPE_WAIT does not take a file handle.
+		 *
+		 * If FileId in the SMB2 Header of the request is not
+		 * 0xFFFFFFFFFFFFFFFF, then the server MUST fail the request
+		 * with STATUS_INVALID_PARAMETER.
+		 */
+		if (in_file_id_persistent != UINT64_MAX ||
+		    in_file_id_volatile != UINT64_MAX) {
+			return smbd_smb2_request_error(req,
+				NT_STATUS_INVALID_PARAMETER);
+		}
+		break;
+	default:
+		if (req->compat_chain_fsp) {
+			/* skip check */
+		} else if (in_file_id_persistent != in_file_id_volatile) {
+			return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+		}
+		break;
 	}
 
 	subreq = smbd_smb2_ioctl_send(req,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list