xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_pathname.c (revision b24e356b384ccc80805e7150979de2373d44347c)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23c13be35aSGordon Ross  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
26bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
27da6c28aaSamw #include <smbsrv/smb_fsops.h>
28da6c28aaSamw #include <sys/pathname.h>
29da6c28aaSamw #include <sys/sdt.h>
30da6c28aaSamw 
318b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static char *smb_pathname_catia_v5tov4(smb_request_t *, char *, char *, int);
328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static char *smb_pathname_catia_v4tov5(smb_request_t *, char *, char *, int);
338b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static int smb_pathname_lookup(pathname_t *, pathname_t *, int,
349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States     vnode_t **, vnode_t *, vnode_t *, smb_attr_t *attr, cred_t *);
35fe1c642dSBill Krier static char *smb_pathname_strdup(smb_request_t *, const char *);
36fe1c642dSBill Krier static char *smb_pathname_strcat(smb_request_t *, char *, const char *);
37fe1c642dSBill Krier static void smb_pathname_preprocess(smb_request_t *, smb_pathname_t *);
389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_pathname_preprocess_quota(smb_request_t *, smb_pathname_t *);
399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_pathname_dfs_preprocess(smb_request_t *, char *, size_t);
409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_pathname_preprocess_adminshare(smb_request_t *,
419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States     smb_pathname_t *);
429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
438b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
44da6c28aaSamw uint32_t
45da6c28aaSamw smb_is_executable(char *path)
46da6c28aaSamw {
47da6c28aaSamw 	char	extension[5];
48da6c28aaSamw 	int	len = strlen(path);
49da6c28aaSamw 
50da6c28aaSamw 	if ((len >= 4) && (path[len - 4] == '.')) {
51da6c28aaSamw 		(void) strcpy(extension, &path[len - 3]);
52bbf6f00cSJordan Brown 		(void) smb_strupr(extension);
53da6c28aaSamw 
54da6c28aaSamw 		if (strcmp(extension, "EXE") == 0)
55da6c28aaSamw 			return (NODE_FLAGS_EXECUTABLE);
56da6c28aaSamw 
57da6c28aaSamw 		if (strcmp(extension, "COM") == 0)
58da6c28aaSamw 			return (NODE_FLAGS_EXECUTABLE);
59da6c28aaSamw 
60da6c28aaSamw 		if (strcmp(extension, "DLL") == 0)
61da6c28aaSamw 			return (NODE_FLAGS_EXECUTABLE);
62da6c28aaSamw 
63da6c28aaSamw 		if (strcmp(extension, "SYM") == 0)
64da6c28aaSamw 			return (NODE_FLAGS_EXECUTABLE);
65da6c28aaSamw 	}
66da6c28aaSamw 
67da6c28aaSamw 	return (0);
68da6c28aaSamw }
69da6c28aaSamw 
70da6c28aaSamw /*
71da6c28aaSamw  * smb_pathname_reduce
72da6c28aaSamw  *
73da6c28aaSamw  * smb_pathname_reduce() takes a path and returns the smb_node for the
74da6c28aaSamw  * second-to-last component of the path.  It also returns the name of the last
75da6c28aaSamw  * component.  Pointers for both of these fields must be supplied by the caller.
76da6c28aaSamw  *
77da6c28aaSamw  * Upon success, 0 is returned.
78da6c28aaSamw  *
79da6c28aaSamw  * Upon error, *dir_node will be set to 0.
80da6c28aaSamw  *
81da6c28aaSamw  * *sr (in)
82da6c28aaSamw  * ---
83da6c28aaSamw  * smb_request structure pointer
84da6c28aaSamw  *
85da6c28aaSamw  * *cred (in)
86da6c28aaSamw  * -----
87da6c28aaSamw  * credential
88da6c28aaSamw  *
89da6c28aaSamw  * *path (in)
90da6c28aaSamw  * -----
91da6c28aaSamw  * pathname to be looked up
92da6c28aaSamw  *
93da6c28aaSamw  * *share_root_node (in)
94da6c28aaSamw  * ----------------
95da6c28aaSamw  * File operations which are share-relative should pass sr->tid_tree->t_snode.
96da6c28aaSamw  * If the call is not for a share-relative operation, this parameter must be 0
97da6c28aaSamw  * (e.g. the call from smbsr_setup_share()).  (Such callers will have path
98da6c28aaSamw  * operations done using root_smb_node.)  This parameter is used to determine
99da6c28aaSamw  * whether mount points can be crossed.
100da6c28aaSamw  *
101da6c28aaSamw  * share_root_node should have at least one reference on it.  This reference
102da6c28aaSamw  * will stay intact throughout this routine.
103da6c28aaSamw  *
104da6c28aaSamw  * *cur_node (in)
105da6c28aaSamw  * ---------
106da6c28aaSamw  * The smb_node for the current directory (for relative paths).
107da6c28aaSamw  * cur_node should have at least one reference on it.
108da6c28aaSamw  * This reference will stay intact throughout this routine.
109da6c28aaSamw  *
110da6c28aaSamw  * **dir_node (out)
111da6c28aaSamw  * ----------
112da6c28aaSamw  * Directory for the penultimate component of the original path.
113da6c28aaSamw  * (Note that this is not the same as the parent directory of the ultimate
114da6c28aaSamw  * target in the case of a link.)
115da6c28aaSamw  *
116da6c28aaSamw  * The directory smb_node is returned held.  The caller will need to release
117da6c28aaSamw  * the hold or otherwise make sure it will get released (e.g. in a destroy
118da6c28aaSamw  * routine if made part of a global structure).
119da6c28aaSamw  *
120da6c28aaSamw  * last_component (out)
121da6c28aaSamw  * --------------
122da6c28aaSamw  * The last component of the path.  (This may be different from the name of any
123da6c28aaSamw  * link target to which the last component may resolve.)
124da6c28aaSamw  *
125da6c28aaSamw  *
126da6c28aaSamw  * ____________________________
127da6c28aaSamw  *
128da6c28aaSamw  * The CIFS server lookup path needs to have logic equivalent to that of
129da6c28aaSamw  * smb_fsop_lookup(), smb_vop_lookup() and other smb_vop_*() routines in the
130da6c28aaSamw  * following areas:
131da6c28aaSamw  *
1325f1ef25cSAram Hăvărneanu  *	- traversal of child mounts (handled by smb_pathname_reduce)
1335f1ef25cSAram Hăvărneanu  *	- unmangling                (handled in smb_pathname)
1345f1ef25cSAram Hăvărneanu  *	- "chroot" behavior of share root (handled by lookuppnvp)
135da6c28aaSamw  *
136da6c28aaSamw  * In addition, it needs to replace backslashes with forward slashes.  It also
137da6c28aaSamw  * ensures that link processing is done correctly, and that directory
138da6c28aaSamw  * information requested by the caller is correctly returned (i.e. for paths
139da6c28aaSamw  * with a link in the last component, the directory information of the
140da6c28aaSamw  * link and not the target needs to be returned).
141da6c28aaSamw  */
142da6c28aaSamw 
143da6c28aaSamw int
144da6c28aaSamw smb_pathname_reduce(
145da6c28aaSamw     smb_request_t	*sr,
146da6c28aaSamw     cred_t		*cred,
147da6c28aaSamw     const char		*path,
148da6c28aaSamw     smb_node_t		*share_root_node,
149da6c28aaSamw     smb_node_t		*cur_node,
150da6c28aaSamw     smb_node_t		**dir_node,
151da6c28aaSamw     char		*last_component)
152da6c28aaSamw {
153da6c28aaSamw 	smb_node_t	*root_node;
15489dc44ceSjose borrego 	pathname_t	ppn;
155da6c28aaSamw 	char		*usepath;
156da6c28aaSamw 	int		lookup_flags = FOLLOW;
157da6c28aaSamw 	int 		trailing_slash = 0;
158da6c28aaSamw 	int		err = 0;
159da6c28aaSamw 	int		len;
16089dc44ceSjose borrego 	smb_node_t	*vss_cur_node;
16189dc44ceSjose borrego 	smb_node_t	*vss_root_node;
16289dc44ceSjose borrego 	smb_node_t	*local_cur_node;
16389dc44ceSjose borrego 	smb_node_t	*local_root_node;
164da6c28aaSamw 
165da6c28aaSamw 	ASSERT(dir_node);
166da6c28aaSamw 	ASSERT(last_component);
167da6c28aaSamw 
168da6c28aaSamw 	*dir_node = NULL;
169da6c28aaSamw 	*last_component = '\0';
17089dc44ceSjose borrego 	vss_cur_node = NULL;
17189dc44ceSjose borrego 	vss_root_node = NULL;
172da6c28aaSamw 
1737b59d02dSjb 	if (sr && sr->tid_tree) {
174f96bd5c8SAlan Wright 		if (STYPE_ISIPC(sr->tid_tree->t_res_type))
1757b59d02dSjb 			return (EACCES);
1767b59d02dSjb 	}
1777b59d02dSjb 
178c8ec8eeaSjose borrego 	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
179da6c28aaSamw 		lookup_flags |= FIGNORECASE;
180da6c28aaSamw 
181da6c28aaSamw 	if (path == NULL)
182da6c28aaSamw 		return (EINVAL);
183da6c28aaSamw 
184da6c28aaSamw 	if (*path == '\0')
185da6c28aaSamw 		return (ENOENT);
186da6c28aaSamw 
187*b24e356bSPeer Dampmann 	usepath = kmem_alloc(SMB_MAXPATHLEN, KM_SLEEP);
188da6c28aaSamw 
189*b24e356bSPeer Dampmann 	len = strlcpy(usepath, path, SMB_MAXPATHLEN);
190*b24e356bSPeer Dampmann 	if (len >= SMB_MAXPATHLEN) {
191*b24e356bSPeer Dampmann 		kmem_free(usepath, SMB_MAXPATHLEN);
192da6c28aaSamw 		return (ENAMETOOLONG);
193da6c28aaSamw 	}
194da6c28aaSamw 
195da6c28aaSamw 	(void) strsubst(usepath, '\\', '/');
196da6c28aaSamw 
197da6c28aaSamw 	if (share_root_node)
198da6c28aaSamw 		root_node = share_root_node;
199da6c28aaSamw 	else
200faa1795aSjb 		root_node = sr->sr_server->si_root_smb_node;
201da6c28aaSamw 
202da6c28aaSamw 	if (cur_node == NULL)
203da6c28aaSamw 		cur_node = root_node;
204da6c28aaSamw 
20589dc44ceSjose borrego 	local_cur_node = cur_node;
20689dc44ceSjose borrego 	local_root_node = root_node;
20789dc44ceSjose borrego 
208148c5f43SAlan Wright 	if (SMB_TREE_IS_DFSROOT(sr) && (sr->smb_flg2 & SMB_FLAGS2_DFS)) {
209*b24e356bSPeer Dampmann 		err = smb_pathname_dfs_preprocess(sr, usepath, SMB_MAXPATHLEN);
2109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (err != 0) {
211*b24e356bSPeer Dampmann 			kmem_free(usepath, SMB_MAXPATHLEN);
2129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			return (err);
2139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
2149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		len = strlen(usepath);
2159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
2169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
21789dc44ceSjose borrego 	if (sr && (sr->smb_flg2 & SMB_FLAGS2_REPARSE_PATH)) {
21889dc44ceSjose borrego 		err = smb_vss_lookup_nodes(sr, root_node, cur_node,
21989dc44ceSjose borrego 		    usepath, &vss_cur_node, &vss_root_node);
22089dc44ceSjose borrego 
22189dc44ceSjose borrego 		if (err != 0) {
22289dc44ceSjose borrego 			kmem_free(usepath, MAXPATHLEN);
22389dc44ceSjose borrego 			return (err);
22489dc44ceSjose borrego 		}
22589dc44ceSjose borrego 
22689dc44ceSjose borrego 		len = strlen(usepath);
22789dc44ceSjose borrego 		local_cur_node = vss_cur_node;
22889dc44ceSjose borrego 		local_root_node = vss_root_node;
22989dc44ceSjose borrego 	}
23089dc44ceSjose borrego 
23189dc44ceSjose borrego 	if (usepath[len - 1] == '/')
23289dc44ceSjose borrego 		trailing_slash = 1;
23389dc44ceSjose borrego 
23489dc44ceSjose borrego 	(void) strcanon(usepath, "/");
23589dc44ceSjose borrego 
236*b24e356bSPeer Dampmann 	(void) pn_alloc_sz(&ppn, SMB_MAXPATHLEN);
237da6c28aaSamw 
238da6c28aaSamw 	if ((err = pn_set(&ppn, usepath)) != 0) {
239da6c28aaSamw 		(void) pn_free(&ppn);
240*b24e356bSPeer Dampmann 		kmem_free(usepath, SMB_MAXPATHLEN);
24189dc44ceSjose borrego 		if (vss_cur_node != NULL)
24289dc44ceSjose borrego 			(void) smb_node_release(vss_cur_node);
24389dc44ceSjose borrego 		if (vss_root_node != NULL)
24489dc44ceSjose borrego 			(void) smb_node_release(vss_root_node);
245da6c28aaSamw 		return (err);
246da6c28aaSamw 	}
247da6c28aaSamw 
248da6c28aaSamw 	/*
249da6c28aaSamw 	 * If a path does not have a trailing slash, strip off the
250da6c28aaSamw 	 * last component.  (We only need to return an smb_node for
251da6c28aaSamw 	 * the second to last component; a name is returned for the
252da6c28aaSamw 	 * last component.)
253da6c28aaSamw 	 */
254da6c28aaSamw 
255da6c28aaSamw 	if (trailing_slash) {
256da6c28aaSamw 		(void) strlcpy(last_component, ".", MAXNAMELEN);
257da6c28aaSamw 	} else {
258da6c28aaSamw 		(void) pn_setlast(&ppn);
259da6c28aaSamw 		(void) strlcpy(last_component, ppn.pn_path, MAXNAMELEN);
260da6c28aaSamw 		ppn.pn_path[0] = '\0';
261da6c28aaSamw 	}
262da6c28aaSamw 
263fc724630SAlan Wright 	if ((strcmp(ppn.pn_buf, "/") == 0) || (ppn.pn_buf[0] == '\0')) {
26489dc44ceSjose borrego 		smb_node_ref(local_cur_node);
26589dc44ceSjose borrego 		*dir_node = local_cur_node;
266da6c28aaSamw 	} else {
26789dc44ceSjose borrego 		err = smb_pathname(sr, ppn.pn_buf, lookup_flags,
26889dc44ceSjose borrego 		    local_root_node, local_cur_node, NULL, dir_node, cred);
269da6c28aaSamw 	}
270da6c28aaSamw 
271da6c28aaSamw 	(void) pn_free(&ppn);
272*b24e356bSPeer Dampmann 	kmem_free(usepath, SMB_MAXPATHLEN);
273da6c28aaSamw 
274da6c28aaSamw 	/*
2755f1ef25cSAram Hăvărneanu 	 * Prevent traversal to another file system if mount point
2765f1ef25cSAram Hăvărneanu 	 * traversal is disabled.
277da6c28aaSamw 	 *
278da6c28aaSamw 	 * Note that we disregard whether the traversal of the path went
279da6c28aaSamw 	 * outside of the file system and then came back (say via a link).
2805f1ef25cSAram Hăvărneanu 	 * This means that only symlinks that are expressed relatively to
2815f1ef25cSAram Hăvărneanu 	 * the share root work.
2825f1ef25cSAram Hăvărneanu 	 *
2835f1ef25cSAram Hăvărneanu 	 * share_root_node is NULL when mapping a share, so we disregard
2845f1ef25cSAram Hăvărneanu 	 * that case.
285da6c28aaSamw 	 */
286da6c28aaSamw 
287da6c28aaSamw 	if ((err == 0) && share_root_node) {
2885f1ef25cSAram Hăvărneanu 		if (share_root_node->vp->v_vfsp != (*dir_node)->vp->v_vfsp) {
289da6c28aaSamw 			err = EACCES;
2905f1ef25cSAram Hăvărneanu 			if ((sr) && (sr)->tid_tree &&
2915f1ef25cSAram Hăvărneanu 			    smb_tree_has_feature((sr)->tid_tree,
2925f1ef25cSAram Hăvărneanu 			    SMB_TREE_TRAVERSE_MOUNTS))
2935f1ef25cSAram Hăvărneanu 				err = 0;
2945f1ef25cSAram Hăvărneanu 		}
295da6c28aaSamw 	}
296da6c28aaSamw 
297da6c28aaSamw 	if (err) {
298da6c28aaSamw 		if (*dir_node) {
299da6c28aaSamw 			(void) smb_node_release(*dir_node);
300da6c28aaSamw 			*dir_node = NULL;
301da6c28aaSamw 		}
302da6c28aaSamw 		*last_component = 0;
303da6c28aaSamw 	}
304da6c28aaSamw 
30589dc44ceSjose borrego 	if (vss_cur_node != NULL)
30689dc44ceSjose borrego 		(void) smb_node_release(vss_cur_node);
30789dc44ceSjose borrego 	if (vss_root_node != NULL)
30889dc44ceSjose borrego 		(void) smb_node_release(vss_root_node);
30989dc44ceSjose borrego 
310da6c28aaSamw 	return (err);
311da6c28aaSamw }
312da6c28aaSamw 
313da6c28aaSamw /*
3148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * smb_pathname()
3158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * wrapper to lookuppnvp().  Handles name unmangling.
316da6c28aaSamw  *
317da6c28aaSamw  * *dir_node is the true directory of the target *node.
318da6c28aaSamw  *
319da6c28aaSamw  * If any component but the last in the path is not found, ENOTDIR instead of
320da6c28aaSamw  * ENOENT will be returned.
321da6c28aaSamw  *
322da6c28aaSamw  * Path components are processed one at a time so that smb_nodes can be
3231fcced4cSJordan Brown  * created for each component.  This allows the n_dnode field in the
324da6c28aaSamw  * smb_node to be properly populated.
325da6c28aaSamw  *
3268b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * Because of the above, links are also processed in this routine
3278b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * (i.e., we do not pass the FOLLOW flag to lookuppnvp()).  This
3288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * will allow smb_nodes to be created for each component of a link.
3298b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  *
3308b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * Mangle checking is per component. If a name is mangled, when the
3318b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * unmangled name is passed to smb_pathname_lookup() do not pass
3328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * FIGNORECASE, since the unmangled name is the real on-disk name.
3338b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * Otherwise pass FIGNORECASE if it's set in flags. This will cause the
3348b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * file system to return "first match" in the event of a case collision.
3358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  *
3368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * If CATIA character translation is enabled it is applied to each
3378b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * component before passing the component to smb_pathname_lookup().
3388b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * After smb_pathname_lookup() the reverse translation is applied.
339da6c28aaSamw  */
340da6c28aaSamw 
341da6c28aaSamw int
3428b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname(smb_request_t *sr, char *path, int flags,
3438b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States     smb_node_t *root_node, smb_node_t *cur_node, smb_node_t **dir_node,
3448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States     smb_node_t **ret_node, cred_t *cred)
345da6c28aaSamw {
3468b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	char		*component, *real_name, *namep;
3478b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	pathname_t	pn, rpn, upn, link_pn;
3488b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_t	*dnode, *fnode;
3499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_attr_t	attr;
3508b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	vnode_t		*rootvp, *vp;
351da6c28aaSamw 	size_t		pathleft;
352da6c28aaSamw 	int		err = 0;
353da6c28aaSamw 	int		nlink = 0;
354da6c28aaSamw 	int		local_flags;
355e3f2c991SKeyur Desai 	uint32_t	abe_flag = 0;
3568b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	char		namebuf[MAXNAMELEN];
357da6c28aaSamw 
358da6c28aaSamw 	if (path == NULL)
359da6c28aaSamw 		return (EINVAL);
360da6c28aaSamw 
361da6c28aaSamw 	ASSERT(root_node);
362da6c28aaSamw 	ASSERT(cur_node);
363da6c28aaSamw 	ASSERT(ret_node);
364da6c28aaSamw 
365da6c28aaSamw 	*ret_node = NULL;
366da6c28aaSamw 
367da6c28aaSamw 	if (dir_node)
368da6c28aaSamw 		*dir_node = NULL;
369da6c28aaSamw 
370*b24e356bSPeer Dampmann 	(void) pn_alloc_sz(&upn, SMB_MAXPATHLEN);
371da6c28aaSamw 
372da6c28aaSamw 	if ((err = pn_set(&upn, path)) != 0) {
373da6c28aaSamw 		(void) pn_free(&upn);
374da6c28aaSamw 		return (err);
375da6c28aaSamw 	}
376da6c28aaSamw 
377e3f2c991SKeyur Desai 	if (SMB_TREE_SUPPORTS_ABE(sr))
378e3f2c991SKeyur Desai 		abe_flag = SMB_ABE;
379e3f2c991SKeyur Desai 
380da6c28aaSamw 	(void) pn_alloc(&pn);
381da6c28aaSamw 	(void) pn_alloc(&rpn);
382da6c28aaSamw 
383da6c28aaSamw 	component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
384da6c28aaSamw 	real_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
385da6c28aaSamw 
3868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	fnode = NULL;
387da6c28aaSamw 	dnode = cur_node;
388da6c28aaSamw 	smb_node_ref(dnode);
3898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	rootvp = root_node->vp;
39055bf511dSas 
391da6c28aaSamw 	while ((pathleft = pn_pathleft(&upn)) != 0) {
392da6c28aaSamw 		if (fnode) {
393da6c28aaSamw 			smb_node_release(dnode);
394da6c28aaSamw 			dnode = fnode;
395da6c28aaSamw 			fnode = NULL;
396da6c28aaSamw 		}
397da6c28aaSamw 
398da6c28aaSamw 		if ((err = pn_getcomponent(&upn, component)) != 0)
399da6c28aaSamw 			break;
400da6c28aaSamw 
4018b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if ((namep = smb_pathname_catia_v5tov4(sr, component,
4028b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		    namebuf, sizeof (namebuf))) == NULL) {
4038b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			err = EILSEQ;
4048b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			break;
405da6c28aaSamw 		}
406da6c28aaSamw 
407da6c28aaSamw 		if ((err = pn_set(&pn, namep)) != 0)
408da6c28aaSamw 			break;
409da6c28aaSamw 
4108b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		local_flags = flags & FIGNORECASE;
4118b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		err = smb_pathname_lookup(&pn, &rpn, local_flags,
4129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    &vp, rootvp, dnode->vp, &attr, cred);
413da6c28aaSamw 
4148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (err) {
415cb174861Sjoyce mcintosh 			if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
416cb174861Sjoyce mcintosh 			    !smb_maybe_mangled(component))
4178b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				break;
4188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
419148c5f43SAlan Wright 			if ((err = smb_unmangle(dnode, component,
420e3f2c991SKeyur Desai 			    real_name, MAXNAMELEN, abe_flag)) != 0)
4218b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				break;
422da6c28aaSamw 
4238b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			if ((namep = smb_pathname_catia_v5tov4(sr, real_name,
4248b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			    namebuf, sizeof (namebuf))) == NULL) {
4258b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				err = EILSEQ;
4268b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				break;
4278b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			}
428da6c28aaSamw 
4298b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			if ((err = pn_set(&pn, namep)) != 0)
4308b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				break;
4318b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
4328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			local_flags = 0;
4338b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			err = smb_pathname_lookup(&pn, &rpn, local_flags,
4349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			    &vp, rootvp, dnode->vp, &attr, cred);
4358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			if (err)
4368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				break;
4378b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		}
438da6c28aaSamw 
4399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		/*
4409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 * This check MUST be done before symlink check
4419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 * since a reparse point is of type VLNK but should
4429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 * not be handled like a regular symlink.
4439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 */
4449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) {
4459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			err = EREMOTE;
4469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			VN_RELE(vp);
4479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			break;
4489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		}
4499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
450da6c28aaSamw 		if ((vp->v_type == VLNK) &&
451da6c28aaSamw 		    ((flags & FOLLOW) || pn_pathleft(&upn))) {
452da6c28aaSamw 
453da6c28aaSamw 			if (++nlink > MAXSYMLINKS) {
454da6c28aaSamw 				err = ELOOP;
4557f667e74Sjose borrego 				VN_RELE(vp);
456da6c28aaSamw 				break;
457da6c28aaSamw 			}
458da6c28aaSamw 
459da6c28aaSamw 			(void) pn_alloc(&link_pn);
460da6c28aaSamw 			err = pn_getsymlink(vp, &link_pn, cred);
4617f667e74Sjose borrego 			VN_RELE(vp);
462da6c28aaSamw 
4638b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			if (err == 0) {
4648b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				if (pn_pathleft(&link_pn) == 0)
4658b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 					(void) pn_set(&link_pn, ".");
4668b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				err = pn_insert(&upn, &link_pn,
4678b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				    strlen(component));
468da6c28aaSamw 			}
469da6c28aaSamw 			pn_free(&link_pn);
470da6c28aaSamw 
471da6c28aaSamw 			if (err)
472da6c28aaSamw 				break;
473da6c28aaSamw 
474da6c28aaSamw 			if (upn.pn_pathlen == 0) {
475da6c28aaSamw 				err = ENOENT;
476da6c28aaSamw 				break;
477da6c28aaSamw 			}
478da6c28aaSamw 
479da6c28aaSamw 			if (upn.pn_path[0] == '/') {
480da6c28aaSamw 				fnode = root_node;
481da6c28aaSamw 				smb_node_ref(fnode);
482da6c28aaSamw 			}
483da6c28aaSamw 
484da6c28aaSamw 			if (pn_fixslash(&upn))
485da6c28aaSamw 				flags |= FOLLOW;
486da6c28aaSamw 
487da6c28aaSamw 		} else {
488da6c28aaSamw 			if (flags & FIGNORECASE) {
489da6c28aaSamw 				if (strcmp(rpn.pn_path, "/") != 0)
490da6c28aaSamw 					pn_setlast(&rpn);
491da6c28aaSamw 				namep = rpn.pn_path;
4928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			} else {
493da6c28aaSamw 				namep = pn.pn_path;
4948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			}
4958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
4968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			namep = smb_pathname_catia_v4tov5(sr, namep,
4978b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			    namebuf, sizeof (namebuf));
498da6c28aaSamw 
499da6c28aaSamw 			fnode = smb_node_lookup(sr, NULL, cred, vp, namep,
500037cac00Sjoyce mcintosh 			    dnode, NULL);
5017f667e74Sjose borrego 			VN_RELE(vp);
502da6c28aaSamw 
503da6c28aaSamw 			if (fnode == NULL) {
504da6c28aaSamw 				err = ENOMEM;
505da6c28aaSamw 				break;
506da6c28aaSamw 			}
507da6c28aaSamw 		}
508da6c28aaSamw 
509da6c28aaSamw 		while (upn.pn_path[0] == '/') {
510da6c28aaSamw 			upn.pn_path++;
511da6c28aaSamw 			upn.pn_pathlen--;
512da6c28aaSamw 		}
5137f667e74Sjose borrego 
514da6c28aaSamw 	}
515da6c28aaSamw 
516da6c28aaSamw 	if ((pathleft) && (err == ENOENT))
517da6c28aaSamw 		err = ENOTDIR;
518da6c28aaSamw 
519da6c28aaSamw 	if (err) {
520da6c28aaSamw 		if (fnode)
521da6c28aaSamw 			smb_node_release(fnode);
522da6c28aaSamw 		if (dnode)
523da6c28aaSamw 			smb_node_release(dnode);
524da6c28aaSamw 	} else {
525da6c28aaSamw 		*ret_node = fnode;
526da6c28aaSamw 
527da6c28aaSamw 		if (dir_node)
528da6c28aaSamw 			*dir_node = dnode;
529da6c28aaSamw 		else
530da6c28aaSamw 			smb_node_release(dnode);
531da6c28aaSamw 	}
532da6c28aaSamw 
533da6c28aaSamw 	kmem_free(component, MAXNAMELEN);
534da6c28aaSamw 	kmem_free(real_name, MAXNAMELEN);
535da6c28aaSamw 	(void) pn_free(&pn);
536da6c28aaSamw 	(void) pn_free(&rpn);
537da6c28aaSamw 	(void) pn_free(&upn);
538da6c28aaSamw 
539da6c28aaSamw 	return (err);
540da6c28aaSamw }
54189dc44ceSjose borrego 
5428b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States /*
5438b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * Holds on dvp and rootvp (if not rootdir) are required by lookuppnvp()
5448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * and will be released within lookuppnvp().
5458b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  */
5468b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static int
5478b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_lookup(pathname_t *pn, pathname_t *rpn, int flags,
5489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States     vnode_t **vp, vnode_t *rootvp, vnode_t *dvp, smb_attr_t *attr, cred_t *cred)
5498b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States {
5508b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	int err;
5518b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
5528b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	*vp = NULL;
5538b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	VN_HOLD(dvp);
5548b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (rootvp != rootdir)
5558b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		VN_HOLD(rootvp);
5568b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
5578b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	err = lookuppnvp(pn, rpn, flags, NULL, vp, rootvp, dvp, cred);
5589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((err == 0) && (attr != NULL))
5598622ec45SGordon Ross 		(void) smb_vop_getattr(*vp, NULL, attr, 0, zone_kcred());
5609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
5618b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	return (err);
5628b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
5638b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
5648b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States /*
5658b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * CATIA Translation of a pathname component prior to passing it to lookuppnvp
5668b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  *
5678b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * If the translated component name contains a '/' NULL is returned.
5688b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * The caller should treat this as error EILSEQ. It is not valid to
5698b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * have a directory name with a '/'.
5708b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  */
5718b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static char *
5728b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_catia_v5tov4(smb_request_t *sr, char *name,
5738b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States     char *namebuf, int buflen)
5748b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States {
5758b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	char *namep;
5768b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
5778b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (SMB_TREE_SUPPORTS_CATIA(sr)) {
5788b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		namep = smb_vop_catia_v5tov4(name, namebuf, buflen);
5798b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (strchr(namep, '/') != NULL)
5808b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			return (NULL);
5818b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		return (namep);
5828b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
5838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
5848b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	return (name);
5858b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
5868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
5878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States /*
5888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * CATIA translation of a pathname component after returning from lookuppnvp
5898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  */
5908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static char *
5918b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_catia_v4tov5(smb_request_t *sr, char *name,
5928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States     char *namebuf, int buflen)
5938b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States {
5948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (SMB_TREE_SUPPORTS_CATIA(sr)) {
5958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_vop_catia_v4tov5(name, namebuf, buflen);
5968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		return (namebuf);
5978b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
5988b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
5998b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	return (name);
6008b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
6018b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
60289dc44ceSjose borrego /*
60389dc44ceSjose borrego  * sr - needed to check for case sense
60489dc44ceSjose borrego  * path - non mangled path needed to be looked up from the startvp
60589dc44ceSjose borrego  * startvp - the vnode to start the lookup from
60689dc44ceSjose borrego  * rootvp - the vnode of the root of the filesystem
60789dc44ceSjose borrego  * returns the vnode found when starting at startvp and using the path
60889dc44ceSjose borrego  *
60989dc44ceSjose borrego  * Finds a vnode starting at startvp and parsing the non mangled path
61089dc44ceSjose borrego  */
61189dc44ceSjose borrego 
61289dc44ceSjose borrego vnode_t *
61389dc44ceSjose borrego smb_lookuppathvptovp(smb_request_t *sr, char *path, vnode_t *startvp,
61489dc44ceSjose borrego     vnode_t *rootvp)
61589dc44ceSjose borrego {
61689dc44ceSjose borrego 	pathname_t pn;
61789dc44ceSjose borrego 	vnode_t *vp = NULL;
61889dc44ceSjose borrego 	int lookup_flags = FOLLOW;
61989dc44ceSjose borrego 
62089dc44ceSjose borrego 	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
62189dc44ceSjose borrego 		lookup_flags |= FIGNORECASE;
62289dc44ceSjose borrego 
62389dc44ceSjose borrego 	(void) pn_alloc(&pn);
62489dc44ceSjose borrego 
62589dc44ceSjose borrego 	if (pn_set(&pn, path) == 0) {
626037cac00Sjoyce mcintosh 		VN_HOLD(startvp);
62789dc44ceSjose borrego 		if (rootvp != rootdir)
62889dc44ceSjose borrego 			VN_HOLD(rootvp);
62989dc44ceSjose borrego 
63089dc44ceSjose borrego 		/* lookuppnvp should release the holds */
63189dc44ceSjose borrego 		if (lookuppnvp(&pn, NULL, lookup_flags, NULL, &vp,
6328622ec45SGordon Ross 		    rootvp, startvp, zone_kcred()) != 0) {
63389dc44ceSjose borrego 			pn_free(&pn);
63489dc44ceSjose borrego 			return (NULL);
63589dc44ceSjose borrego 		}
63689dc44ceSjose borrego 	}
63789dc44ceSjose borrego 
63889dc44ceSjose borrego 	pn_free(&pn);
63989dc44ceSjose borrego 	return (vp);
64089dc44ceSjose borrego }
641fe1c642dSBill Krier 
642fe1c642dSBill Krier /*
643fe1c642dSBill Krier  * smb_pathname_init
644fe1c642dSBill Krier  * Parse path: pname\\fname:sname:stype
645fe1c642dSBill Krier  *
646fe1c642dSBill Krier  * Elements of the smb_pathname_t structure are allocated using request
647fe1c642dSBill Krier  * specific storage and will be free'd when the sr is destroyed.
648fe1c642dSBill Krier  *
649fe1c642dSBill Krier  * Populate pn structure elements with the individual elements
650fe1c642dSBill Krier  * of pn->pn_path. pn->pn_sname will contain the whole stream name
651fe1c642dSBill Krier  * including the stream type and preceding colon: :sname:%DATA
652fe1c642dSBill Krier  * pn_stype will point to the stream type within pn_sname.
653fe1c642dSBill Krier  *
6549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * If the pname element is missing pn_pname will be set to NULL.
655fe1c642dSBill Krier  * If any other element is missing the pointer in pn will be NULL.
656fe1c642dSBill Krier  */
657fe1c642dSBill Krier void
658fe1c642dSBill Krier smb_pathname_init(smb_request_t *sr, smb_pathname_t *pn, char *path)
659fe1c642dSBill Krier {
660fe1c642dSBill Krier 	char *pname, *fname, *sname;
661fe1c642dSBill Krier 	int len;
662fe1c642dSBill Krier 
663fe1c642dSBill Krier 	bzero(pn, sizeof (smb_pathname_t));
664fe1c642dSBill Krier 	pn->pn_path = smb_pathname_strdup(sr, path);
665fe1c642dSBill Krier 
666fe1c642dSBill Krier 	smb_pathname_preprocess(sr, pn);
667fe1c642dSBill Krier 
668fe1c642dSBill Krier 	/* parse pn->pn_path into its constituent parts */
669fe1c642dSBill Krier 	pname = pn->pn_path;
670fe1c642dSBill Krier 	fname = strrchr(pn->pn_path, '\\');
671fe1c642dSBill Krier 
672fe1c642dSBill Krier 	if (fname) {
673fe1c642dSBill Krier 		if (fname == pname) {
6749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			pn->pn_pname = NULL;
675fe1c642dSBill Krier 		} else {
676fe1c642dSBill Krier 			*fname = '\0';
677fe1c642dSBill Krier 			pn->pn_pname =
678fe1c642dSBill Krier 			    smb_pathname_strdup(sr, pname);
679fe1c642dSBill Krier 			*fname = '\\';
680fe1c642dSBill Krier 		}
681fe1c642dSBill Krier 		++fname;
682fe1c642dSBill Krier 	} else {
683fe1c642dSBill Krier 		fname = pname;
6849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		pn->pn_pname = NULL;
685fe1c642dSBill Krier 	}
686fe1c642dSBill Krier 
687fe1c642dSBill Krier 	if (fname[0] == '\0') {
688fe1c642dSBill Krier 		pn->pn_fname = NULL;
689fe1c642dSBill Krier 		return;
690fe1c642dSBill Krier 	}
691fe1c642dSBill Krier 
692fe1c642dSBill Krier 	if (!smb_is_stream_name(fname)) {
693fe1c642dSBill Krier 		pn->pn_fname = smb_pathname_strdup(sr, fname);
694fe1c642dSBill Krier 		return;
695fe1c642dSBill Krier 	}
696fe1c642dSBill Krier 
697fe1c642dSBill Krier 	/*
698fe1c642dSBill Krier 	 * find sname and stype in fname.
699fe1c642dSBill Krier 	 * sname can't be NULL smb_is_stream_name checks this
700fe1c642dSBill Krier 	 */
701fe1c642dSBill Krier 	sname = strchr(fname, ':');
702fe1c642dSBill Krier 	if (sname == fname)
703fe1c642dSBill Krier 		fname = NULL;
704fe1c642dSBill Krier 	else {
705fe1c642dSBill Krier 		*sname = '\0';
706fe1c642dSBill Krier 		pn->pn_fname =
707fe1c642dSBill Krier 		    smb_pathname_strdup(sr, fname);
708fe1c642dSBill Krier 		*sname = ':';
709fe1c642dSBill Krier 	}
710fe1c642dSBill Krier 
711fe1c642dSBill Krier 	pn->pn_sname = smb_pathname_strdup(sr, sname);
712fe1c642dSBill Krier 	pn->pn_stype = strchr(pn->pn_sname + 1, ':');
713fe1c642dSBill Krier 	if (pn->pn_stype) {
714fe1c642dSBill Krier 		(void) smb_strupr(pn->pn_stype);
715fe1c642dSBill Krier 	} else {
716fe1c642dSBill Krier 		len = strlen(pn->pn_sname);
717fe1c642dSBill Krier 		pn->pn_sname = smb_pathname_strcat(sr, pn->pn_sname, ":$DATA");
718fe1c642dSBill Krier 		pn->pn_stype = pn->pn_sname + len;
719fe1c642dSBill Krier 	}
720fe1c642dSBill Krier 	++pn->pn_stype;
721fe1c642dSBill Krier }
722fe1c642dSBill Krier 
723fe1c642dSBill Krier /*
724fe1c642dSBill Krier  * smb_pathname_preprocess
725fe1c642dSBill Krier  *
726fe1c642dSBill Krier  * Perform common pre-processing of pn->pn_path:
727fe1c642dSBill Krier  * - if the pn_path is blank, set it to '\\'
728fe1c642dSBill Krier  * - perform unicode wildcard converstion.
729fe1c642dSBill Krier  * - convert any '/' to '\\'
730fe1c642dSBill Krier  * - eliminate duplicate slashes
731fe1c642dSBill Krier  * - remove trailing slashes
7329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * - quota directory specific pre-processing
733fe1c642dSBill Krier  */
734fe1c642dSBill Krier static void
735fe1c642dSBill Krier smb_pathname_preprocess(smb_request_t *sr, smb_pathname_t *pn)
736fe1c642dSBill Krier {
737fe1c642dSBill Krier 	char *p;
738fe1c642dSBill Krier 
739fe1c642dSBill Krier 	/* treat empty path as "\\" */
740fe1c642dSBill Krier 	if (strlen(pn->pn_path) == 0) {
741fe1c642dSBill Krier 		pn->pn_path = smb_pathname_strdup(sr, "\\");
742fe1c642dSBill Krier 		return;
743fe1c642dSBill Krier 	}
744fe1c642dSBill Krier 
745c13be35aSGordon Ross 	if (sr->session->dialect < NT_LM_0_12)
746c13be35aSGordon Ross 		smb_convert_wildcards(pn->pn_path);
747fe1c642dSBill Krier 
748fe1c642dSBill Krier 	/* treat '/' as '\\' */
749fe1c642dSBill Krier 	(void) strsubst(pn->pn_path, '/', '\\');
750fe1c642dSBill Krier 
751fe1c642dSBill Krier 	(void) strcanon(pn->pn_path, "\\");
752fe1c642dSBill Krier 
753fe1c642dSBill Krier 	/* remove trailing '\\' */
754fe1c642dSBill Krier 	p = pn->pn_path + strlen(pn->pn_path) - 1;
755fe1c642dSBill Krier 	if ((p != pn->pn_path) && (*p == '\\'))
756fe1c642dSBill Krier 		*p = '\0';
7579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_pathname_preprocess_quota(sr, pn);
7599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_pathname_preprocess_adminshare(sr, pn);
7609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
7639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * smb_pathname_preprocess_quota
7649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
7659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * There is a special file required by windows so that the quota
7669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * tab will be displayed by windows clients. This is created in
7679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * a special directory, $EXTEND, at the root of the shared file
7689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * system. To hide this directory prepend a '.' (dot).
7699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
7709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
7719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_preprocess_quota(smb_request_t *sr, smb_pathname_t *pn)
7729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *name = "$EXTEND";
7749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *new_name = ".$EXTEND";
7759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *p, *slash;
7769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int len;
7779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (!smb_node_is_vfsroot(sr->tid_tree->t_snode))
7799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return;
7809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	p = pn->pn_path;
7829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	/* ignore any initial "\\" */
7849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	p += strspn(p, "\\");
7859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smb_strcasecmp(p, name, strlen(name)) != 0)
7869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return;
7879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	p += strlen(name);
7899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((*p != ':') && (*p != '\\') && (*p != '\0'))
7909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return;
7919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	slash = (pn->pn_path[0] == '\\') ? "\\" : "";
7939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	len = strlen(pn->pn_path) + 2;
7949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	pn->pn_path = smb_srm_alloc(sr, len);
7959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) snprintf(pn->pn_path, len, "%s%s%s", slash, new_name, p);
7969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) smb_strupr(pn->pn_path);
7979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
7989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
8009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * smb_pathname_preprocess_adminshare
8019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
8029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Convert any path with share name "C$" or "c$" (Admin share) in to lower case.
8039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
8049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
8059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_preprocess_adminshare(smb_request_t *sr, smb_pathname_t *pn)
8069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
8079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (strcasecmp(sr->tid_tree->t_sharename, "c$") == 0)
8089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_strlwr(pn->pn_path);
809fe1c642dSBill Krier }
810fe1c642dSBill Krier 
811fe1c642dSBill Krier /*
812fe1c642dSBill Krier  * smb_pathname_strdup
813fe1c642dSBill Krier  *
814fe1c642dSBill Krier  * Duplicate NULL terminated string s.
815fe1c642dSBill Krier  *
816fe1c642dSBill Krier  * The new string is allocated using request specific storage and will
817fe1c642dSBill Krier  * be free'd when the sr is destroyed.
818fe1c642dSBill Krier  */
819fe1c642dSBill Krier static char *
820fe1c642dSBill Krier smb_pathname_strdup(smb_request_t *sr, const char *s)
821fe1c642dSBill Krier {
822fe1c642dSBill Krier 	char *s2;
823fe1c642dSBill Krier 	size_t n;
824fe1c642dSBill Krier 
825fe1c642dSBill Krier 	n = strlen(s) + 1;
8269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	s2 = smb_srm_zalloc(sr, n);
827fe1c642dSBill Krier 	(void) strlcpy(s2, s, n);
828fe1c642dSBill Krier 	return (s2);
829fe1c642dSBill Krier }
830fe1c642dSBill Krier 
831fe1c642dSBill Krier /*
832fe1c642dSBill Krier  * smb_pathname_strcat
833fe1c642dSBill Krier  *
834fe1c642dSBill Krier  * Reallocate NULL terminated string s1 to accommodate
835fe1c642dSBill Krier  * concatenating  NULL terminated string s2.
836fe1c642dSBill Krier  * Append s2 and return resulting NULL terminated string.
837fe1c642dSBill Krier  *
838fe1c642dSBill Krier  * The string buffer is reallocated using request specific
839fe1c642dSBill Krier  * storage and will be free'd when the sr is destroyed.
840fe1c642dSBill Krier  */
841fe1c642dSBill Krier static char *
842fe1c642dSBill Krier smb_pathname_strcat(smb_request_t *sr, char *s1, const char *s2)
843fe1c642dSBill Krier {
844fe1c642dSBill Krier 	size_t n;
845fe1c642dSBill Krier 
846fe1c642dSBill Krier 	n = strlen(s1) + strlen(s2) + 1;
8479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	s1 = smb_srm_rezalloc(sr, s1, n);
848fe1c642dSBill Krier 	(void) strlcat(s1, s2, n);
849fe1c642dSBill Krier 	return (s1);
850fe1c642dSBill Krier }
851fe1c642dSBill Krier 
852fe1c642dSBill Krier /*
853fe1c642dSBill Krier  * smb_pathname_validate
854fe1c642dSBill Krier  *
855fe1c642dSBill Krier  * Perform basic validation of pn:
856fe1c642dSBill Krier  * - If first component of pn->path is ".." -> PATH_SYNTAX_BAD
857fe1c642dSBill Krier  * - If there are wildcards in pn->pn_pname -> OBJECT_NAME_INVALID
858fe1c642dSBill Krier  * - If fname is "." -> INVALID_OBJECT_NAME
859fe1c642dSBill Krier  *
860fe1c642dSBill Krier  * On unix .. at the root of a file system links to the root. Thus
861fe1c642dSBill Krier  * an attempt to lookup "/../../.." will be the same as looking up "/"
862fe1c642dSBill Krier  * CIFs clients expect the above to result in
863fe1c642dSBill Krier  * NT_STATUS_OBJECT_PATH_SYNTAX_BAD. It is currently not possible
864fe1c642dSBill Krier  * (and questionable if it's desirable) to deal with all cases
865fe1c642dSBill Krier  * but paths beginning with \\.. are handled.
866fe1c642dSBill Krier  *
867fe1c642dSBill Krier  * Returns: B_TRUE if pn is valid,
868fe1c642dSBill Krier  *          otherwise returns B_FALSE and sets error status in sr.
869fe1c642dSBill Krier  */
870fe1c642dSBill Krier boolean_t
871fe1c642dSBill Krier smb_pathname_validate(smb_request_t *sr, smb_pathname_t *pn)
872fe1c642dSBill Krier {
873fe1c642dSBill Krier 	char *path = pn->pn_path;
874fe1c642dSBill Krier 
875fe1c642dSBill Krier 	/* ignore any initial "\\" */
876fe1c642dSBill Krier 	path += strspn(path, "\\");
877fe1c642dSBill Krier 
878fe1c642dSBill Krier 	/* If first component of path is ".." -> PATH_SYNTAX_BAD */
879fe1c642dSBill Krier 	if ((strcmp(path, "..") == 0) || (strncmp(path, "..\\", 3) == 0)) {
880fe1c642dSBill Krier 		smbsr_error(sr, NT_STATUS_OBJECT_PATH_SYNTAX_BAD,
881fe1c642dSBill Krier 		    ERRDOS, ERROR_BAD_PATHNAME);
882fe1c642dSBill Krier 		return (B_FALSE);
883fe1c642dSBill Krier 	}
884fe1c642dSBill Krier 
885fe1c642dSBill Krier 	/* If there are wildcards in pn->pn_pname -> OBJECT_NAME_INVALID */
886fe1c642dSBill Krier 	if (pn->pn_pname && smb_contains_wildcards(pn->pn_pname)) {
887fe1c642dSBill Krier 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
888fe1c642dSBill Krier 		    ERRDOS, ERROR_INVALID_NAME);
889fe1c642dSBill Krier 		return (B_FALSE);
890fe1c642dSBill Krier 	}
891fe1c642dSBill Krier 
892fe1c642dSBill Krier 	/* If fname is "." -> INVALID_OBJECT_NAME */
893fe1c642dSBill Krier 	if (pn->pn_fname && (strcmp(pn->pn_fname, ".") == 0)) {
894fe1c642dSBill Krier 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
895fe1c642dSBill Krier 		    ERRDOS, ERROR_PATH_NOT_FOUND);
896fe1c642dSBill Krier 		return (B_FALSE);
897fe1c642dSBill Krier 	}
898fe1c642dSBill Krier 
899fe1c642dSBill Krier 	return (B_TRUE);
900fe1c642dSBill Krier }
901fe1c642dSBill Krier 
902fe1c642dSBill Krier /*
903fe1c642dSBill Krier  * smb_validate_dirname
904fe1c642dSBill Krier  *
905fe1c642dSBill Krier  * smb_pathname_validate() should have already been performed on pn.
906fe1c642dSBill Krier  *
907fe1c642dSBill Krier  * Very basic directory name validation:  checks for colons in a path.
908fe1c642dSBill Krier  * Need to skip the drive prefix since it contains a colon.
909fe1c642dSBill Krier  *
910fe1c642dSBill Krier  * Returns: B_TRUE if the name is valid,
911fe1c642dSBill Krier  *          otherwise returns B_FALSE and sets error status in sr.
912fe1c642dSBill Krier  */
913fe1c642dSBill Krier boolean_t
914fe1c642dSBill Krier smb_validate_dirname(smb_request_t *sr, smb_pathname_t *pn)
915fe1c642dSBill Krier {
916fe1c642dSBill Krier 	char *name;
917fe1c642dSBill Krier 	char *path = pn->pn_path;
918fe1c642dSBill Krier 
919fe1c642dSBill Krier 	if ((name = path) != 0) {
920fe1c642dSBill Krier 		name += strspn(name, "\\");
921fe1c642dSBill Krier 
922fe1c642dSBill Krier 		if (strchr(name, ':') != 0) {
923fe1c642dSBill Krier 			smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
924fe1c642dSBill Krier 			    ERRDOS, ERROR_INVALID_NAME);
925fe1c642dSBill Krier 			return (B_FALSE);
926fe1c642dSBill Krier 		}
927fe1c642dSBill Krier 	}
928fe1c642dSBill Krier 
929fe1c642dSBill Krier 	return (B_TRUE);
930fe1c642dSBill Krier }
931fe1c642dSBill Krier 
932fe1c642dSBill Krier /*
933fe1c642dSBill Krier  * smb_validate_object_name
934fe1c642dSBill Krier  *
935fe1c642dSBill Krier  * smb_pathname_validate() should have already been pertformed on pn.
936fe1c642dSBill Krier  *
937fe1c642dSBill Krier  * Very basic file name validation.
938fe1c642dSBill Krier  * For filenames, we check for names of the form "AAAn:". Names that
939fe1c642dSBill Krier  * contain three characters, a single digit and a colon (:) are reserved
940fe1c642dSBill Krier  * as DOS device names, i.e. "COM1:".
941fe1c642dSBill Krier  * Stream name validation is handed off to smb_validate_stream_name
942fe1c642dSBill Krier  *
943fe1c642dSBill Krier  * Returns: B_TRUE if pn->pn_fname is valid,
944fe1c642dSBill Krier  *          otherwise returns B_FALSE and sets error status in sr.
945fe1c642dSBill Krier  */
946fe1c642dSBill Krier boolean_t
947fe1c642dSBill Krier smb_validate_object_name(smb_request_t *sr, smb_pathname_t *pn)
948fe1c642dSBill Krier {
949fe1c642dSBill Krier 	if (pn->pn_fname &&
950fe1c642dSBill Krier 	    strlen(pn->pn_fname) == 5 &&
951fe1c642dSBill Krier 	    smb_isdigit(pn->pn_fname[3]) &&
952fe1c642dSBill Krier 	    pn->pn_fname[4] == ':') {
953fe1c642dSBill Krier 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
954fe1c642dSBill Krier 		    ERRDOS, ERROR_INVALID_NAME);
955fe1c642dSBill Krier 		return (B_FALSE);
956fe1c642dSBill Krier 	}
957fe1c642dSBill Krier 
958fe1c642dSBill Krier 	if (pn->pn_sname)
959fe1c642dSBill Krier 		return (smb_validate_stream_name(sr, pn));
960fe1c642dSBill Krier 
961fe1c642dSBill Krier 	return (B_TRUE);
962fe1c642dSBill Krier }
963fe1c642dSBill Krier 
964fe1c642dSBill Krier /*
965fe1c642dSBill Krier  * smb_stream_parse_name
966fe1c642dSBill Krier  *
967fe1c642dSBill Krier  * smb_stream_parse_name should only be called for a path that
968fe1c642dSBill Krier  * contains a valid named stream.  Path validation should have
969fe1c642dSBill Krier  * been performed before this function is called.
970fe1c642dSBill Krier  *
971fe1c642dSBill Krier  * Find the last component of path and split it into filename
972fe1c642dSBill Krier  * and stream name.
973fe1c642dSBill Krier  *
974fe1c642dSBill Krier  * On return the named stream type will be present.  The stream
975fe1c642dSBill Krier  * type defaults to ":$DATA", if it has not been defined
976fe1c642dSBill Krier  * For exmaple, 'stream' contains :<sname>:$DATA
977fe1c642dSBill Krier  */
978fe1c642dSBill Krier void
979fe1c642dSBill Krier smb_stream_parse_name(char *path, char *filename, char *stream)
980fe1c642dSBill Krier {
981fe1c642dSBill Krier 	char *fname, *sname, *stype;
982fe1c642dSBill Krier 
983fe1c642dSBill Krier 	ASSERT(path);
984fe1c642dSBill Krier 	ASSERT(filename);
985fe1c642dSBill Krier 	ASSERT(stream);
986fe1c642dSBill Krier 
987fe1c642dSBill Krier 	fname = strrchr(path, '\\');
988fe1c642dSBill Krier 	fname = (fname == NULL) ? path : fname + 1;
989fe1c642dSBill Krier 	(void) strlcpy(filename, fname, MAXNAMELEN);
990fe1c642dSBill Krier 
991fe1c642dSBill Krier 	sname = strchr(filename, ':');
992fe1c642dSBill Krier 	(void) strlcpy(stream, sname, MAXNAMELEN);
993fe1c642dSBill Krier 	*sname = '\0';
994fe1c642dSBill Krier 
995fe1c642dSBill Krier 	stype = strchr(stream + 1, ':');
996fe1c642dSBill Krier 	if (stype == NULL)
997fe1c642dSBill Krier 		(void) strlcat(stream, ":$DATA", MAXNAMELEN);
998fe1c642dSBill Krier 	else
999fe1c642dSBill Krier 		(void) smb_strupr(stype);
1000fe1c642dSBill Krier }
1001fe1c642dSBill Krier 
1002fe1c642dSBill Krier /*
1003fe1c642dSBill Krier  * smb_is_stream_name
1004fe1c642dSBill Krier  *
1005fe1c642dSBill Krier  * Determines if 'path' specifies a named stream.
1006fe1c642dSBill Krier  *
1007fe1c642dSBill Krier  * path is a NULL terminated string which could be a stream path.
1008fe1c642dSBill Krier  * [pathname/]fname[:stream_name[:stream_type]]
1009fe1c642dSBill Krier  *
1010fe1c642dSBill Krier  * - If there is no colon in the path or it's the last char
1011fe1c642dSBill Krier  *   then it's not a stream name
1012fe1c642dSBill Krier  *
1013fe1c642dSBill Krier  * - '::' is a non-stream and is commonly used by Windows to designate
1014fe1c642dSBill Krier  *   the unamed stream in the form "::$DATA"
1015fe1c642dSBill Krier  */
1016fe1c642dSBill Krier boolean_t
1017fe1c642dSBill Krier smb_is_stream_name(char *path)
1018fe1c642dSBill Krier {
1019fe1c642dSBill Krier 	char *colonp;
1020fe1c642dSBill Krier 
1021fe1c642dSBill Krier 	if (path == NULL)
1022fe1c642dSBill Krier 		return (B_FALSE);
1023fe1c642dSBill Krier 
1024fe1c642dSBill Krier 	colonp = strchr(path, ':');
1025fe1c642dSBill Krier 	if ((colonp == NULL) || (*(colonp+1) == '\0'))
1026fe1c642dSBill Krier 		return (B_FALSE);
1027fe1c642dSBill Krier 
1028fe1c642dSBill Krier 	if (strstr(path, "::"))
1029fe1c642dSBill Krier 		return (B_FALSE);
1030fe1c642dSBill Krier 
1031fe1c642dSBill Krier 	return (B_TRUE);
1032fe1c642dSBill Krier }
1033fe1c642dSBill Krier 
1034fe1c642dSBill Krier /*
1035fe1c642dSBill Krier  * smb_validate_stream_name
1036fe1c642dSBill Krier  *
1037fe1c642dSBill Krier  * B_FALSE will be returned, and the error status ser in the sr, if:
1038fe1c642dSBill Krier  * - the path is not a stream name
1039fe1c642dSBill Krier  * - a path is specified but the fname is ommitted.
1040fe1c642dSBill Krier  * - the stream_type is specified but not valid.
1041fe1c642dSBill Krier  *
1042fe1c642dSBill Krier  * Note: the stream type is case-insensitive.
1043fe1c642dSBill Krier  */
1044fe1c642dSBill Krier boolean_t
1045fe1c642dSBill Krier smb_validate_stream_name(smb_request_t *sr, smb_pathname_t *pn)
1046fe1c642dSBill Krier {
1047fe1c642dSBill Krier 	static char *strmtype[] = {
1048fe1c642dSBill Krier 		"$DATA",
1049fe1c642dSBill Krier 		"$INDEX_ALLOCATION"
1050fe1c642dSBill Krier 	};
1051fe1c642dSBill Krier 	int i;
1052fe1c642dSBill Krier 
1053fe1c642dSBill Krier 	ASSERT(pn);
1054fe1c642dSBill Krier 	ASSERT(pn->pn_sname);
1055fe1c642dSBill Krier 
1056fe1c642dSBill Krier 	if ((!(pn->pn_sname)) ||
1057fe1c642dSBill Krier 	    ((pn->pn_pname) && !(pn->pn_fname))) {
1058fe1c642dSBill Krier 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
1059fe1c642dSBill Krier 		    ERRDOS, ERROR_INVALID_NAME);
1060fe1c642dSBill Krier 		return (B_FALSE);
1061fe1c642dSBill Krier 	}
1062fe1c642dSBill Krier 
1063fe1c642dSBill Krier 
1064fe1c642dSBill Krier 	if (pn->pn_stype != NULL) {
1065fe1c642dSBill Krier 		for (i = 0; i < sizeof (strmtype) / sizeof (strmtype[0]); ++i) {
1066fe1c642dSBill Krier 			if (strcasecmp(pn->pn_stype, strmtype[i]) == 0)
1067fe1c642dSBill Krier 				return (B_TRUE);
1068fe1c642dSBill Krier 		}
1069fe1c642dSBill Krier 
1070fe1c642dSBill Krier 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
1071fe1c642dSBill Krier 		    ERRDOS, ERROR_INVALID_NAME);
1072fe1c642dSBill Krier 		return (B_FALSE);
1073fe1c642dSBill Krier 	}
1074fe1c642dSBill Krier 
1075fe1c642dSBill Krier 	return (B_TRUE);
1076fe1c642dSBill Krier }
10779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
10799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * valid DFS I/O path:
10809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
10819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * \server-or-domain\share
10829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * \server-or-domain\share\path
10839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
10849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * All the returned errors by this function needs to be
10859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * checked against Windows.
10869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  */
10879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int
10889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_dfs_preprocess(smb_request_t *sr, char *path, size_t pathsz)
10899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
10909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_unc_t unc;
10919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	char *linkpath;
10929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int rc;
10939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (sr->tid_tree == NULL)
10959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (0);
10969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
10979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if ((rc = smb_unc_init(path, &unc)) != 0)
10989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (rc);
10999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smb_strcasecmp(unc.unc_share, sr->tid_tree->t_sharename, 0)) {
11019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_unc_free(&unc);
11029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (EINVAL);
11039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
11049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	linkpath = unc.unc_path;
11069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) snprintf(path, pathsz, "/%s", (linkpath) ? linkpath : "");
11079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
11089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_unc_free(&unc);
11099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (0);
11109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
1111