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 2017 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 /* 17 * Copyright 2020 RackTop Systems, Inc. 18 */ 19 20 /* 21 * Dispatch function for SMB2_QUERY_INFO 22 */ 23 24 #include <smbsrv/smb2_kproto.h> 25 #include <smbsrv/smb_fsops.h> 26 #include <smbsrv/ntifs.h> 27 28 smb_sdrc_t 29 smb2_query_info(smb_request_t *sr) 30 { 31 smb_queryinfo_t *qi; 32 uint16_t StructSize; 33 uint32_t oBufLength; 34 uint16_t iBufOffset; 35 uint32_t iBufLength; 36 smb2fid_t smb2fid; 37 uint16_t DataOff; 38 uint32_t status; 39 int rc = 0; 40 41 qi = smb_srm_zalloc(sr, sizeof (*qi)); 42 43 /* 44 * SMB2 Query Info request 45 */ 46 rc = smb_mbc_decodef( 47 &sr->smb_data, "wbblw..lllqq", 48 &StructSize, /* w */ 49 &qi->qi_InfoType, /* b */ 50 &qi->qi_InfoClass, /* b */ 51 &oBufLength, /* l */ 52 &iBufOffset, /* w */ 53 /* reserved .. */ 54 &iBufLength, /* l */ 55 &qi->qi_AddlInfo, /* l */ 56 &qi->qi_Flags, /* l */ 57 &smb2fid.persistent, /* q */ 58 &smb2fid.temporal); /* q */ 59 if (rc || StructSize != 41) 60 return (SDRC_ERROR); 61 62 /* 63 * If there's an input buffer, setup a shadow. 64 */ 65 if (iBufLength) { 66 rc = MBC_SHADOW_CHAIN(&qi->in_data, &sr->smb_data, 67 sr->smb2_cmd_hdr + iBufOffset, iBufLength); 68 if (rc) { 69 return (SDRC_ERROR); 70 } 71 } 72 73 if (oBufLength > smb2_max_trans) 74 oBufLength = smb2_max_trans; 75 sr->raw_data.max_bytes = oBufLength; 76 77 status = smb2sr_lookup_fid(sr, &smb2fid); 78 DTRACE_SMB2_START(op__QueryInfo, smb_request_t *, sr); 79 80 if (status) 81 goto errout; 82 83 switch (qi->qi_InfoType) { 84 case SMB2_0_INFO_FILE: 85 status = smb2_qinfo_file(sr, qi); 86 break; 87 case SMB2_0_INFO_FILESYSTEM: 88 status = smb2_qinfo_fs(sr, qi); 89 break; 90 case SMB2_0_INFO_SECURITY: 91 status = smb2_qinfo_sec(sr, qi); 92 break; 93 case SMB2_0_INFO_QUOTA: 94 status = smb2_qinfo_quota(sr, qi); 95 break; 96 default: 97 status = NT_STATUS_INVALID_PARAMETER; 98 break; 99 } 100 101 errout: 102 sr->smb2_status = status; 103 DTRACE_SMB2_DONE(op__QueryInfo, smb_request_t *, sr); 104 105 switch (status) { 106 107 case 0: /* success */ 108 break; 109 110 case NT_STATUS_BUFFER_OVERFLOW: 111 /* Not really an error, per se. Advisory. */ 112 break; 113 114 case NT_STATUS_BUFFER_TOO_SMALL: /* only in smb2_qinfo_sec.c */ 115 /* 116 * [MS-SMB2] 3.3.5.20.3 117 * Handling SMB2_0_INFO_SECURITY 118 * If dialect 3.1.1 must return 4-byte value 119 * containing required buffer size. 120 * ByteCount==12, ErrorContextCount==1, 121 * ErrorData: ErrorDataLength==4,ErrorId==0 122 * ErrorContextData==<buffer size> 123 * Otherwise ByteCount==4 124 * 125 * When returning with data, 3.1.1 encapsulate. 126 */ 127 if (sr->session->dialect < SMB_VERS_3_11) { 128 smb2sr_put_error_data(sr, status, &sr->raw_data); 129 } else { 130 smb2sr_put_error_ctx0(sr, status, &sr->raw_data); 131 } 132 return (SDRC_SUCCESS); 133 134 case NT_STATUS_INFO_LENGTH_MISMATCH: /* there is no in smb2_qinfo_*.c */ 135 /* 136 * [MS-SMB2] 3.3.5.20.1 137 * SMB 3.1.1 Handling SMB2_0_INFO_FILE 138 * [MS-SMB2] 3.3.5.20.2 139 * SMB 3.1.1 Handling SMB2_0_INFO_FILESYSTEM 140 * 141 * ByteCount==8, ErrorContextCount==1, 142 * ErrorData: ErrorDataLength==0,ErrorId==0 143 * Otherwise ByteCount==0 144 */ 145 if (sr->session->dialect < SMB_VERS_3_11) { 146 smb2sr_put_error_data(sr, status, NULL); 147 } else { 148 smb2sr_put_error_ctx0(sr, status, NULL); 149 } 150 return (SDRC_SUCCESS); 151 152 default: 153 smb2sr_put_error(sr, status); 154 return (SDRC_SUCCESS); 155 } 156 157 /* 158 * SMB2 Query Info reply 159 */ 160 DataOff = SMB2_HDR_SIZE + 8; 161 oBufLength = MBC_LENGTH(&sr->raw_data); 162 rc = smb_mbc_encodef( 163 &sr->reply, "wwlC", 164 9, /* StructSize */ /* w */ 165 DataOff, /* w */ 166 oBufLength, /* l */ 167 &sr->raw_data); /* C */ 168 if (rc) 169 sr->smb2_status = NT_STATUS_INTERNAL_ERROR; 170 171 return (SDRC_SUCCESS); 172 } 173