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