5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 #include <smbsrv/smb_kproto.h>
29 #include <smbsrv/smbinfo.h>
30 #include <smbsrv/smb_fsops.h>
31
32 /*
33 * The create directory message is sent to create a new directory. The
34 * appropriate Tid and additional pathname are passed. The directory must
35 * not exist for it to be created.
36 *
37 * Client Request Description
38 * ================================== =================================
39 * UCHAR WordCount; Count of parameter words = 0
40 * USHORT ByteCount; Count of data bytes; min = 2
41 * UCHAR BufferFormat; 0x04
42 * STRING DirectoryName[]; Directory name
43 *
44 * Servers require clients to have at least create permission for the
45 * subtree containing the directory in order to create a new directory.
46 * The creator's access rights to the new directory are be determined by
47 * local policy on the server.
48 *
49 * Server Response Description
50 * ================================== =================================
51 * UCHAR WordCount; Count of parameter words = 0
52 * USHORT ByteCount; Count of data bytes = 0
53 */
54 smb_sdrc_t
55 smb_pre_create_directory(smb_request_t *sr)
56 {
57 int rc;
58
59 rc = smbsr_decode_data(sr, "%S", sr,
60 &sr->arg.dirop.fqi.fq_path.pn_path);
61
62 DTRACE_SMB_2(op__CreateDirectory__start, smb_request_t *, sr,
63 struct dirop *, &sr->arg.dirop);
64
65 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
66 }
67
68 void
69 smb_post_create_directory(smb_request_t *sr)
70 {
71 DTRACE_SMB_1(op__CreateDirectory__done, smb_request_t *, sr);
72 }
73
74 smb_sdrc_t
75 smb_com_create_directory(smb_request_t *sr)
76 {
77 int rc = 0;
78 smb_pathname_t *pn = &sr->arg.dirop.fqi.fq_path;
79
80 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
81 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
82 ERRDOS, ERROR_ACCESS_DENIED);
83 return (SDRC_ERROR);
84 }
85
86 smb_pathname_init(sr, pn, pn->pn_path);
87 if (!smb_pathname_validate(sr, pn) ||
88 !smb_validate_dirname(sr, pn)) {
89 return (SDRC_ERROR);
90 }
91
189 * USHORT ByteCount; Count of data bytes; min = 2
190 * UCHAR BufferFormat; 0x04
191 * STRING DirectoryName[]; Directory name
192 *
193 * The directory to be deleted cannot be the root of the share specified
194 * by Tid.
195 *
196 * Server Response Description
197 * ================================== =================================
198 * UCHAR WordCount; Count of parameter words = 0
199 * USHORT ByteCount; Count of data bytes = 0
200 */
201 smb_sdrc_t
202 smb_pre_delete_directory(smb_request_t *sr)
203 {
204 int rc;
205
206 rc = smbsr_decode_data(sr, "%S", sr,
207 &sr->arg.dirop.fqi.fq_path.pn_path);
208
209 DTRACE_SMB_2(op__DeleteDirectory__start, smb_request_t *, sr,
210 struct dirop *, &sr->arg.dirop);
211
212 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
213 }
214
215 void
216 smb_post_delete_directory(smb_request_t *sr)
217 {
218 DTRACE_SMB_1(op__DeleteDirectory__done, smb_request_t *, sr);
219 }
220
221 smb_sdrc_t
222 smb_com_delete_directory(smb_request_t *sr)
223 {
224 int rc;
225 uint32_t flags = 0;
226 smb_fqi_t *fqi;
227 smb_node_t *tnode;
228
229 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
230 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
231 ERRDOS, ERROR_ACCESS_DENIED);
232 return (SDRC_ERROR);
233 }
234
235 fqi = &sr->arg.dirop.fqi;
236 tnode = sr->tid_tree->t_snode;
237
238 smb_pathname_init(sr, &fqi->fq_path, fqi->fq_path.pn_path);
239 if (!smb_pathname_validate(sr, &fqi->fq_path) ||
240 !smb_validate_dirname(sr, &fqi->fq_path)) {
241 return (SDRC_ERROR);
242 }
243
244 rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
245 tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);
246
247 if (rc != 0) {
248 smbsr_errno(sr, rc);
249 return (SDRC_ERROR);
250 }
251
252 rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
253 tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
254 if (rc != 0) {
255 if (rc == ENOENT)
256 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
257 ERRDOS, ERROR_FILE_NOT_FOUND);
258 else
259 smbsr_errno(sr, rc);
260 smb_node_release(fqi->fq_dnode);
261 return (SDRC_ERROR);
262 }
263
264 /*
265 * Delete should fail if this is the root of a share
266 * or a DFS link
267 */
268 if ((fqi->fq_fnode == tnode) || smb_node_is_dfslink(fqi->fq_fnode)) {
269 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
270 ERRDOS, ERROR_ACCESS_DENIED);
271 smb_node_release(fqi->fq_dnode);
272 smb_node_release(fqi->fq_fnode);
273 return (SDRC_ERROR);
274 }
275
276 if (!smb_node_is_dir(fqi->fq_fnode)) {
277 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
278 ERRDOS, ERROR_PATH_NOT_FOUND);
344 * UCHAR BufferFormat; 0x04
345 * STRING DirectoryPath[]; Directory path
346 *
347 * Server Response Description
348 * ================================== =================================
349 *
350 * UCHAR WordCount; Count of parameter words = 0
351 * USHORT ByteCount; Count of data bytes = 0
352 *
353 * DOS clients, in particular, depend on ERRbadpath if the directory is
354 * not found.
355 */
356 smb_sdrc_t
357 smb_pre_check_directory(smb_request_t *sr)
358 {
359 int rc;
360
361 rc = smbsr_decode_data(sr, "%S", sr,
362 &sr->arg.dirop.fqi.fq_path.pn_path);
363
364 DTRACE_SMB_2(op__CheckDirectory__start, smb_request_t *, sr,
365 struct dirop *, &sr->arg.dirop);
366
367 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
368 }
369
370 void
371 smb_post_check_directory(smb_request_t *sr)
372 {
373 DTRACE_SMB_1(op__CheckDirectory__done, smb_request_t *, sr);
374 }
375
376 smb_sdrc_t
377 smb_com_check_directory(smb_request_t *sr)
378 {
379 int rc;
380 smb_fqi_t *fqi;
381 smb_node_t *tnode;
382 smb_node_t *node;
383 char *path;
384 smb_pathname_t *pn;
385
386 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
387 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
388 ERROR_ACCESS_DENIED);
389 return (SDRC_ERROR);
390 }
391
392 fqi = &sr->arg.dirop.fqi;
393 pn = &fqi->fq_path;
400 smb_pathname_init(sr, pn, pn->pn_path);
401 if (!smb_pathname_validate(sr, pn) ||
402 !smb_validate_dirname(sr, pn)) {
403 return (SDRC_ERROR);
404 }
405
406 path = pn->pn_path;
407 tnode = sr->tid_tree->t_snode;
408
409 rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode,
410 &fqi->fq_dnode, fqi->fq_last_comp);
411 if (rc != 0) {
412 smbsr_errno(sr, rc);
413 return (SDRC_ERROR);
414 }
415
416 rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
417 tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
418 smb_node_release(fqi->fq_dnode);
419 if (rc != 0) {
420 if (rc == ENOENT)
421 smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
422 ERRDOS, ERROR_PATH_NOT_FOUND);
423 else
424 smbsr_errno(sr, rc);
425 return (SDRC_ERROR);
426 }
427
428 node = fqi->fq_fnode;
429 if (!smb_node_is_dir(node)) {
430 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
431 ERRDOS, ERROR_PATH_NOT_FOUND);
432 smb_node_release(node);
433 return (SDRC_ERROR);
434 }
435
436 if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
437 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
438 smb_node_release(node);
439 return (SDRC_ERROR);
440 }
441
442 rc = smb_fsop_access(sr, sr->user_cr, node, FILE_TRAVERSE);
443
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 #include <smbsrv/smb_kproto.h>
29 #include <smbsrv/smbinfo.h>
30 #include <smbsrv/smb_fsops.h>
31
32 /*
33 * The create directory message is sent to create a new directory. The
34 * appropriate Tid and additional pathname are passed. The directory must
35 * not exist for it to be created.
36 *
37 * Client Request Description
38 * ================================== =================================
39 * UCHAR WordCount; Count of parameter words = 0
40 * USHORT ByteCount; Count of data bytes; min = 2
41 * UCHAR BufferFormat; 0x04
42 * STRING DirectoryName[]; Directory name
43 *
44 * Servers require clients to have at least create permission for the
45 * subtree containing the directory in order to create a new directory.
46 * The creator's access rights to the new directory are be determined by
47 * local policy on the server.
48 *
49 * Server Response Description
50 * ================================== =================================
51 * UCHAR WordCount; Count of parameter words = 0
52 * USHORT ByteCount; Count of data bytes = 0
53 */
54 smb_sdrc_t
55 smb_pre_create_directory(smb_request_t *sr)
56 {
57 int rc;
58
59 rc = smbsr_decode_data(sr, "%S", sr,
60 &sr->arg.dirop.fqi.fq_path.pn_path);
61
62 DTRACE_SMB_START(op__CreateDirectory, smb_request_t *, sr);
63
64 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
65 }
66
67 void
68 smb_post_create_directory(smb_request_t *sr)
69 {
70 DTRACE_SMB_DONE(op__CreateDirectory, smb_request_t *, sr);
71 }
72
73 smb_sdrc_t
74 smb_com_create_directory(smb_request_t *sr)
75 {
76 int rc = 0;
77 smb_pathname_t *pn = &sr->arg.dirop.fqi.fq_path;
78
79 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
80 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
81 ERRDOS, ERROR_ACCESS_DENIED);
82 return (SDRC_ERROR);
83 }
84
85 smb_pathname_init(sr, pn, pn->pn_path);
86 if (!smb_pathname_validate(sr, pn) ||
87 !smb_validate_dirname(sr, pn)) {
88 return (SDRC_ERROR);
89 }
90
188 * USHORT ByteCount; Count of data bytes; min = 2
189 * UCHAR BufferFormat; 0x04
190 * STRING DirectoryName[]; Directory name
191 *
192 * The directory to be deleted cannot be the root of the share specified
193 * by Tid.
194 *
195 * Server Response Description
196 * ================================== =================================
197 * UCHAR WordCount; Count of parameter words = 0
198 * USHORT ByteCount; Count of data bytes = 0
199 */
200 smb_sdrc_t
201 smb_pre_delete_directory(smb_request_t *sr)
202 {
203 int rc;
204
205 rc = smbsr_decode_data(sr, "%S", sr,
206 &sr->arg.dirop.fqi.fq_path.pn_path);
207
208 DTRACE_SMB_START(op__DeleteDirectory, smb_request_t *, sr);
209
210 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
211 }
212
213 void
214 smb_post_delete_directory(smb_request_t *sr)
215 {
216 DTRACE_SMB_DONE(op__DeleteDirectory, smb_request_t *, sr);
217 }
218
219 smb_sdrc_t
220 smb_com_delete_directory(smb_request_t *sr)
221 {
222 int rc;
223 uint32_t flags = 0;
224 smb_fqi_t *fqi;
225 smb_node_t *tnode;
226
227 if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
228 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
229 ERRDOS, ERROR_ACCESS_DENIED);
230 return (SDRC_ERROR);
231 }
232
233 fqi = &sr->arg.dirop.fqi;
234 tnode = sr->tid_tree->t_snode;
235
236 smb_pathname_init(sr, &fqi->fq_path, fqi->fq_path.pn_path);
237 if (!smb_pathname_validate(sr, &fqi->fq_path) ||
238 !smb_validate_dirname(sr, &fqi->fq_path)) {
239 return (SDRC_ERROR);
240 }
241
242 rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
243 tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);
244
245 if (rc != 0) {
246 smbsr_errno(sr, rc);
247 return (SDRC_ERROR);
248 }
249
250 rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
251 tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
252 if (rc != 0) {
253 smbsr_errno(sr, rc);
254 smb_node_release(fqi->fq_dnode);
255 return (SDRC_ERROR);
256 }
257
258 /*
259 * Delete should fail if this is the root of a share
260 * or a DFS link
261 */
262 if ((fqi->fq_fnode == tnode) || smb_node_is_dfslink(fqi->fq_fnode)) {
263 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
264 ERRDOS, ERROR_ACCESS_DENIED);
265 smb_node_release(fqi->fq_dnode);
266 smb_node_release(fqi->fq_fnode);
267 return (SDRC_ERROR);
268 }
269
270 if (!smb_node_is_dir(fqi->fq_fnode)) {
271 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
272 ERRDOS, ERROR_PATH_NOT_FOUND);
338 * UCHAR BufferFormat; 0x04
339 * STRING DirectoryPath[]; Directory path
340 *
341 * Server Response Description
342 * ================================== =================================
343 *
344 * UCHAR WordCount; Count of parameter words = 0
345 * USHORT ByteCount; Count of data bytes = 0
346 *
347 * DOS clients, in particular, depend on ERRbadpath if the directory is
348 * not found.
349 */
350 smb_sdrc_t
351 smb_pre_check_directory(smb_request_t *sr)
352 {
353 int rc;
354
355 rc = smbsr_decode_data(sr, "%S", sr,
356 &sr->arg.dirop.fqi.fq_path.pn_path);
357
358 DTRACE_SMB_START(op__CheckDirectory, smb_request_t *, sr);
359
360 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
361 }
362
363 void
364 smb_post_check_directory(smb_request_t *sr)
365 {
366 DTRACE_SMB_DONE(op__CheckDirectory, smb_request_t *, sr);
367 }
368
369 smb_sdrc_t
370 smb_com_check_directory(smb_request_t *sr)
371 {
372 int rc;
373 smb_fqi_t *fqi;
374 smb_node_t *tnode;
375 smb_node_t *node;
376 char *path;
377 smb_pathname_t *pn;
378
379 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
380 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
381 ERROR_ACCESS_DENIED);
382 return (SDRC_ERROR);
383 }
384
385 fqi = &sr->arg.dirop.fqi;
386 pn = &fqi->fq_path;
393 smb_pathname_init(sr, pn, pn->pn_path);
394 if (!smb_pathname_validate(sr, pn) ||
395 !smb_validate_dirname(sr, pn)) {
396 return (SDRC_ERROR);
397 }
398
399 path = pn->pn_path;
400 tnode = sr->tid_tree->t_snode;
401
402 rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode,
403 &fqi->fq_dnode, fqi->fq_last_comp);
404 if (rc != 0) {
405 smbsr_errno(sr, rc);
406 return (SDRC_ERROR);
407 }
408
409 rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
410 tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
411 smb_node_release(fqi->fq_dnode);
412 if (rc != 0) {
413 smbsr_errno(sr, rc);
414 return (SDRC_ERROR);
415 }
416
417 node = fqi->fq_fnode;
418 if (!smb_node_is_dir(node)) {
419 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
420 ERRDOS, ERROR_PATH_NOT_FOUND);
421 smb_node_release(node);
422 return (SDRC_ERROR);
423 }
424
425 if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
426 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
427 smb_node_release(node);
428 return (SDRC_ERROR);
429 }
430
431 rc = smb_fsop_access(sr, sr->user_cr, node, FILE_TRAVERSE);
432
|