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 <[email protected]>
Date:   Tue May 29 14:08:43 2012 +0200

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

commit 8b4e6777206d7df4174f9d61830d1c337a46089f
Author: Stefan Metzmacher <[email protected]>
Date:   Tue May 29 13:25:31 2012 +0200

    s3:smb2_ioctl: add more validation checks
    
    metze

commit 4ac57a3c965603684c55dbc6b02d882331d85ede
Author: Stefan Metzmacher <[email protected]>
Date:   Tue May 29 12:06:22 2012 +0200

    s3:smb2_ioctl: add some more validation checks
    
    Based on a patch from Christian Ambach <[email protected]>.
    
    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

Reply via email to