1e3f2c991SKeyur Desai /*
2e3f2c991SKeyur Desai  * CDDL HEADER START
3e3f2c991SKeyur Desai  *
4e3f2c991SKeyur Desai  * The contents of this file are subject to the terms of the
5e3f2c991SKeyur Desai  * Common Development and Distribution License (the "License").
6e3f2c991SKeyur Desai  * You may not use this file except in compliance with the License.
7e3f2c991SKeyur Desai  *
8e3f2c991SKeyur Desai  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e3f2c991SKeyur Desai  * or http://www.opensolaris.org/os/licensing.
10e3f2c991SKeyur Desai  * See the License for the specific language governing permissions
11e3f2c991SKeyur Desai  * and limitations under the License.
12e3f2c991SKeyur Desai  *
13e3f2c991SKeyur Desai  * When distributing Covered Code, include this CDDL HEADER in each
14e3f2c991SKeyur Desai  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e3f2c991SKeyur Desai  * If applicable, add the following below this CDDL HEADER, with the
16e3f2c991SKeyur Desai  * fields enclosed by brackets "[]" replaced with your own identifying
17e3f2c991SKeyur Desai  * information: Portions Copyright [yyyy] [name of copyright owner]
18e3f2c991SKeyur Desai  *
19e3f2c991SKeyur Desai  * CDDL HEADER END
20e3f2c991SKeyur Desai  */
21e3f2c991SKeyur Desai /*
22cb174861Sjoyce mcintosh  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*2dbda4a2SGordon Ross  * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
24e3f2c991SKeyur Desai  */
25e3f2c991SKeyur Desai 
26e3f2c991SKeyur Desai /*
27e3f2c991SKeyur Desai  * Trans2 Set File/Path Information Levels:
28e3f2c991SKeyur Desai  *
29e3f2c991SKeyur Desai  * SMB_INFO_STANDARD
30e3f2c991SKeyur Desai  * SMB_INFO_SET_EAS
31e3f2c991SKeyur Desai  * SMB_SET_FILE_BASIC_INFO
32e3f2c991SKeyur Desai  * SMB_SET_FILE_DISPOSITION_INFO
33e3f2c991SKeyur Desai  * SMB_SET_FILE_END_OF_FILE_INFO
34e3f2c991SKeyur Desai  * SMB_SET_FILE_ALLOCATION_INFO
35e3f2c991SKeyur Desai  *
36bbf6f00cSJordan Brown  * Handled Passthrough levels:
37e3f2c991SKeyur Desai  * SMB_FILE_BASIC_INFORMATION
38bbf6f00cSJordan Brown  * SMB_FILE_RENAME_INFORMATION
39bbf6f00cSJordan Brown  * SMB_FILE_LINK_INFORMATION
40e3f2c991SKeyur Desai  * SMB_FILE_DISPOSITION_INFORMATION
41e3f2c991SKeyur Desai  * SMB_FILE_END_OF_FILE_INFORMATION
42e3f2c991SKeyur Desai  * SMB_FILE_ALLOCATION_INFORMATION
43e3f2c991SKeyur Desai  *
44e3f2c991SKeyur Desai  * Internal levels representing non trans2 requests
45e3f2c991SKeyur Desai  * SMB_SET_INFORMATION
46e3f2c991SKeyur Desai  * SMB_SET_INFORMATION2
47e3f2c991SKeyur Desai  */
48e3f2c991SKeyur Desai 
49e3f2c991SKeyur Desai /*
50e3f2c991SKeyur Desai  * Setting timestamps:
51e3f2c991SKeyur Desai  * The behaviour when the time field is set to -1 is not documented
52e3f2c991SKeyur Desai  * but is generally treated like 0, meaning that that server file
53e3f2c991SKeyur Desai  * system assigned value need not be changed.
54e3f2c991SKeyur Desai  *
55e3f2c991SKeyur Desai  * Setting attributes - FILE_ATTRIBUTE_NORMAL:
56e3f2c991SKeyur Desai  * SMB_SET_INFORMATION -
57e3f2c991SKeyur Desai  * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set
58e3f2c991SKeyur Desai  *   do NOT change the file's attributes.
59e3f2c991SKeyur Desai  * SMB_SET_BASIC_INFO -
60e3f2c991SKeyur Desai  * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set
61e3f2c991SKeyur Desai  *   clear (0) the file's attributes.
62e3f2c991SKeyur Desai  * - if the specified attributes are 0 do NOT change the file's
63e3f2c991SKeyur Desai  *   attributes.
64e3f2c991SKeyur Desai  */
65e3f2c991SKeyur Desai 
66bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
67e3f2c991SKeyur Desai #include <smbsrv/smb_fsops.h>
68e3f2c991SKeyur Desai 
69a90cf9f2SGordon Ross static int smb_set_by_fid(smb_request_t *, smb_xa_t *, uint16_t);
70a90cf9f2SGordon Ross static int smb_set_by_path(smb_request_t *, smb_xa_t *, uint16_t);
71e3f2c991SKeyur Desai 
72e3f2c991SKeyur Desai /*
73a90cf9f2SGordon Ross  * These functions all return and NT status code.
74e3f2c991SKeyur Desai  */
75a90cf9f2SGordon Ross static uint32_t smb_set_fileinfo(smb_request_t *, smb_setinfo_t *, int);
76a90cf9f2SGordon Ross static uint32_t smb_set_information(smb_request_t *, smb_setinfo_t *);
77a90cf9f2SGordon Ross static uint32_t smb_set_information2(smb_request_t *, smb_setinfo_t *);
78a90cf9f2SGordon Ross static uint32_t smb_set_standard_info(smb_request_t *, smb_setinfo_t *);
79a90cf9f2SGordon Ross static uint32_t smb_set_rename_info(smb_request_t *sr, smb_setinfo_t *);
80e3f2c991SKeyur Desai 
81e3f2c991SKeyur Desai /*
82e3f2c991SKeyur Desai  * smb_com_trans2_set_file_information
83e3f2c991SKeyur Desai  */
84e3f2c991SKeyur Desai smb_sdrc_t
smb_com_trans2_set_file_information(smb_request_t * sr,smb_xa_t * xa)85e3f2c991SKeyur Desai smb_com_trans2_set_file_information(smb_request_t *sr, smb_xa_t *xa)
86e3f2c991SKeyur Desai {
87e3f2c991SKeyur Desai 	uint16_t infolev;
88e3f2c991SKeyur Desai 
89e3f2c991SKeyur Desai 	if (smb_mbc_decodef(&xa->req_param_mb, "ww",
90e3f2c991SKeyur Desai 	    &sr->smb_fid, &infolev) != 0)
91e3f2c991SKeyur Desai 		return (SDRC_ERROR);
92e3f2c991SKeyur Desai 
93e3f2c991SKeyur Desai 	if (smb_set_by_fid(sr, xa, infolev) != 0)
94e3f2c991SKeyur Desai 		return (SDRC_ERROR);
95e3f2c991SKeyur Desai 
96e3f2c991SKeyur Desai 	return (SDRC_SUCCESS);
97e3f2c991SKeyur Desai }
98e3f2c991SKeyur Desai 
99e3f2c991SKeyur Desai /*
100e3f2c991SKeyur Desai  * smb_com_trans2_set_path_information
101e3f2c991SKeyur Desai  */
102e3f2c991SKeyur Desai smb_sdrc_t
smb_com_trans2_set_path_information(smb_request_t * sr,smb_xa_t * xa)103e3f2c991SKeyur Desai smb_com_trans2_set_path_information(smb_request_t *sr, smb_xa_t *xa)
104e3f2c991SKeyur Desai {
1059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	uint16_t	infolev;
1069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_fqi_t	*fqi = &sr->arg.dirop.fqi;
107e3f2c991SKeyur Desai 
108f96bd5c8SAlan Wright 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
109e3f2c991SKeyur Desai 		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
110e3f2c991SKeyur Desai 		    ERRDOS, ERROR_INVALID_FUNCTION);
111e3f2c991SKeyur Desai 		return (SDRC_ERROR);
112e3f2c991SKeyur Desai 	}
113e3f2c991SKeyur Desai 
114e3f2c991SKeyur Desai 	if (smb_mbc_decodef(&xa->req_param_mb, "%w4.u",
1159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    sr, &infolev, &fqi->fq_path.pn_path) != 0)
116e3f2c991SKeyur Desai 		return (SDRC_ERROR);
117e3f2c991SKeyur Desai 
1189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smb_set_by_path(sr, xa, infolev) != 0)
119e3f2c991SKeyur Desai 		return (SDRC_ERROR);
120e3f2c991SKeyur Desai 
121e3f2c991SKeyur Desai 	return (SDRC_SUCCESS);
122e3f2c991SKeyur Desai }
123e3f2c991SKeyur Desai 
124e3f2c991SKeyur Desai /*
125e3f2c991SKeyur Desai  * smb_com_set_information (aka setattr)
126e3f2c991SKeyur Desai  */
127e3f2c991SKeyur Desai smb_sdrc_t
smb_pre_set_information(smb_request_t * sr)128e3f2c991SKeyur Desai smb_pre_set_information(smb_request_t *sr)
129e3f2c991SKeyur Desai {
13093bc28dbSGordon Ross 	DTRACE_SMB_START(op__SetInformation, smb_request_t *, sr);
131e3f2c991SKeyur Desai 	return (SDRC_SUCCESS);
132e3f2c991SKeyur Desai }
133e3f2c991SKeyur Desai 
134e3f2c991SKeyur Desai void
smb_post_set_information(smb_request_t * sr)135e3f2c991SKeyur Desai smb_post_set_information(smb_request_t *sr)
136e3f2c991SKeyur Desai {
13793bc28dbSGordon Ross 	DTRACE_SMB_DONE(op__SetInformation, smb_request_t *, sr);
138e3f2c991SKeyur Desai }
139e3f2c991SKeyur Desai 
140e3f2c991SKeyur Desai smb_sdrc_t
smb_com_set_information(smb_request_t * sr)141e3f2c991SKeyur Desai smb_com_set_information(smb_request_t *sr)
142e3f2c991SKeyur Desai {
1439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	uint16_t	infolev = SMB_SET_INFORMATION;
1449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_fqi_t	*fqi = &sr->arg.dirop.fqi;
145e3f2c991SKeyur Desai 
146f96bd5c8SAlan Wright 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
147e3f2c991SKeyur Desai 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
148e3f2c991SKeyur Desai 		    ERRDOS, ERROR_ACCESS_DENIED);
149e3f2c991SKeyur Desai 		return (SDRC_ERROR);
150e3f2c991SKeyur Desai 	}
151e3f2c991SKeyur Desai 
1529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path) != 0)
153e3f2c991SKeyur Desai 		return (SDRC_ERROR);
154e3f2c991SKeyur Desai 
1559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smb_set_by_path(sr, NULL, infolev) != 0)
156e3f2c991SKeyur Desai 		return (SDRC_ERROR);
157e3f2c991SKeyur Desai 
158e3f2c991SKeyur Desai 	if (smbsr_encode_empty_result(sr) != 0)
159e3f2c991SKeyur Desai 		return (SDRC_ERROR);
160e3f2c991SKeyur Desai 
161e3f2c991SKeyur Desai 	return (SDRC_SUCCESS);
162e3f2c991SKeyur Desai }
163e3f2c991SKeyur Desai 
164e3f2c991SKeyur Desai /*
165e3f2c991SKeyur Desai  * smb_com_set_information2 (aka setattre)
166e3f2c991SKeyur Desai  */
167e3f2c991SKeyur Desai smb_sdrc_t
smb_pre_set_information2(smb_request_t * sr)168e3f2c991SKeyur Desai smb_pre_set_information2(smb_request_t *sr)
169e3f2c991SKeyur Desai {
17093bc28dbSGordon Ross 	DTRACE_SMB_START(op__SetInformation2, smb_request_t *, sr);
171e3f2c991SKeyur Desai 	return (SDRC_SUCCESS);
172e3f2c991SKeyur Desai }
173e3f2c991SKeyur Desai 
174e3f2c991SKeyur Desai void
smb_post_set_information2(smb_request_t * sr)175e3f2c991SKeyur Desai smb_post_set_information2(smb_request_t *sr)
176e3f2c991SKeyur Desai {
17793bc28dbSGordon Ross 	DTRACE_SMB_DONE(op__SetInformation2, smb_request_t *, sr);
178e3f2c991SKeyur Desai }
179e3f2c991SKeyur Desai 
180e3f2c991SKeyur Desai smb_sdrc_t
smb_com_set_information2(smb_request_t * sr)181e3f2c991SKeyur Desai smb_com_set_information2(smb_request_t *sr)
182e3f2c991SKeyur Desai {
183e3f2c991SKeyur Desai 	uint16_t infolev = SMB_SET_INFORMATION2;
184e3f2c991SKeyur Desai 
185e3f2c991SKeyur Desai 	if (smbsr_decode_vwv(sr, "w", &sr->smb_fid) != 0)
186e3f2c991SKeyur Desai 		return (SDRC_ERROR);
187e3f2c991SKeyur Desai 
188e3f2c991SKeyur Desai 	if (smb_set_by_fid(sr, NULL, infolev) != 0)
189e3f2c991SKeyur Desai 		return (SDRC_ERROR);
190e3f2c991SKeyur Desai 
191e3f2c991SKeyur Desai 	if (smbsr_encode_empty_result(sr) != 0)
192e3f2c991SKeyur Desai 		return (SDRC_ERROR);
193e3f2c991SKeyur Desai 
194e3f2c991SKeyur Desai 	return (SDRC_SUCCESS);
195e3f2c991SKeyur Desai }
196e3f2c991SKeyur Desai 
197e3f2c991SKeyur Desai /*
198e3f2c991SKeyur Desai  * smb_set_by_fid
199e3f2c991SKeyur Desai  *
200e3f2c991SKeyur Desai  * Common code for setting file information by open file id.
201e3f2c991SKeyur Desai  * Use the id to identify the node object and invoke smb_set_fileinfo
202e3f2c991SKeyur Desai  * for that node.
203e3f2c991SKeyur Desai  *
204e3f2c991SKeyur Desai  * Setting attributes on a named pipe by id is handled by simply
205e3f2c991SKeyur Desai  * returning success.
206e3f2c991SKeyur Desai  */
207e3f2c991SKeyur Desai static int
smb_set_by_fid(smb_request_t * sr,smb_xa_t * xa,uint16_t infolev)208e3f2c991SKeyur Desai smb_set_by_fid(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
209e3f2c991SKeyur Desai {
210e3f2c991SKeyur Desai 	smb_setinfo_t sinfo;
211a90cf9f2SGordon Ross 	uint32_t status;
212a90cf9f2SGordon Ross 	int rc = 0;
213e3f2c991SKeyur Desai 
214e3f2c991SKeyur Desai 	if (SMB_TREE_IS_READONLY(sr)) {
215e3f2c991SKeyur Desai 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
216e3f2c991SKeyur Desai 		    ERRDOS, ERROR_ACCESS_DENIED);
217e3f2c991SKeyur Desai 		return (-1);
218e3f2c991SKeyur Desai 	}
219e3f2c991SKeyur Desai 
220f96bd5c8SAlan Wright 	if (STYPE_ISIPC(sr->tid_tree->t_res_type))
221e3f2c991SKeyur Desai 		return (0);
222e3f2c991SKeyur Desai 
223e3f2c991SKeyur Desai 	smbsr_lookup_file(sr);
224e3f2c991SKeyur Desai 	if (sr->fid_ofile == NULL) {
225e3f2c991SKeyur Desai 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
226e3f2c991SKeyur Desai 		return (-1);
227e3f2c991SKeyur Desai 	}
228e3f2c991SKeyur Desai 
229e3f2c991SKeyur Desai 	if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
230e3f2c991SKeyur Desai 		smbsr_release_file(sr);
231e3f2c991SKeyur Desai 		return (0);
232e3f2c991SKeyur Desai 	}
233e3f2c991SKeyur Desai 
234e3f2c991SKeyur Desai 	sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
235e3f2c991SKeyur Desai 
236a90cf9f2SGordon Ross 	bzero(&sinfo, sizeof (sinfo));
237e3f2c991SKeyur Desai 	sinfo.si_node = sr->fid_ofile->f_node;
238a90cf9f2SGordon Ross 	if (xa != NULL)
239a90cf9f2SGordon Ross 		sinfo.si_data = xa->req_data_mb;
240a90cf9f2SGordon Ross 	status = smb_set_fileinfo(sr, &sinfo, infolev);
241a90cf9f2SGordon Ross 	if (status != 0) {
242a90cf9f2SGordon Ross 		smbsr_error(sr, status, 0, 0);
243a90cf9f2SGordon Ross 		rc = -1;
244a90cf9f2SGordon Ross 	}
245e3f2c991SKeyur Desai 
246e3f2c991SKeyur Desai 	smbsr_release_file(sr);
247e3f2c991SKeyur Desai 	return (rc);
248e3f2c991SKeyur Desai }
249e3f2c991SKeyur Desai 
250e3f2c991SKeyur Desai /*
251e3f2c991SKeyur Desai  * smb_set_by_path
252e3f2c991SKeyur Desai  *
253e3f2c991SKeyur Desai  * Common code for setting file information by file name.
254e3f2c991SKeyur Desai  * Use the file name to identify the node object and invoke
255e3f2c991SKeyur Desai  * smb_set_fileinfo for that node.
256e3f2c991SKeyur Desai  *
2579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Path should be set in sr->arg.dirop.fqi.fq_path prior to
2589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * calling smb_set_by_path.
2599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
260e3f2c991SKeyur Desai  * Setting attributes on a named pipe by name is an error and
261e3f2c991SKeyur Desai  * is handled in the calling functions so that they can return
262e3f2c991SKeyur Desai  * the appropriate error status code (which differs by caller).
263e3f2c991SKeyur Desai  */
264e3f2c991SKeyur Desai static int
smb_set_by_path(smb_request_t * sr,smb_xa_t * xa,uint16_t infolev)2659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_set_by_path(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
266e3f2c991SKeyur Desai {
267e3f2c991SKeyur Desai 	int rc;
268a90cf9f2SGordon Ross 	uint32_t status;
269e3f2c991SKeyur Desai 	smb_setinfo_t sinfo;
270e3f2c991SKeyur Desai 	smb_node_t *node, *dnode;
271e3f2c991SKeyur Desai 	char *name;
2729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_pathname_t	*pn;
273e3f2c991SKeyur Desai 
274e3f2c991SKeyur Desai 	if (SMB_TREE_IS_READONLY(sr)) {
275e3f2c991SKeyur Desai 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
276e3f2c991SKeyur Desai 		    ERRDOS, ERROR_ACCESS_DENIED);
277e3f2c991SKeyur Desai 		return (-1);
278e3f2c991SKeyur Desai 	}
279e3f2c991SKeyur Desai 
280*2dbda4a2SGordon Ross 	if (STYPE_ISIPC(sr->tid_tree->t_res_type))
281*2dbda4a2SGordon Ross 		return (0);
282*2dbda4a2SGordon Ross 
2839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	pn = &sr->arg.dirop.fqi.fq_path;
2849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_pathname_init(sr, pn, pn->pn_path);
2859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (!smb_pathname_validate(sr, pn))
2869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (-1);
2879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
288e3f2c991SKeyur Desai 	name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
2899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
290e3f2c991SKeyur Desai 	    sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode, name);
291e3f2c991SKeyur Desai 	if (rc == 0) {
292e3f2c991SKeyur Desai 		rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS,
293e3f2c991SKeyur Desai 		    sr->tid_tree->t_snode, dnode, name, &node);
294e3f2c991SKeyur Desai 		smb_node_release(dnode);
295e3f2c991SKeyur Desai 	}
296e3f2c991SKeyur Desai 	kmem_free(name, MAXNAMELEN);
297e3f2c991SKeyur Desai 
298e3f2c991SKeyur Desai 	if (rc != 0) {
299d2488fe8SGordon Ross 		smbsr_errno(sr, rc);
300e3f2c991SKeyur Desai 		return (-1);
301e3f2c991SKeyur Desai 	}
302e3f2c991SKeyur Desai 
303a90cf9f2SGordon Ross 	bzero(&sinfo, sizeof (sinfo));
304e3f2c991SKeyur Desai 	sinfo.si_node = node;
305a90cf9f2SGordon Ross 	if (xa != NULL)
306a90cf9f2SGordon Ross 		sinfo.si_data = xa->req_data_mb;
307a90cf9f2SGordon Ross 	status = smb_set_fileinfo(sr, &sinfo, infolev);
308a90cf9f2SGordon Ross 	if (status != 0) {
309a90cf9f2SGordon Ross 		smbsr_error(sr, status, 0, 0);
310a90cf9f2SGordon Ross 		rc = -1;
311a90cf9f2SGordon Ross 	}
312e3f2c991SKeyur Desai 
313e3f2c991SKeyur Desai 	smb_node_release(node);
314e3f2c991SKeyur Desai 	return (rc);
315e3f2c991SKeyur Desai }
316e3f2c991SKeyur Desai 
317e3f2c991SKeyur Desai /*
318e3f2c991SKeyur Desai  * smb_set_fileinfo
319bbf6f00cSJordan Brown  *
320bbf6f00cSJordan Brown  * For compatibility with windows servers, SMB_FILE_LINK_INFORMATION
321bbf6f00cSJordan Brown  * is handled by returning NT_STATUS_NOT_SUPPORTED.
322e3f2c991SKeyur Desai  */
323a90cf9f2SGordon Ross static uint32_t
smb_set_fileinfo(smb_request_t * sr,smb_setinfo_t * sinfo,int infolev)324a90cf9f2SGordon Ross smb_set_fileinfo(smb_request_t *sr, smb_setinfo_t *sinfo, int infolev)
325e3f2c991SKeyur Desai {
326a90cf9f2SGordon Ross 	uint32_t status;
327a90cf9f2SGordon Ross 
328a90cf9f2SGordon Ross 	switch (infolev) {
329e3f2c991SKeyur Desai 	case SMB_SET_INFORMATION:
330a90cf9f2SGordon Ross 		status = smb_set_information(sr, sinfo);
331a90cf9f2SGordon Ross 		break;
332e3f2c991SKeyur Desai 
333e3f2c991SKeyur Desai 	case SMB_SET_INFORMATION2:
334a90cf9f2SGordon Ross 		status = smb_set_information2(sr, sinfo);
335a90cf9f2SGordon Ross 		break;
336e3f2c991SKeyur Desai 
337e3f2c991SKeyur Desai 	case SMB_INFO_STANDARD:
338a90cf9f2SGordon Ross 		status = smb_set_standard_info(sr, sinfo);
339a90cf9f2SGordon Ross 		break;
340e3f2c991SKeyur Desai 
341e3f2c991SKeyur Desai 	case SMB_INFO_SET_EAS:
3423bd40d98SGordon Ross 		status = NT_STATUS_EAS_NOT_SUPPORTED;
343a90cf9f2SGordon Ross 		break;
344e3f2c991SKeyur Desai 
345e3f2c991SKeyur Desai 	case SMB_SET_FILE_BASIC_INFO:
346e3f2c991SKeyur Desai 	case SMB_FILE_BASIC_INFORMATION:
347a90cf9f2SGordon Ross 		status = smb_set_basic_info(sr, sinfo);
348a90cf9f2SGordon Ross 		break;
349e3f2c991SKeyur Desai 
350e3f2c991SKeyur Desai 	case SMB_SET_FILE_DISPOSITION_INFO:
351e3f2c991SKeyur Desai 	case SMB_FILE_DISPOSITION_INFORMATION:
352a90cf9f2SGordon Ross 		status = smb_set_disposition_info(sr, sinfo);
353a90cf9f2SGordon Ross 		break;
354e3f2c991SKeyur Desai 
355e3f2c991SKeyur Desai 	case SMB_SET_FILE_END_OF_FILE_INFO:
356e3f2c991SKeyur Desai 	case SMB_FILE_END_OF_FILE_INFORMATION:
357a90cf9f2SGordon Ross 		status = smb_set_eof_info(sr, sinfo);
358a90cf9f2SGordon Ross 		break;
359e3f2c991SKeyur Desai 
360e3f2c991SKeyur Desai 	case SMB_SET_FILE_ALLOCATION_INFO:
361e3f2c991SKeyur Desai 	case SMB_FILE_ALLOCATION_INFORMATION:
362a90cf9f2SGordon Ross 		status = smb_set_alloc_info(sr, sinfo);
363a90cf9f2SGordon Ross 		break;
364e3f2c991SKeyur Desai 
365bbf6f00cSJordan Brown 	case SMB_FILE_RENAME_INFORMATION:
366a90cf9f2SGordon Ross 		status = smb_set_rename_info(sr, sinfo);
367a90cf9f2SGordon Ross 		break;
368bbf6f00cSJordan Brown 
369bbf6f00cSJordan Brown 	case SMB_FILE_LINK_INFORMATION:
370a90cf9f2SGordon Ross 		status = NT_STATUS_NOT_SUPPORTED;
371a90cf9f2SGordon Ross 		break;
372a90cf9f2SGordon Ross 
373e3f2c991SKeyur Desai 	default:
374a90cf9f2SGordon Ross 		status = NT_STATUS_INVALID_INFO_CLASS;
375e3f2c991SKeyur Desai 		break;
376e3f2c991SKeyur Desai 	}
377e3f2c991SKeyur Desai 
378a90cf9f2SGordon Ross 	return (status);
379e3f2c991SKeyur Desai }
380e3f2c991SKeyur Desai 
381e3f2c991SKeyur Desai /*
382e3f2c991SKeyur Desai  * smb_set_information
383e3f2c991SKeyur Desai  *
384e3f2c991SKeyur Desai  * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the
385e3f2c991SKeyur Desai  * target is not a directory.
386e3f2c991SKeyur Desai  *
387e3f2c991SKeyur Desai  * For compatibility with Windows Servers, if the specified
388e3f2c991SKeyur Desai  * attributes have ONLY FILE_ATTRIBUTE_NORMAL set do NOT change
389e3f2c991SKeyur Desai  * the file's attributes.
390e3f2c991SKeyur Desai  */
391a90cf9f2SGordon Ross static uint32_t
smb_set_information(smb_request_t * sr,smb_setinfo_t * sinfo)392e3f2c991SKeyur Desai smb_set_information(smb_request_t *sr, smb_setinfo_t *sinfo)
393e3f2c991SKeyur Desai {
394e3f2c991SKeyur Desai 	smb_attr_t attr;
395a90cf9f2SGordon Ross 	smb_node_t *node = sinfo->si_node;
396a90cf9f2SGordon Ross 	uint32_t status = 0;
397e3f2c991SKeyur Desai 	uint32_t mtime;
398a90cf9f2SGordon Ross 	uint16_t attributes;
399a90cf9f2SGordon Ross 	int rc;
400e3f2c991SKeyur Desai 
401e3f2c991SKeyur Desai 	if (smbsr_decode_vwv(sr, "wl10.", &attributes, &mtime) != 0)
402a90cf9f2SGordon Ross 		return (NT_STATUS_INFO_LENGTH_MISMATCH);
403e3f2c991SKeyur Desai 
404e3f2c991SKeyur Desai 	if ((attributes & FILE_ATTRIBUTE_DIRECTORY) &&
405e3f2c991SKeyur Desai 	    (!smb_node_is_dir(node))) {
406a90cf9f2SGordon Ross 		return (NT_STATUS_INVALID_PARAMETER);
407e3f2c991SKeyur Desai 	}
408e3f2c991SKeyur Desai 
409e3f2c991SKeyur Desai 	bzero(&attr, sizeof (smb_attr_t));
410e3f2c991SKeyur Desai 	if (attributes != FILE_ATTRIBUTE_NORMAL) {
411e3f2c991SKeyur Desai 		attr.sa_dosattr = attributes;
412e3f2c991SKeyur Desai 		attr.sa_mask |= SMB_AT_DOSATTR;
413e3f2c991SKeyur Desai 	}
414e3f2c991SKeyur Desai 
415e3f2c991SKeyur Desai 	if (mtime != 0 && mtime != UINT_MAX) {
416e3f2c991SKeyur Desai 		attr.sa_vattr.va_mtime.tv_sec =
417e3f2c991SKeyur Desai 		    smb_time_local_to_gmt(sr, mtime);
418e3f2c991SKeyur Desai 		attr.sa_mask |= SMB_AT_MTIME;
419e3f2c991SKeyur Desai 	}
420e3f2c991SKeyur Desai 
421e3f2c991SKeyur Desai 	rc = smb_node_setattr(sr, node, sr->user_cr, NULL, &attr);
422a90cf9f2SGordon Ross 	if (rc != 0)
423a90cf9f2SGordon Ross 		status = smb_errno2status(rc);
424e3f2c991SKeyur Desai 
425a90cf9f2SGordon Ross 	return (status);
426e3f2c991SKeyur Desai }
427e3f2c991SKeyur Desai 
428e3f2c991SKeyur Desai /*
429e3f2c991SKeyur Desai  * smb_set_information2
430e3f2c991SKeyur Desai  */
431a90cf9f2SGordon Ross static uint32_t
smb_set_information2(smb_request_t * sr,smb_setinfo_t * sinfo)432e3f2c991SKeyur Desai smb_set_information2(smb_request_t *sr, smb_setinfo_t *sinfo)
433e3f2c991SKeyur Desai {
434e3f2c991SKeyur Desai 	smb_attr_t attr;
435a90cf9f2SGordon Ross 	uint32_t crtime, atime, mtime;
436a90cf9f2SGordon Ross 	uint32_t status = 0;
437a90cf9f2SGordon Ross 	int rc;
438e3f2c991SKeyur Desai 
439e3f2c991SKeyur Desai 	if (smbsr_decode_vwv(sr, "yyy", &crtime, &atime, &mtime) != 0)
440a90cf9f2SGordon Ross 		return (NT_STATUS_INFO_LENGTH_MISMATCH);
441e3f2c991SKeyur Desai 
442e3f2c991SKeyur Desai 	bzero(&attr, sizeof (smb_attr_t));
443e3f2c991SKeyur Desai 	if (mtime != 0 && mtime != UINT_MAX) {
444e3f2c991SKeyur Desai 		attr.sa_vattr.va_mtime.tv_sec =
445e3f2c991SKeyur Desai 		    smb_time_local_to_gmt(sr, mtime);
446e3f2c991SKeyur Desai 		attr.sa_mask |= SMB_AT_MTIME;
447e3f2c991SKeyur Desai 	}
448e3f2c991SKeyur Desai 
449e3f2c991SKeyur Desai 	if (crtime != 0 && crtime != UINT_MAX) {
450e3f2c991SKeyur Desai 		attr.sa_crtime.tv_sec = smb_time_local_to_gmt(sr, crtime);
451e3f2c991SKeyur Desai 		attr.sa_mask |= SMB_AT_CRTIME;
452e3f2c991SKeyur Desai 	}
453e3f2c991SKeyur Desai 
454e3f2c991SKeyur Desai 	if (atime != 0 && atime != UINT_MAX) {
455e3f2c991SKeyur Desai 		attr.sa_vattr.va_atime.tv_sec =
456e3f2c991SKeyur Desai 		    smb_time_local_to_gmt(sr, atime);
457e3f2c991SKeyur Desai 		attr.sa_mask |= SMB_AT_ATIME;
458e3f2c991SKeyur Desai 	}
459e3f2c991SKeyur Desai 
460e3f2c991SKeyur Desai 	rc = smb_node_setattr(sr, sinfo->si_node, sr->user_cr,
461e3f2c991SKeyur Desai 	    sr->fid_ofile, &attr);
462a90cf9f2SGordon Ross 	if (rc != 0)
463a90cf9f2SGordon Ross 		status = smb_errno2status(rc);
464e3f2c991SKeyur Desai 
465a90cf9f2SGordon Ross 	return (status);
466e3f2c991SKeyur Desai }
467e3f2c991SKeyur Desai 
468e3f2c991SKeyur Desai /*
469e3f2c991SKeyur Desai  * smb_set_standard_info
470e3f2c991SKeyur Desai  *
471e3f2c991SKeyur Desai  * Sets standard file/path information.
472e3f2c991SKeyur Desai  */
473a90cf9f2SGordon Ross static uint32_t
smb_set_standard_info(smb_request_t * sr,smb_setinfo_t * sinfo)474e3f2c991SKeyur Desai smb_set_standard_info(smb_request_t *sr, smb_setinfo_t *sinfo)
475e3f2c991SKeyur Desai {
476e3f2c991SKeyur Desai 	smb_attr_t attr;
477e3f2c991SKeyur Desai 	smb_node_t *node = sinfo->si_node;
478a90cf9f2SGordon Ross 	uint32_t crtime, atime, mtime;
479a90cf9f2SGordon Ross 	uint32_t status = 0;
480e3f2c991SKeyur Desai 	int rc;
481e3f2c991SKeyur Desai 
482a90cf9f2SGordon Ross 	if (smb_mbc_decodef(&sinfo->si_data, "yyy",
483a90cf9f2SGordon Ross 	    &crtime, &atime, &mtime) != 0)
484a90cf9f2SGordon Ross 		return (NT_STATUS_INFO_LENGTH_MISMATCH);
485e3f2c991SKeyur Desai 
486e3f2c991SKeyur Desai 	bzero(&attr, sizeof (smb_attr_t));
487e3f2c991SKeyur Desai 	if (mtime != 0 && mtime != (uint32_t)-1) {
488e3f2c991SKeyur Desai 		attr.sa_vattr.va_mtime.tv_sec =
489e3f2c991SKeyur Desai 		    smb_time_local_to_gmt(sr, mtime);
490e3f2c991SKeyur Desai 		attr.sa_mask |= SMB_AT_MTIME;
491e3f2c991SKeyur Desai 	}
492e3f2c991SKeyur Desai 
493e3f2c991SKeyur Desai 	if (crtime != 0 && crtime != (uint32_t)-1) {
494e3f2c991SKeyur Desai 		attr.sa_crtime.tv_sec = smb_time_local_to_gmt(sr, crtime);
495e3f2c991SKeyur Desai 		attr.sa_mask |= SMB_AT_CRTIME;
496e3f2c991SKeyur Desai 	}
497e3f2c991SKeyur Desai 
498e3f2c991SKeyur Desai 	if (atime != 0 && atime != (uint32_t)-1) {
499e3f2c991SKeyur Desai 		attr.sa_vattr.va_atime.tv_sec =
500e3f2c991SKeyur Desai 		    smb_time_local_to_gmt(sr, atime);
501e3f2c991SKeyur Desai 		attr.sa_mask |= SMB_AT_ATIME;
502e3f2c991SKeyur Desai 	}
503e3f2c991SKeyur Desai 
504e3f2c991SKeyur Desai 	rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, &attr);
505a90cf9f2SGordon Ross 	if (rc != 0)
506a90cf9f2SGordon Ross 		status = smb_errno2status(rc);
507e3f2c991SKeyur Desai 
508a90cf9f2SGordon Ross 	return (status);
509e3f2c991SKeyur Desai }
510bbf6f00cSJordan Brown 
511bbf6f00cSJordan Brown /*
512bbf6f00cSJordan Brown  * smb_set_rename_info
513bbf6f00cSJordan Brown  *
514a90cf9f2SGordon Ross  * This call only allows a rename in the same directory, and the
515a90cf9f2SGordon Ross  * directory name is not part of the new name provided.
516a90cf9f2SGordon Ross  *
517cb174861Sjoyce mcintosh  * Explicitly specified parameter validation rules:
518bbf6f00cSJordan Brown  * - If rootdir is not NULL respond with NT_STATUS_INVALID_PARAMETER.
519bbf6f00cSJordan Brown  * - If the filename contains a separator character respond with
520bbf6f00cSJordan Brown  *   NT_STATUS_INVALID_PARAMETER.
521cb174861Sjoyce mcintosh  *
522cb174861Sjoyce mcintosh  * Oplock break:
523cb174861Sjoyce mcintosh  * Some Windows servers break BATCH oplocks prior to the rename.
524cb174861Sjoyce mcintosh  * W2K3 does not. We behave as W2K3; we do not send an oplock break.
525bbf6f00cSJordan Brown  */
526a90cf9f2SGordon Ross static uint32_t
smb_set_rename_info(smb_request_t * sr,smb_setinfo_t * sinfo)527bbf6f00cSJordan Brown smb_set_rename_info(smb_request_t *sr, smb_setinfo_t *sinfo)
528bbf6f00cSJordan Brown {
529a90cf9f2SGordon Ross 	smb_fqi_t *src_fqi = &sr->arg.dirop.fqi;
530a90cf9f2SGordon Ross 	smb_fqi_t *dst_fqi = &sr->arg.dirop.dst_fqi;
531bbf6f00cSJordan Brown 	char *fname;
532a90cf9f2SGordon Ross 	char *path;
533a90cf9f2SGordon Ross 	uint8_t flags;
534a90cf9f2SGordon Ross 	uint32_t rootdir, namelen;
535a90cf9f2SGordon Ross 	uint32_t status = 0;
536a90cf9f2SGordon Ross 	int rc;
537bbf6f00cSJordan Brown 
538a90cf9f2SGordon Ross 	rc = smb_mbc_decodef(&sinfo->si_data, "b...ll",
539bbf6f00cSJordan Brown 	    &flags, &rootdir, &namelen);
540bbf6f00cSJordan Brown 	if (rc == 0) {
541a90cf9f2SGordon Ross 		rc = smb_mbc_decodef(&sinfo->si_data, "%#U",
542bbf6f00cSJordan Brown 		    sr, namelen, &fname);
543bbf6f00cSJordan Brown 	}
544bbf6f00cSJordan Brown 	if (rc != 0)
545a90cf9f2SGordon Ross 		return (NT_STATUS_INFO_LENGTH_MISMATCH);
546bbf6f00cSJordan Brown 
547bbf6f00cSJordan Brown 	if ((rootdir != 0) || (namelen == 0) || (namelen >= MAXNAMELEN)) {
548a90cf9f2SGordon Ross 		return (NT_STATUS_INVALID_PARAMETER);
549bbf6f00cSJordan Brown 	}
550bbf6f00cSJordan Brown 
551bbf6f00cSJordan Brown 	if (strchr(fname, '\\') != NULL) {
552a90cf9f2SGordon Ross 		return (NT_STATUS_NOT_SUPPORTED);
553a90cf9f2SGordon Ross 	}
554a90cf9f2SGordon Ross 
555a90cf9f2SGordon Ross 	/*
556a90cf9f2SGordon Ross 	 * Construct the full dst. path relative to the share root.
557a90cf9f2SGordon Ross 	 * Allocated path is free'd in smb_request_free.
558a90cf9f2SGordon Ross 	 */
559a90cf9f2SGordon Ross 	path = smb_srm_zalloc(sr, SMB_MAXPATHLEN);
560a90cf9f2SGordon Ross 	if (src_fqi->fq_path.pn_pname) {
561a90cf9f2SGordon Ross 		/* Got here via: smb_set_by_path */
562a90cf9f2SGordon Ross 		(void) snprintf(path, SMB_MAXPATHLEN, "%s\\%s",
563a90cf9f2SGordon Ross 		    src_fqi->fq_path.pn_pname, fname);
564a90cf9f2SGordon Ross 	} else {
565a90cf9f2SGordon Ross 		/* Got here via: smb_set_by_fid */
566a90cf9f2SGordon Ross 		rc = smb_node_getshrpath(sinfo->si_node->n_dnode,
567a90cf9f2SGordon Ross 		    sr->tid_tree, path, SMB_MAXPATHLEN);
568a90cf9f2SGordon Ross 		if (rc != 0) {
569a90cf9f2SGordon Ross 			status = smb_errno2status(rc);
570a90cf9f2SGordon Ross 			return (status);
571a90cf9f2SGordon Ross 		}
572a90cf9f2SGordon Ross 		(void) strlcat(path, "\\", SMB_MAXPATHLEN);
573a90cf9f2SGordon Ross 		(void) strlcat(path, fname, SMB_MAXPATHLEN);
574bbf6f00cSJordan Brown 	}
575bbf6f00cSJordan Brown 
576a90cf9f2SGordon Ross 	/*
577a90cf9f2SGordon Ross 	 * The common rename code can slightly optimize a
578a90cf9f2SGordon Ross 	 * rename in the same directory when we set the
579a90cf9f2SGordon Ross 	 * dst_fqi->fq_dnode, dst_fqi->fq_last_comp
580a90cf9f2SGordon Ross 	 */
581a90cf9f2SGordon Ross 	dst_fqi->fq_dnode = sinfo->si_node->n_dnode;
582a90cf9f2SGordon Ross 	(void) strlcpy(dst_fqi->fq_last_comp, fname, MAXNAMELEN);
583bbf6f00cSJordan Brown 
584a90cf9f2SGordon Ross 	status = smb_setinfo_rename(sr, sinfo->si_node, path, flags);
585a90cf9f2SGordon Ross 	return (status);
586bbf6f00cSJordan Brown }
587