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
smb2_query_info(smb_request_t * sr)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