xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_directory.c (revision 11963:061945695ce1)
18934SJose.Borrego@Sun.COM /*
28934SJose.Borrego@Sun.COM  * CDDL HEADER START
38934SJose.Borrego@Sun.COM  *
48934SJose.Borrego@Sun.COM  * The contents of this file are subject to the terms of the
58934SJose.Borrego@Sun.COM  * Common Development and Distribution License (the "License").
68934SJose.Borrego@Sun.COM  * You may not use this file except in compliance with the License.
78934SJose.Borrego@Sun.COM  *
88934SJose.Borrego@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98934SJose.Borrego@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108934SJose.Borrego@Sun.COM  * See the License for the specific language governing permissions
118934SJose.Borrego@Sun.COM  * and limitations under the License.
128934SJose.Borrego@Sun.COM  *
138934SJose.Borrego@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148934SJose.Borrego@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158934SJose.Borrego@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168934SJose.Borrego@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178934SJose.Borrego@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188934SJose.Borrego@Sun.COM  *
198934SJose.Borrego@Sun.COM  * CDDL HEADER END
208934SJose.Borrego@Sun.COM  */
218934SJose.Borrego@Sun.COM /*
2211447Samw@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
238934SJose.Borrego@Sun.COM  * Use is subject to license terms.
248934SJose.Borrego@Sun.COM  */
258934SJose.Borrego@Sun.COM 
2610966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
278934SJose.Borrego@Sun.COM #include <smbsrv/smbinfo.h>
288934SJose.Borrego@Sun.COM #include <smbsrv/smb_fsops.h>
298934SJose.Borrego@Sun.COM 
308934SJose.Borrego@Sun.COM /*
318934SJose.Borrego@Sun.COM  * The create directory message is sent to create a new directory.  The
328934SJose.Borrego@Sun.COM  * appropriate Tid and additional pathname are passed.  The directory must
338934SJose.Borrego@Sun.COM  * not exist for it to be created.
348934SJose.Borrego@Sun.COM  *
358934SJose.Borrego@Sun.COM  * Client Request                     Description
368934SJose.Borrego@Sun.COM  * ================================== =================================
378934SJose.Borrego@Sun.COM  * UCHAR WordCount;                   Count of parameter words = 0
388934SJose.Borrego@Sun.COM  * USHORT ByteCount;                  Count of data bytes; min = 2
398934SJose.Borrego@Sun.COM  * UCHAR BufferFormat;                0x04
408934SJose.Borrego@Sun.COM  * STRING DirectoryName[];            Directory name
418934SJose.Borrego@Sun.COM  *
428934SJose.Borrego@Sun.COM  * Servers require clients to have at least create permission for the
438934SJose.Borrego@Sun.COM  * subtree containing the directory in order to create a new directory.
448934SJose.Borrego@Sun.COM  * The creator's access rights to the new directory are be determined by
458934SJose.Borrego@Sun.COM  * local policy on the server.
468934SJose.Borrego@Sun.COM  *
478934SJose.Borrego@Sun.COM  * Server Response                    Description
488934SJose.Borrego@Sun.COM  * ================================== =================================
498934SJose.Borrego@Sun.COM  * UCHAR WordCount;                   Count of parameter words = 0
508934SJose.Borrego@Sun.COM  * USHORT ByteCount;                  Count of data bytes = 0
518934SJose.Borrego@Sun.COM  */
528934SJose.Borrego@Sun.COM smb_sdrc_t
smb_pre_create_directory(smb_request_t * sr)538934SJose.Borrego@Sun.COM smb_pre_create_directory(smb_request_t *sr)
548934SJose.Borrego@Sun.COM {
558934SJose.Borrego@Sun.COM 	int rc;
568934SJose.Borrego@Sun.COM 
579343SAfshin.Ardakani@Sun.COM 	rc = smbsr_decode_data(sr, "%S", sr,
589343SAfshin.Ardakani@Sun.COM 	    &sr->arg.dirop.fqi.fq_path.pn_path);
598934SJose.Borrego@Sun.COM 
608934SJose.Borrego@Sun.COM 	DTRACE_SMB_2(op__CreateDirectory__start, smb_request_t *, sr,
618934SJose.Borrego@Sun.COM 	    struct dirop *, &sr->arg.dirop);
628934SJose.Borrego@Sun.COM 
638934SJose.Borrego@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
648934SJose.Borrego@Sun.COM }
658934SJose.Borrego@Sun.COM 
668934SJose.Borrego@Sun.COM void
smb_post_create_directory(smb_request_t * sr)678934SJose.Borrego@Sun.COM smb_post_create_directory(smb_request_t *sr)
688934SJose.Borrego@Sun.COM {
698934SJose.Borrego@Sun.COM 	DTRACE_SMB_1(op__CreateDirectory__done, smb_request_t *, sr);
708934SJose.Borrego@Sun.COM }
718934SJose.Borrego@Sun.COM 
728934SJose.Borrego@Sun.COM smb_sdrc_t
smb_com_create_directory(smb_request_t * sr)738934SJose.Borrego@Sun.COM smb_com_create_directory(smb_request_t *sr)
748934SJose.Borrego@Sun.COM {
758934SJose.Borrego@Sun.COM 	int rc = 0;
7611337SWilliam.Krier@Sun.COM 	smb_pathname_t *pn = &sr->arg.dirop.fqi.fq_path;
778934SJose.Borrego@Sun.COM 
788934SJose.Borrego@Sun.COM 	if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
798934SJose.Borrego@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
808934SJose.Borrego@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
818934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
828934SJose.Borrego@Sun.COM 	}
838934SJose.Borrego@Sun.COM 
8411337SWilliam.Krier@Sun.COM 	smb_pathname_init(sr, pn, pn->pn_path);
8511337SWilliam.Krier@Sun.COM 	if (!smb_pathname_validate(sr, pn) ||
8611337SWilliam.Krier@Sun.COM 	    !smb_validate_dirname(sr, pn)) {
878934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
888934SJose.Borrego@Sun.COM 	}
898934SJose.Borrego@Sun.COM 
9011337SWilliam.Krier@Sun.COM 	if ((rc = smb_common_create_directory(sr)) != 0) {
9111337SWilliam.Krier@Sun.COM 		smbsr_errno(sr, rc);
928934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
938934SJose.Borrego@Sun.COM 	}
948934SJose.Borrego@Sun.COM 
958934SJose.Borrego@Sun.COM 	rc = smbsr_encode_empty_result(sr);
968934SJose.Borrego@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
978934SJose.Borrego@Sun.COM }
988934SJose.Borrego@Sun.COM 
998934SJose.Borrego@Sun.COM /*
1008934SJose.Borrego@Sun.COM  * smb_common_create_directory
1018934SJose.Borrego@Sun.COM  *
1028934SJose.Borrego@Sun.COM  * Currently called from:
1038934SJose.Borrego@Sun.COM  *		smb_com_create_directory
1048934SJose.Borrego@Sun.COM  *		smb_com_trans2_create_directory
1058934SJose.Borrego@Sun.COM  *
1068934SJose.Borrego@Sun.COM  * Returns errno values.
1078934SJose.Borrego@Sun.COM  */
1088934SJose.Borrego@Sun.COM int
smb_common_create_directory(smb_request_t * sr)1098934SJose.Borrego@Sun.COM smb_common_create_directory(smb_request_t *sr)
1108934SJose.Borrego@Sun.COM {
1118934SJose.Borrego@Sun.COM 	int rc;
1128934SJose.Borrego@Sun.COM 	smb_attr_t new_attr;
11310504SKeyur.Desai@Sun.COM 	smb_fqi_t *fqi;
11410504SKeyur.Desai@Sun.COM 	smb_node_t *tnode;
1158934SJose.Borrego@Sun.COM 
11610504SKeyur.Desai@Sun.COM 	fqi = &sr->arg.dirop.fqi;
11710504SKeyur.Desai@Sun.COM 	tnode = sr->tid_tree->t_snode;
1188934SJose.Borrego@Sun.COM 
11910504SKeyur.Desai@Sun.COM 	rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
12010504SKeyur.Desai@Sun.COM 	    tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);
12110504SKeyur.Desai@Sun.COM 	if (rc != 0)
1228934SJose.Borrego@Sun.COM 		return (rc);
1238934SJose.Borrego@Sun.COM 
12411337SWilliam.Krier@Sun.COM 	if (smb_is_invalid_filename(fqi->fq_last_comp)) {
12511337SWilliam.Krier@Sun.COM 		smb_node_release(fqi->fq_dnode);
12611337SWilliam.Krier@Sun.COM 		return (EILSEQ); /* NT_STATUS_OBJECT_NAME_INVALID */
12711337SWilliam.Krier@Sun.COM 	}
12811337SWilliam.Krier@Sun.COM 
12910504SKeyur.Desai@Sun.COM 	/* lookup node - to ensure that it does NOT exist */
13010504SKeyur.Desai@Sun.COM 	rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
13110504SKeyur.Desai@Sun.COM 	    tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
13210504SKeyur.Desai@Sun.COM 	if (rc == 0) {
13310504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_dnode);
13410504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_fnode);
13510504SKeyur.Desai@Sun.COM 		return (EEXIST);
13610504SKeyur.Desai@Sun.COM 	}
13710504SKeyur.Desai@Sun.COM 	if (rc != ENOENT) {
13810504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_dnode);
13910504SKeyur.Desai@Sun.COM 		return (rc);
14010504SKeyur.Desai@Sun.COM 	}
1418934SJose.Borrego@Sun.COM 
14210504SKeyur.Desai@Sun.COM 	rc = smb_fsop_access(sr, sr->user_cr, fqi->fq_dnode,
14310504SKeyur.Desai@Sun.COM 	    FILE_ADD_SUBDIRECTORY);
14410504SKeyur.Desai@Sun.COM 	if (rc != NT_STATUS_SUCCESS) {
14510504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_dnode);
1468934SJose.Borrego@Sun.COM 		return (EACCES);
14710504SKeyur.Desai@Sun.COM 	}
1488934SJose.Borrego@Sun.COM 
1498934SJose.Borrego@Sun.COM 	/*
1508934SJose.Borrego@Sun.COM 	 * Explicitly set sa_dosattr, otherwise the file system may
1518934SJose.Borrego@Sun.COM 	 * automatically apply FILE_ATTRIBUTE_ARCHIVE which, for
1528934SJose.Borrego@Sun.COM 	 * compatibility with windows servers, should not be set.
1538934SJose.Borrego@Sun.COM 	 */
1548934SJose.Borrego@Sun.COM 	bzero(&new_attr, sizeof (new_attr));
1558934SJose.Borrego@Sun.COM 	new_attr.sa_dosattr = FILE_ATTRIBUTE_DIRECTORY;
1568934SJose.Borrego@Sun.COM 	new_attr.sa_vattr.va_type = VDIR;
1578934SJose.Borrego@Sun.COM 	new_attr.sa_vattr.va_mode = 0777;
1588934SJose.Borrego@Sun.COM 	new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE | SMB_AT_DOSATTR;
1598934SJose.Borrego@Sun.COM 
16010504SKeyur.Desai@Sun.COM 	rc = smb_fsop_mkdir(sr, sr->user_cr, fqi->fq_dnode, fqi->fq_last_comp,
16110504SKeyur.Desai@Sun.COM 	    &new_attr, &fqi->fq_fnode);
16210504SKeyur.Desai@Sun.COM 	if (rc != 0) {
16310504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_dnode);
1648934SJose.Borrego@Sun.COM 		return (rc);
1658934SJose.Borrego@Sun.COM 	}
1668934SJose.Borrego@Sun.COM 
1678934SJose.Borrego@Sun.COM 	sr->arg.open.create_options = FILE_DIRECTORY_FILE;
1688934SJose.Borrego@Sun.COM 
16910504SKeyur.Desai@Sun.COM 	smb_node_release(fqi->fq_dnode);
17010504SKeyur.Desai@Sun.COM 	smb_node_release(fqi->fq_fnode);
1718934SJose.Borrego@Sun.COM 	return (0);
1728934SJose.Borrego@Sun.COM }
1738934SJose.Borrego@Sun.COM 
1748934SJose.Borrego@Sun.COM /*
1758934SJose.Borrego@Sun.COM  * The delete directory message is sent to delete an empty directory. The
1768934SJose.Borrego@Sun.COM  * appropriate Tid and additional pathname are passed. The directory must
1778934SJose.Borrego@Sun.COM  * be empty for it to be deleted.
1788934SJose.Borrego@Sun.COM  *
1798934SJose.Borrego@Sun.COM  * NT supports a hidden permission known as File Delete Child (FDC). If
1808934SJose.Borrego@Sun.COM  * the user has FullControl access to a directory, the user is permitted
1818934SJose.Borrego@Sun.COM  * to delete any object in the directory regardless of the permissions
1828934SJose.Borrego@Sun.COM  * on the object.
1838934SJose.Borrego@Sun.COM  *
1848934SJose.Borrego@Sun.COM  * Client Request                     Description
1858934SJose.Borrego@Sun.COM  * ================================== =================================
1868934SJose.Borrego@Sun.COM  * UCHAR WordCount;                   Count of parameter words = 0
1878934SJose.Borrego@Sun.COM  * USHORT ByteCount;                  Count of data bytes; min = 2
1888934SJose.Borrego@Sun.COM  * UCHAR BufferFormat;                0x04
1898934SJose.Borrego@Sun.COM  * STRING DirectoryName[];            Directory name
1908934SJose.Borrego@Sun.COM  *
1918934SJose.Borrego@Sun.COM  * The directory to be deleted cannot be the root of the share specified
1928934SJose.Borrego@Sun.COM  * by Tid.
1938934SJose.Borrego@Sun.COM  *
1948934SJose.Borrego@Sun.COM  * Server Response                    Description
1958934SJose.Borrego@Sun.COM  * ================================== =================================
1968934SJose.Borrego@Sun.COM  * UCHAR WordCount;                   Count of parameter words = 0
1978934SJose.Borrego@Sun.COM  * USHORT ByteCount;                  Count of data bytes = 0
1988934SJose.Borrego@Sun.COM  */
1998934SJose.Borrego@Sun.COM smb_sdrc_t
smb_pre_delete_directory(smb_request_t * sr)2008934SJose.Borrego@Sun.COM smb_pre_delete_directory(smb_request_t *sr)
2018934SJose.Borrego@Sun.COM {
2028934SJose.Borrego@Sun.COM 	int rc;
2038934SJose.Borrego@Sun.COM 
2049343SAfshin.Ardakani@Sun.COM 	rc = smbsr_decode_data(sr, "%S", sr,
2059343SAfshin.Ardakani@Sun.COM 	    &sr->arg.dirop.fqi.fq_path.pn_path);
2068934SJose.Borrego@Sun.COM 
2078934SJose.Borrego@Sun.COM 	DTRACE_SMB_2(op__DeleteDirectory__start, smb_request_t *, sr,
2088934SJose.Borrego@Sun.COM 	    struct dirop *, &sr->arg.dirop);
2098934SJose.Borrego@Sun.COM 
2108934SJose.Borrego@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2118934SJose.Borrego@Sun.COM }
2128934SJose.Borrego@Sun.COM 
2138934SJose.Borrego@Sun.COM void
smb_post_delete_directory(smb_request_t * sr)2148934SJose.Borrego@Sun.COM smb_post_delete_directory(smb_request_t *sr)
2158934SJose.Borrego@Sun.COM {
2168934SJose.Borrego@Sun.COM 	DTRACE_SMB_1(op__DeleteDirectory__done, smb_request_t *, sr);
2178934SJose.Borrego@Sun.COM }
2188934SJose.Borrego@Sun.COM 
2198934SJose.Borrego@Sun.COM smb_sdrc_t
smb_com_delete_directory(smb_request_t * sr)2208934SJose.Borrego@Sun.COM smb_com_delete_directory(smb_request_t *sr)
2218934SJose.Borrego@Sun.COM {
2228934SJose.Borrego@Sun.COM 	int rc;
2239231SAfshin.Ardakani@Sun.COM 	uint32_t flags = 0;
22410504SKeyur.Desai@Sun.COM 	smb_fqi_t *fqi;
22510504SKeyur.Desai@Sun.COM 	smb_node_t *tnode;
2268934SJose.Borrego@Sun.COM 
2278934SJose.Borrego@Sun.COM 	if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
2288934SJose.Borrego@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
2298934SJose.Borrego@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
2308934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
2318934SJose.Borrego@Sun.COM 	}
2328934SJose.Borrego@Sun.COM 
23310504SKeyur.Desai@Sun.COM 	fqi = &sr->arg.dirop.fqi;
23410504SKeyur.Desai@Sun.COM 	tnode = sr->tid_tree->t_snode;
2358934SJose.Borrego@Sun.COM 
23611337SWilliam.Krier@Sun.COM 	smb_pathname_init(sr, &fqi->fq_path, fqi->fq_path.pn_path);
23711337SWilliam.Krier@Sun.COM 	if (!smb_pathname_validate(sr, &fqi->fq_path) ||
23811337SWilliam.Krier@Sun.COM 	    !smb_validate_dirname(sr, &fqi->fq_path)) {
23911337SWilliam.Krier@Sun.COM 		return (SDRC_ERROR);
24011337SWilliam.Krier@Sun.COM 	}
24111337SWilliam.Krier@Sun.COM 
24210504SKeyur.Desai@Sun.COM 	rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
24310504SKeyur.Desai@Sun.COM 	    tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);
244*11963SAfshin.Ardakani@Sun.COM 
24510504SKeyur.Desai@Sun.COM 	if (rc != 0) {
24610504SKeyur.Desai@Sun.COM 		smbsr_errno(sr, rc);
24710504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
24810504SKeyur.Desai@Sun.COM 	}
24910504SKeyur.Desai@Sun.COM 
25010504SKeyur.Desai@Sun.COM 	rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
25110504SKeyur.Desai@Sun.COM 	    tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
25210504SKeyur.Desai@Sun.COM 	if (rc != 0) {
2538934SJose.Borrego@Sun.COM 		if (rc == ENOENT)
2548934SJose.Borrego@Sun.COM 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
2558934SJose.Borrego@Sun.COM 			    ERRDOS, ERROR_FILE_NOT_FOUND);
2568934SJose.Borrego@Sun.COM 		else
2578934SJose.Borrego@Sun.COM 			smbsr_errno(sr, rc);
25810504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_dnode);
2598934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
2608934SJose.Borrego@Sun.COM 	}
2618934SJose.Borrego@Sun.COM 
262*11963SAfshin.Ardakani@Sun.COM 	/*
263*11963SAfshin.Ardakani@Sun.COM 	 * Delete should fail if this is the root of a share
264*11963SAfshin.Ardakani@Sun.COM 	 * or a DFS link
265*11963SAfshin.Ardakani@Sun.COM 	 */
266*11963SAfshin.Ardakani@Sun.COM 	if ((fqi->fq_fnode == tnode) || smb_node_is_dfslink(fqi->fq_fnode)) {
26711337SWilliam.Krier@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
26811337SWilliam.Krier@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
26911337SWilliam.Krier@Sun.COM 		smb_node_release(fqi->fq_dnode);
27011337SWilliam.Krier@Sun.COM 		smb_node_release(fqi->fq_fnode);
27111337SWilliam.Krier@Sun.COM 		return (SDRC_ERROR);
27211337SWilliam.Krier@Sun.COM 	}
27311337SWilliam.Krier@Sun.COM 
274*11963SAfshin.Ardakani@Sun.COM 	if (!smb_node_is_dir(fqi->fq_fnode)) {
275*11963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
276*11963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_PATH_NOT_FOUND);
277*11963SAfshin.Ardakani@Sun.COM 		smb_node_release(fqi->fq_dnode);
278*11963SAfshin.Ardakani@Sun.COM 		smb_node_release(fqi->fq_fnode);
279*11963SAfshin.Ardakani@Sun.COM 		return (SDRC_ERROR);
280*11963SAfshin.Ardakani@Sun.COM 	}
281*11963SAfshin.Ardakani@Sun.COM 
28210504SKeyur.Desai@Sun.COM 	rc = smb_node_getattr(sr, fqi->fq_fnode, &fqi->fq_fattr);
28310504SKeyur.Desai@Sun.COM 	if (rc != 0) {
28410504SKeyur.Desai@Sun.COM 		smbsr_errno(sr, rc);
28510504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_dnode);
28610504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_fnode);
2878934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
2888934SJose.Borrego@Sun.COM 	}
2898934SJose.Borrego@Sun.COM 
29010504SKeyur.Desai@Sun.COM 	if ((fqi->fq_fattr.sa_dosattr & FILE_ATTRIBUTE_READONLY) ||
29110504SKeyur.Desai@Sun.COM 	    (smb_fsop_access(sr, sr->user_cr, fqi->fq_fnode, DELETE)
29210504SKeyur.Desai@Sun.COM 	    != NT_STATUS_SUCCESS)) {
29310504SKeyur.Desai@Sun.COM 		smbsr_error(sr, NT_STATUS_CANNOT_DELETE,
29410504SKeyur.Desai@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
29510504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_dnode);
29610504SKeyur.Desai@Sun.COM 		smb_node_release(fqi->fq_fnode);
29710504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
29810504SKeyur.Desai@Sun.COM 	}
2998934SJose.Borrego@Sun.COM 
3009231SAfshin.Ardakani@Sun.COM 	if (SMB_TREE_SUPPORTS_CATIA(sr))
3019231SAfshin.Ardakani@Sun.COM 		flags |= SMB_CATIA;
3029231SAfshin.Ardakani@Sun.COM 
30310504SKeyur.Desai@Sun.COM 	rc = smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
30410504SKeyur.Desai@Sun.COM 	    fqi->fq_fnode->od_name, flags);
30510504SKeyur.Desai@Sun.COM 
30610504SKeyur.Desai@Sun.COM 	smb_node_release(fqi->fq_fnode);
30710504SKeyur.Desai@Sun.COM 	smb_node_release(fqi->fq_dnode);
30810504SKeyur.Desai@Sun.COM 
3098934SJose.Borrego@Sun.COM 	if (rc != 0) {
3108934SJose.Borrego@Sun.COM 		if (rc == EEXIST)
3118934SJose.Borrego@Sun.COM 			smbsr_error(sr, NT_STATUS_DIRECTORY_NOT_EMPTY,
3128934SJose.Borrego@Sun.COM 			    ERRDOS, ERROR_DIR_NOT_EMPTY);
3138934SJose.Borrego@Sun.COM 		else
3148934SJose.Borrego@Sun.COM 			smbsr_errno(sr, rc);
3158934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
3168934SJose.Borrego@Sun.COM 	}
3178934SJose.Borrego@Sun.COM 
3188934SJose.Borrego@Sun.COM 	rc = smbsr_encode_empty_result(sr);
3198934SJose.Borrego@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
3208934SJose.Borrego@Sun.COM }
3218934SJose.Borrego@Sun.COM 
3228934SJose.Borrego@Sun.COM /*
3238934SJose.Borrego@Sun.COM  * This SMB is used to verify that a path exists and is a directory.  No
3248934SJose.Borrego@Sun.COM  * error is returned if the given path exists and the client has read
3258934SJose.Borrego@Sun.COM  * access to it.  Client machines which maintain a concept of a "working
3268934SJose.Borrego@Sun.COM  * directory" will find this useful to verify the validity of a "change
3278934SJose.Borrego@Sun.COM  * working directory" command.  Note that the servers do NOT have a concept
3288934SJose.Borrego@Sun.COM  * of working directory for a particular client.  The client must always
3298934SJose.Borrego@Sun.COM  * supply full pathnames relative to the Tid in the SMB header.
3308934SJose.Borrego@Sun.COM  *
3318934SJose.Borrego@Sun.COM  * Client Request                     Description
3328934SJose.Borrego@Sun.COM  * ================================== =================================
3338934SJose.Borrego@Sun.COM  *
3348934SJose.Borrego@Sun.COM  * UCHAR WordCount;                   Count of parameter words = 0
3358934SJose.Borrego@Sun.COM  * USHORT ByteCount;                  Count of data bytes;    min = 2
3368934SJose.Borrego@Sun.COM  * UCHAR BufferFormat;                0x04
3378934SJose.Borrego@Sun.COM  * STRING DirectoryPath[];            Directory path
3388934SJose.Borrego@Sun.COM  *
3398934SJose.Borrego@Sun.COM  * Server Response                    Description
3408934SJose.Borrego@Sun.COM  * ================================== =================================
3418934SJose.Borrego@Sun.COM  *
3428934SJose.Borrego@Sun.COM  * UCHAR WordCount;                   Count of parameter words = 0
3438934SJose.Borrego@Sun.COM  * USHORT ByteCount;                  Count of data bytes = 0
3448934SJose.Borrego@Sun.COM  *
3458934SJose.Borrego@Sun.COM  * DOS clients, in particular, depend on ERRbadpath if the directory is
3468934SJose.Borrego@Sun.COM  * not found.
3478934SJose.Borrego@Sun.COM  */
3488934SJose.Borrego@Sun.COM smb_sdrc_t
smb_pre_check_directory(smb_request_t * sr)3498934SJose.Borrego@Sun.COM smb_pre_check_directory(smb_request_t *sr)
3508934SJose.Borrego@Sun.COM {
3518934SJose.Borrego@Sun.COM 	int rc;
3528934SJose.Borrego@Sun.COM 
3539343SAfshin.Ardakani@Sun.COM 	rc = smbsr_decode_data(sr, "%S", sr,
3549343SAfshin.Ardakani@Sun.COM 	    &sr->arg.dirop.fqi.fq_path.pn_path);
3558934SJose.Borrego@Sun.COM 
3568934SJose.Borrego@Sun.COM 	DTRACE_SMB_2(op__CheckDirectory__start, smb_request_t *, sr,
3578934SJose.Borrego@Sun.COM 	    struct dirop *, &sr->arg.dirop);
3588934SJose.Borrego@Sun.COM 
3598934SJose.Borrego@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
3608934SJose.Borrego@Sun.COM }
3618934SJose.Borrego@Sun.COM 
3628934SJose.Borrego@Sun.COM void
smb_post_check_directory(smb_request_t * sr)3638934SJose.Borrego@Sun.COM smb_post_check_directory(smb_request_t *sr)
3648934SJose.Borrego@Sun.COM {
3658934SJose.Borrego@Sun.COM 	DTRACE_SMB_1(op__CheckDirectory__done, smb_request_t *, sr);
3668934SJose.Borrego@Sun.COM }
3678934SJose.Borrego@Sun.COM 
3688934SJose.Borrego@Sun.COM smb_sdrc_t
smb_com_check_directory(smb_request_t * sr)3698934SJose.Borrego@Sun.COM smb_com_check_directory(smb_request_t *sr)
3708934SJose.Borrego@Sun.COM {
3718934SJose.Borrego@Sun.COM 	int rc;
37210504SKeyur.Desai@Sun.COM 	smb_fqi_t *fqi;
37310504SKeyur.Desai@Sun.COM 	smb_node_t *tnode;
374*11963SAfshin.Ardakani@Sun.COM 	smb_node_t *node;
37510504SKeyur.Desai@Sun.COM 	char *path;
37611337SWilliam.Krier@Sun.COM 	smb_pathname_t *pn;
3778934SJose.Borrego@Sun.COM 
37811447Samw@Sun.COM 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
3798934SJose.Borrego@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
3808934SJose.Borrego@Sun.COM 		    ERROR_ACCESS_DENIED);
3818934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
3828934SJose.Borrego@Sun.COM 	}
3838934SJose.Borrego@Sun.COM 
38410504SKeyur.Desai@Sun.COM 	fqi = &sr->arg.dirop.fqi;
38511337SWilliam.Krier@Sun.COM 	pn = &fqi->fq_path;
38610504SKeyur.Desai@Sun.COM 
38711337SWilliam.Krier@Sun.COM 	if (pn->pn_path[0] == '\0') {
3888934SJose.Borrego@Sun.COM 		rc = smbsr_encode_empty_result(sr);
3898934SJose.Borrego@Sun.COM 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
3908934SJose.Borrego@Sun.COM 	}
3918934SJose.Borrego@Sun.COM 
39211337SWilliam.Krier@Sun.COM 	smb_pathname_init(sr, pn, pn->pn_path);
39311337SWilliam.Krier@Sun.COM 	if (!smb_pathname_validate(sr, pn) ||
39411337SWilliam.Krier@Sun.COM 	    !smb_validate_dirname(sr, pn)) {
3958934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
3968934SJose.Borrego@Sun.COM 	}
3978934SJose.Borrego@Sun.COM 
39811337SWilliam.Krier@Sun.COM 	path = pn->pn_path;
39910504SKeyur.Desai@Sun.COM 	tnode = sr->tid_tree->t_snode;
4008934SJose.Borrego@Sun.COM 
40110504SKeyur.Desai@Sun.COM 	rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode,
40210504SKeyur.Desai@Sun.COM 	    &fqi->fq_dnode, fqi->fq_last_comp);
40310504SKeyur.Desai@Sun.COM 	if (rc != 0) {
40410504SKeyur.Desai@Sun.COM 		smbsr_errno(sr, rc);
40510504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
40610504SKeyur.Desai@Sun.COM 	}
40710504SKeyur.Desai@Sun.COM 
40810504SKeyur.Desai@Sun.COM 	rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
40910504SKeyur.Desai@Sun.COM 	    tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
41010504SKeyur.Desai@Sun.COM 	smb_node_release(fqi->fq_dnode);
41110504SKeyur.Desai@Sun.COM 	if (rc != 0) {
4128934SJose.Borrego@Sun.COM 		if (rc == ENOENT)
4138934SJose.Borrego@Sun.COM 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4148934SJose.Borrego@Sun.COM 			    ERRDOS, ERROR_PATH_NOT_FOUND);
4158934SJose.Borrego@Sun.COM 		else
4168934SJose.Borrego@Sun.COM 			smbsr_errno(sr, rc);
4178934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
4188934SJose.Borrego@Sun.COM 	}
4198934SJose.Borrego@Sun.COM 
420*11963SAfshin.Ardakani@Sun.COM 	node = fqi->fq_fnode;
421*11963SAfshin.Ardakani@Sun.COM 	if (!smb_node_is_dir(node)) {
422*11963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
423*11963SAfshin.Ardakani@Sun.COM 		    ERRDOS, ERROR_PATH_NOT_FOUND);
424*11963SAfshin.Ardakani@Sun.COM 		smb_node_release(node);
4258934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
4268934SJose.Borrego@Sun.COM 	}
4278934SJose.Borrego@Sun.COM 
428*11963SAfshin.Ardakani@Sun.COM 	if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
429*11963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
430*11963SAfshin.Ardakani@Sun.COM 		smb_node_release(node);
43110504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
43210504SKeyur.Desai@Sun.COM 	}
4338934SJose.Borrego@Sun.COM 
434*11963SAfshin.Ardakani@Sun.COM 	rc = smb_fsop_access(sr, sr->user_cr, node, FILE_TRAVERSE);
43510504SKeyur.Desai@Sun.COM 
436*11963SAfshin.Ardakani@Sun.COM 	smb_node_release(node);
4378934SJose.Borrego@Sun.COM 
4388934SJose.Borrego@Sun.COM 	if (rc != 0) {
4398934SJose.Borrego@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
4408934SJose.Borrego@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
4418934SJose.Borrego@Sun.COM 		return (SDRC_ERROR);
4428934SJose.Borrego@Sun.COM 	}
4438934SJose.Borrego@Sun.COM 
4448934SJose.Borrego@Sun.COM 	rc = smbsr_encode_empty_result(sr);
4458934SJose.Borrego@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
4468934SJose.Borrego@Sun.COM }
447