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 2019 Nexenta by DDN, Inc. All rights reserved.
14 * Copyright 2022 RackTop Systems, Inc.
15 */
16
17 /*
18 * Dispatch function for SMB2_SET_INFO
19 *
20 * [MS-FSCC 2.4] If a file system does not support ...
21 * an Information Classs, NT_STATUS_INVALID_PARAMETER...
22 */
23
24 #include <smbsrv/smb2_kproto.h>
25 #include <smbsrv/smb_fsops.h>
26 #include <smbsrv/ntifs.h>
27
28 static uint32_t smb2_setf_rename(smb_request_t *, smb_setinfo_t *);
29 static uint32_t smb2_setf_link(smb_request_t *, smb_setinfo_t *);
30
31 static uint32_t smb2_setf_seek(smb_request_t *, smb_setinfo_t *);
32 static uint32_t smb2_setf_full_ea(smb_request_t *, smb_setinfo_t *);
33 static uint32_t smb2_setf_mode(smb_request_t *, smb_setinfo_t *);
34
35 static uint32_t smb2_setf_pipe(smb_request_t *, smb_setinfo_t *);
36 static uint32_t smb2_setf_valid_len(smb_request_t *, smb_setinfo_t *);
37 static uint32_t smb2_setf_shortname(smb_request_t *, smb_setinfo_t *);
38
39
40 uint32_t
smb2_setinfo_file(smb_request_t * sr,smb_setinfo_t * si,int InfoClass)41 smb2_setinfo_file(smb_request_t *sr, smb_setinfo_t *si, int InfoClass)
42 {
43 smb_ofile_t *of = sr->fid_ofile;
44 uint32_t status;
45
46 si->si_node = of->f_node;
47
48 /* Most info levels need a disk file */
49 switch (of->f_ftype) {
50 case SMB_FTYPE_DISK:
51 case SMB_FTYPE_PRINTER:
52 break;
53 case SMB_FTYPE_BYTE_PIPE:
54 case SMB_FTYPE_MESG_PIPE:
55 if (InfoClass != FilePipeInformation)
56 return (NT_STATUS_INVALID_PARAMETER);
57 break;
58 default:
59 return (NT_STATUS_INTERNAL_ERROR);
60 break;
61 }
62
63 switch (InfoClass) {
64 case FileBasicInformation: /* 4 */
65 status = smb_set_basic_info(sr, si);
66 break;
67 case FileRenameInformation: /* 10 */
68 status = smb2_setf_rename(sr, si);
69 break;
70 case FileLinkInformation: /* 11 */
71 status = smb2_setf_link(sr, si);
72 break;
73 case FileDispositionInformation: /* 13 */
74 status = smb_set_disposition_info(sr, si);
75 break;
76 case FilePositionInformation: /* 14 */
77 status = smb2_setf_seek(sr, si);
78 break;
79 case FileFullEaInformation: /* 15 */
80 status = smb2_setf_full_ea(sr, si);
81 break;
82 case FileModeInformation: /* 16 */
83 status = smb2_setf_mode(sr, si);
84 break;
85 case FileAllocationInformation: /* 19 */
86 status = smb_set_alloc_info(sr, si);
87 break;
88 case FileEndOfFileInformation: /* 20 */
89 status = smb_set_eof_info(sr, si);
90 break;
91 case FilePipeInformation: /* 23 */
92 status = smb2_setf_pipe(sr, si);
93 break;
94 case FileValidDataLengthInformation: /* 39 */
95 status = smb2_setf_valid_len(sr, si);
96 break;
97 case FileShortNameInformation: /* 40 */
98 status = smb2_setf_shortname(sr, si);
99 break;
100 default:
101 status = NT_STATUS_INVALID_INFO_CLASS;
102 break;
103 }
104
105 return (status);
106 }
107
108
109 /*
110 * FileRenameInformation
111 * See also: smb_set_rename_info()
112 */
113 static uint32_t
smb2_setf_rename(smb_request_t * sr,smb_setinfo_t * si)114 smb2_setf_rename(smb_request_t *sr, smb_setinfo_t *si)
115 {
116 char *fname;
117 uint8_t flags;
118 uint64_t rootdir;
119 uint32_t namelen;
120 uint32_t status = 0;
121 int rc;
122
123 rc = smb_mbc_decodef(&si->si_data, "b7.ql",
124 &flags, &rootdir, &namelen);
125 if (rc == 0) {
126 rc = smb_mbc_decodef(&si->si_data, "%#U",
127 sr, namelen, &fname);
128 }
129 if (rc != 0)
130 return (NT_STATUS_INFO_LENGTH_MISMATCH);
131
132 if ((rootdir != 0) || (namelen == 0) || (namelen >= SMB_MAXPATHLEN)) {
133 return (NT_STATUS_INVALID_PARAMETER);
134 }
135
136 status = smb_setinfo_rename(sr, si->si_node, fname, flags);
137
138 return (status);
139 }
140
141 /*
142 * FileLinkInformation
143 */
144 static uint32_t
smb2_setf_link(smb_request_t * sr,smb_setinfo_t * si)145 smb2_setf_link(smb_request_t *sr, smb_setinfo_t *si)
146 {
147 char *fname;
148 uint8_t flags;
149 uint64_t rootdir;
150 uint32_t namelen;
151 uint32_t status = 0;
152 int rc;
153
154 rc = smb_mbc_decodef(&si->si_data, "b7.ql",
155 &flags, &rootdir, &namelen);
156 if (rc == 0) {
157 rc = smb_mbc_decodef(&si->si_data, "%#U",
158 sr, namelen, &fname);
159 }
160 if (rc != 0)
161 return (NT_STATUS_INFO_LENGTH_MISMATCH);
162
163 if ((rootdir != 0) || (namelen == 0) || (namelen >= SMB_MAXPATHLEN)) {
164 return (NT_STATUS_INVALID_PARAMETER);
165 }
166
167 status = smb_setinfo_link(sr, si->si_node, fname, flags);
168
169 return (status);
170 }
171
172
173 /*
174 * FilePositionInformation
175 */
176 static uint32_t
smb2_setf_seek(smb_request_t * sr,smb_setinfo_t * si)177 smb2_setf_seek(smb_request_t *sr, smb_setinfo_t *si)
178 {
179 smb_ofile_t *of = sr->fid_ofile;
180 uint64_t newoff;
181
182 if (smb_mbc_decodef(&si->si_data, "q", &newoff) != 0)
183 return (NT_STATUS_INFO_LENGTH_MISMATCH);
184
185 ASSERT(of->f_magic == SMB_OFILE_MAGIC);
186 mutex_enter(&of->f_mutex);
187 of->f_seek_pos = newoff;
188 mutex_exit(&of->f_mutex);
189
190 return (0);
191 }
192
193 /*
194 * FileFullEaInformation
195 * We could put EAs in a named stream...
196 */
197 /* ARGSUSED */
198 static uint32_t
smb2_setf_full_ea(smb_request_t * sr,smb_setinfo_t * si)199 smb2_setf_full_ea(smb_request_t *sr, smb_setinfo_t *si)
200 {
201 return (NT_STATUS_EAS_NOT_SUPPORTED);
202 }
203
204 /*
205 * FileModeInformation [MS-FSCC 2.4.24]
206 * FILE_WRITE_THROUGH
207 * FILE_SEQUENTIAL_ONLY
208 * FILE_NO_INTERMEDIATE_BUFFERING
209 * etc.
210 */
211 static uint32_t
smb2_setf_mode(smb_request_t * sr,smb_setinfo_t * si)212 smb2_setf_mode(smb_request_t *sr, smb_setinfo_t *si)
213 {
214 _NOTE(ARGUNUSED(sr))
215 uint32_t Mode;
216
217 if (smb_mbc_decodef(&si->si_data, "l", &Mode) != 0)
218 return (NT_STATUS_INFO_LENGTH_MISMATCH);
219
220 #if 0 /* XXX - todo */
221 if (Mode & FILE_WRITE_THROUGH) {
222 /* store this in the ofile */
223 }
224 #endif
225
226 return (NT_STATUS_SUCCESS);
227 }
228
229
230
231 /*
232 * FilePipeInformation
233 */
234 static uint32_t
smb2_setf_pipe(smb_request_t * sr,smb_setinfo_t * si)235 smb2_setf_pipe(smb_request_t *sr, smb_setinfo_t *si)
236 {
237 _NOTE(ARGUNUSED(si))
238 smb_ofile_t *of = sr->fid_ofile;
239 uint32_t ReadMode;
240 uint32_t CompletionMode;
241 uint32_t status;
242
243 if (smb_mbc_decodef(&si->si_data, "ll",
244 &ReadMode, &CompletionMode) != 0)
245 return (NT_STATUS_INFO_LENGTH_MISMATCH);
246
247 switch (of->f_ftype) {
248 case SMB_FTYPE_BYTE_PIPE:
249 case SMB_FTYPE_MESG_PIPE:
250 /*
251 * XXX: Do we need to actually do anything with
252 * ReadMode or CompletionMode? If so, (later)
253 * store these in the opipe object.
254 *
255 * See also: smb2_sif_pipe()
256 */
257 status = 0;
258 break;
259 case SMB_FTYPE_DISK:
260 case SMB_FTYPE_PRINTER:
261 default:
262 status = NT_STATUS_INVALID_PARAMETER;
263 }
264
265 return (status);
266 }
267
268 /*
269 * FileValidDataLengthInformation
270 */
271 /* ARGSUSED */
272 static uint32_t
smb2_setf_valid_len(smb_request_t * sr,smb_setinfo_t * si)273 smb2_setf_valid_len(smb_request_t *sr, smb_setinfo_t *si)
274 {
275 smb_ofile_t *of = sr->fid_ofile;
276 uint64_t eod;
277 int rc;
278
279 if (smb_mbc_decodef(&si->si_data, "q", &eod) != 0)
280 return (NT_STATUS_INFO_LENGTH_MISMATCH);
281
282 /*
283 * Zero out data from EoD to end of file.
284 * (Passing len=0 covers to end of file)
285 */
286 rc = smb_fsop_freesp(sr, of->f_cr, of, eod, 0);
287 if (rc != 0)
288 return (smb_errno2status(rc));
289
290 return (0);
291 }
292
293 /*
294 * FileShortNameInformation
295 * We can (optionally) support supply short names,
296 * but you can't change them.
297 */
298 static uint32_t
smb2_setf_shortname(smb_request_t * sr,smb_setinfo_t * si)299 smb2_setf_shortname(smb_request_t *sr, smb_setinfo_t *si)
300 {
301 _NOTE(ARGUNUSED(si))
302 smb_ofile_t *of = sr->fid_ofile;
303
304 if (of->f_ftype != SMB_FTYPE_DISK)
305 return (NT_STATUS_INVALID_PARAMETER);
306 if ((of->f_tree->t_flags & SMB_TREE_SHORTNAMES) == 0)
307 return (NT_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME);
308
309 return (NT_STATUS_ACCESS_DENIED);
310 }
311