1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 /*
  17  * Dispatch function for SMB2_QUERY_INFO
  18  */
  19 
  20 #include <smbsrv/smb2_kproto.h>
  21 #include <smbsrv/smb_fsops.h>
  22 #include <smbsrv/ntifs.h>
  23 
  24 smb_sdrc_t
  25 smb2_query_info(smb_request_t *sr)
  26 {
  27         smb_queryinfo_t *qi;
  28         uint16_t StructSize;
  29         uint32_t oBufLength;
  30         uint16_t iBufOffset;
  31         uint32_t iBufLength;
  32         smb2fid_t smb2fid;
  33         uint16_t DataOff;
  34         uint32_t status;
  35         smb_sdrc_t sdrc = SDRC_SUCCESS;
  36         int rc = 0;
  37 
  38         qi = kmem_zalloc(sizeof (*qi), KM_SLEEP);
  39 
  40         /*
  41          * SMB2 Query Info request
  42          */
  43         rc = smb_mbc_decodef(
  44             &sr->smb_data, "wbblw..lllqq",
  45             &StructSize,            /* w */
  46             &qi->qi_InfoType,            /* b */
  47             &qi->qi_InfoClass,           /* b */
  48             &oBufLength,            /* l */
  49             &iBufOffset,            /* w */
  50             /* reserved                   .. */
  51             &iBufLength,            /* l */
  52             &qi->qi_AddlInfo,            /* l */
  53             &qi->qi_Flags,               /* l */
  54             &smb2fid.persistent,    /* q */
  55             &smb2fid.temporal);             /* q */
  56         if (rc || StructSize != 41) {
  57                 sdrc = SDRC_ERROR;
  58                 goto out;
  59         }
  60 
  61         status = smb2sr_lookup_fid(sr, &smb2fid);
  62         if (status) {
  63                 smb2sr_put_error(sr, status);
  64                 goto out;
  65         }
  66 
  67         if (oBufLength > smb2_max_trans)
  68                 oBufLength = smb2_max_trans;
  69 
  70         /*
  71          * If there's an input buffer, setup a shadow.
  72          */
  73         if (iBufLength) {
  74                 rc = MBC_SHADOW_CHAIN(&qi->in_data, &sr->smb_data,
  75                     sr->smb2_cmd_hdr + iBufOffset, iBufLength);
  76                 if (rc) {
  77                         smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER);
  78                         goto out;
  79                 }
  80         }
  81 
  82         sr->raw_data.max_bytes = oBufLength;
  83 
  84         switch (qi->qi_InfoType) {
  85         case SMB2_0_INFO_FILE:
  86                 status = smb2_qinfo_file(sr, qi);
  87                 break;
  88         case SMB2_0_INFO_FILESYSTEM:
  89                 status = smb2_qinfo_fs(sr, qi);
  90                 break;
  91         case SMB2_0_INFO_SECURITY:
  92                 status = smb2_qinfo_sec(sr, qi);
  93                 break;
  94         case SMB2_0_INFO_QUOTA:
  95                 status = smb2_qinfo_quota(sr, qi);
  96                 break;
  97         default:
  98                 status = NT_STATUS_INVALID_PARAMETER;
  99                 break;
 100         }
 101 
 102         switch (status) {
 103 
 104         case 0: /* success */
 105                 break;
 106 
 107         case NT_STATUS_BUFFER_OVERFLOW:
 108                 /* Not really an error, per se.  Advisory. */
 109                 sr->smb2_status = status;
 110                 break;
 111 
 112         case NT_STATUS_BUFFER_TOO_SMALL:
 113         case NT_STATUS_INFO_LENGTH_MISMATCH:
 114                 /*
 115                  * These are special, per. [MS-SMB2] 3.2.5.17
 116                  * The error data is a 4-byte count of the size
 117                  * required to successfully query the data.
 118                  * That error data is built by the functions
 119                  * that returns one of these errors.
 120                  */
 121                 smb2sr_put_error_data(sr, status, &sr->raw_data);
 122                 goto out;
 123 
 124         default:
 125                 smb2sr_put_error(sr, status);
 126                 goto out;
 127         }
 128 
 129         /*
 130          * SMB2 Query Info reply
 131          */
 132         DataOff = SMB2_HDR_SIZE + 8;
 133         oBufLength = MBC_LENGTH(&sr->raw_data);
 134         rc = smb_mbc_encodef(
 135             &sr->reply, "wwlC",
 136             9,  /* StructSize */        /* w */
 137             DataOff,                    /* w */
 138             oBufLength,                 /* l */
 139             &sr->raw_data);              /* C */
 140         if (rc)
 141                 sdrc = SDRC_ERROR;
 142 
 143 out:
 144         kmem_free(qi, sizeof (*qi));
 145 
 146         return (sdrc);
 147 }