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.
231bc6aeeeSMatt Barden * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
24*680069d3SMatt Barden * Copyright 2021-2023 RackTop Systems, Inc.
25da6c28aaSamw */
26da6c28aaSamw
27bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
28da6c28aaSamw #include <smbsrv/smb_fsops.h>
29da6c28aaSamw #include <sys/pathname.h>
30*680069d3SMatt Barden #include <sys/priv_const.h>
31*680069d3SMatt Barden #include <sys/policy.h>
32da6c28aaSamw #include <sys/sdt.h>
33da6c28aaSamw
348b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static char *smb_pathname_catia_v5tov4(smb_request_t *, char *, char *, int);
358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static char *smb_pathname_catia_v4tov5(smb_request_t *, char *, char *, int);
368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static int smb_pathname_lookup(pathname_t *, pathname_t *, int,
379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States vnode_t **, vnode_t *, vnode_t *, smb_attr_t *attr, cred_t *);
38fe1c642dSBill Krier static char *smb_pathname_strdup(smb_request_t *, const char *);
39fe1c642dSBill Krier static char *smb_pathname_strcat(smb_request_t *, char *, const char *);
40fe1c642dSBill Krier static void smb_pathname_preprocess(smb_request_t *, smb_pathname_t *);
419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_pathname_preprocess_quota(smb_request_t *, smb_pathname_t *);
429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_pathname_dfs_preprocess(smb_request_t *, char *, size_t);
439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_pathname_preprocess_adminshare(smb_request_t *,
449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_t *);
459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
468b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
47da6c28aaSamw uint32_t
smb_is_executable(char * path)48da6c28aaSamw smb_is_executable(char *path)
49da6c28aaSamw {
50da6c28aaSamw char extension[5];
51da6c28aaSamw int len = strlen(path);
52da6c28aaSamw
53da6c28aaSamw if ((len >= 4) && (path[len - 4] == '.')) {
54da6c28aaSamw (void) strcpy(extension, &path[len - 3]);
55bbf6f00cSJordan Brown (void) smb_strupr(extension);
56da6c28aaSamw
57da6c28aaSamw if (strcmp(extension, "EXE") == 0)
58da6c28aaSamw return (NODE_FLAGS_EXECUTABLE);
59da6c28aaSamw
60da6c28aaSamw if (strcmp(extension, "COM") == 0)
61da6c28aaSamw return (NODE_FLAGS_EXECUTABLE);
62da6c28aaSamw
63da6c28aaSamw if (strcmp(extension, "DLL") == 0)
64da6c28aaSamw return (NODE_FLAGS_EXECUTABLE);
65da6c28aaSamw
66da6c28aaSamw if (strcmp(extension, "SYM") == 0)
67da6c28aaSamw return (NODE_FLAGS_EXECUTABLE);
68da6c28aaSamw }
69da6c28aaSamw
70da6c28aaSamw return (0);
71da6c28aaSamw }
72da6c28aaSamw
73da6c28aaSamw /*
74da6c28aaSamw * smb_pathname_reduce
75da6c28aaSamw *
76da6c28aaSamw * smb_pathname_reduce() takes a path and returns the smb_node for the
77da6c28aaSamw * second-to-last component of the path. It also returns the name of the last
78da6c28aaSamw * component. Pointers for both of these fields must be supplied by the caller.
79da6c28aaSamw *
80da6c28aaSamw * Upon success, 0 is returned.
81da6c28aaSamw *
82da6c28aaSamw * Upon error, *dir_node will be set to 0.
83da6c28aaSamw *
84da6c28aaSamw * *sr (in)
85da6c28aaSamw * ---
86da6c28aaSamw * smb_request structure pointer
87da6c28aaSamw *
88da6c28aaSamw * *cred (in)
89da6c28aaSamw * -----
90da6c28aaSamw * credential
91da6c28aaSamw *
92da6c28aaSamw * *path (in)
93da6c28aaSamw * -----
94da6c28aaSamw * pathname to be looked up
95da6c28aaSamw *
96da6c28aaSamw * *share_root_node (in)
97da6c28aaSamw * ----------------
98da6c28aaSamw * File operations which are share-relative should pass sr->tid_tree->t_snode.
99da6c28aaSamw * If the call is not for a share-relative operation, this parameter must be 0
100da6c28aaSamw * (e.g. the call from smbsr_setup_share()). (Such callers will have path
101da6c28aaSamw * operations done using root_smb_node.) This parameter is used to determine
102da6c28aaSamw * whether mount points can be crossed.
103da6c28aaSamw *
104da6c28aaSamw * share_root_node should have at least one reference on it. This reference
105da6c28aaSamw * will stay intact throughout this routine.
106da6c28aaSamw *
107da6c28aaSamw * *cur_node (in)
108da6c28aaSamw * ---------
109da6c28aaSamw * The smb_node for the current directory (for relative paths).
110da6c28aaSamw * cur_node should have at least one reference on it.
111da6c28aaSamw * This reference will stay intact throughout this routine.
112da6c28aaSamw *
113da6c28aaSamw * **dir_node (out)
114da6c28aaSamw * ----------
115da6c28aaSamw * Directory for the penultimate component of the original path.
116da6c28aaSamw * (Note that this is not the same as the parent directory of the ultimate
117da6c28aaSamw * target in the case of a link.)
118da6c28aaSamw *
119da6c28aaSamw * The directory smb_node is returned held. The caller will need to release
120da6c28aaSamw * the hold or otherwise make sure it will get released (e.g. in a destroy
121da6c28aaSamw * routine if made part of a global structure).
122da6c28aaSamw *
123da6c28aaSamw * last_component (out)
124da6c28aaSamw * --------------
125da6c28aaSamw * The last component of the path. (This may be different from the name of any
126da6c28aaSamw * link target to which the last component may resolve.)
127da6c28aaSamw *
128da6c28aaSamw *
129da6c28aaSamw * ____________________________
130da6c28aaSamw *
131da6c28aaSamw * The CIFS server lookup path needs to have logic equivalent to that of
132da6c28aaSamw * smb_fsop_lookup(), smb_vop_lookup() and other smb_vop_*() routines in the
133da6c28aaSamw * following areas:
134da6c28aaSamw *
1355f1ef25cSAram Hăvărneanu * - traversal of child mounts (handled by smb_pathname_reduce)
1365f1ef25cSAram Hăvărneanu * - unmangling (handled in smb_pathname)
1375f1ef25cSAram Hăvărneanu * - "chroot" behavior of share root (handled by lookuppnvp)
138da6c28aaSamw *
139da6c28aaSamw * In addition, it needs to replace backslashes with forward slashes. It also
140da6c28aaSamw * ensures that link processing is done correctly, and that directory
141da6c28aaSamw * information requested by the caller is correctly returned (i.e. for paths
142da6c28aaSamw * with a link in the last component, the directory information of the
143da6c28aaSamw * link and not the target needs to be returned).
144da6c28aaSamw */
145da6c28aaSamw
146da6c28aaSamw int
smb_pathname_reduce(smb_request_t * sr,cred_t * cred,const char * path,smb_node_t * share_root_node,smb_node_t * cur_node,smb_node_t ** dir_node,char * last_component)147da6c28aaSamw smb_pathname_reduce(
148da6c28aaSamw smb_request_t *sr,
149da6c28aaSamw cred_t *cred,
150da6c28aaSamw const char *path,
151da6c28aaSamw smb_node_t *share_root_node,
152da6c28aaSamw smb_node_t *cur_node,
153da6c28aaSamw smb_node_t **dir_node,
154da6c28aaSamw char *last_component)
155da6c28aaSamw {
156da6c28aaSamw smb_node_t *root_node;
15746a7047cSGordon Ross pathname_t ppn = {0};
15846a7047cSGordon Ross pathname_t mnt_pn = {0};
159da6c28aaSamw char *usepath;
160da6c28aaSamw int lookup_flags = FOLLOW;
1618d94f651SGordon Ross int trailing_slash = 0;
162da6c28aaSamw int err = 0;
163da6c28aaSamw int len;
1641bc6aeeeSMatt Barden smb_node_t *vss_node;
16589dc44ceSjose borrego smb_node_t *local_cur_node;
16689dc44ceSjose borrego smb_node_t *local_root_node;
1671bc6aeeeSMatt Barden boolean_t chk_vss;
1681bc6aeeeSMatt Barden char *gmttoken;
169da6c28aaSamw
170da6c28aaSamw ASSERT(dir_node);
171da6c28aaSamw ASSERT(last_component);
172da6c28aaSamw
173da6c28aaSamw *dir_node = NULL;
174da6c28aaSamw *last_component = '\0';
1751bc6aeeeSMatt Barden vss_node = NULL;
1761bc6aeeeSMatt Barden gmttoken = NULL;
1771bc6aeeeSMatt Barden chk_vss = B_FALSE;
178da6c28aaSamw
1797b59d02dSjb if (sr && sr->tid_tree) {
180f96bd5c8SAlan Wright if (STYPE_ISIPC(sr->tid_tree->t_res_type))
1817b59d02dSjb return (EACCES);
1827b59d02dSjb }
1837b59d02dSjb
184c8ec8eeaSjose borrego if (SMB_TREE_IS_CASEINSENSITIVE(sr))
185da6c28aaSamw lookup_flags |= FIGNORECASE;
186da6c28aaSamw
187da6c28aaSamw if (path == NULL)
188da6c28aaSamw return (EINVAL);
189da6c28aaSamw
190da6c28aaSamw if (*path == '\0')
191da6c28aaSamw return (ENOENT);
192da6c28aaSamw
193b24e356bSPeer Dampmann usepath = kmem_alloc(SMB_MAXPATHLEN, KM_SLEEP);
194da6c28aaSamw
195b24e356bSPeer Dampmann len = strlcpy(usepath, path, SMB_MAXPATHLEN);
196b24e356bSPeer Dampmann if (len >= SMB_MAXPATHLEN) {
197b24e356bSPeer Dampmann kmem_free(usepath, SMB_MAXPATHLEN);
198da6c28aaSamw return (ENAMETOOLONG);
199da6c28aaSamw }
200da6c28aaSamw
201da6c28aaSamw (void) strsubst(usepath, '\\', '/');
202da6c28aaSamw
203da6c28aaSamw if (share_root_node)
204da6c28aaSamw root_node = share_root_node;
205da6c28aaSamw else
206faa1795aSjb root_node = sr->sr_server->si_root_smb_node;
207da6c28aaSamw
208da6c28aaSamw if (cur_node == NULL)
209da6c28aaSamw cur_node = root_node;
210da6c28aaSamw
21189dc44ceSjose borrego local_cur_node = cur_node;
21289dc44ceSjose borrego local_root_node = root_node;
21389dc44ceSjose borrego
214a90cf9f2SGordon Ross if (SMB_TREE_IS_DFSROOT(sr)) {
215a90cf9f2SGordon Ross int is_dfs;
216a90cf9f2SGordon Ross if (sr->session->dialect >= SMB_VERS_2_BASE)
217a90cf9f2SGordon Ross is_dfs = sr->smb2_hdr_flags &
218a90cf9f2SGordon Ross SMB2_FLAGS_DFS_OPERATIONS;
219a90cf9f2SGordon Ross else
220a90cf9f2SGordon Ross is_dfs = sr->smb_flg2 & SMB_FLAGS2_DFS;
221a90cf9f2SGordon Ross if (is_dfs != 0) {
222a90cf9f2SGordon Ross err = smb_pathname_dfs_preprocess(sr, usepath,
223a90cf9f2SGordon Ross SMB_MAXPATHLEN);
224a90cf9f2SGordon Ross if (err != 0) {
225a90cf9f2SGordon Ross kmem_free(usepath, SMB_MAXPATHLEN);
226a90cf9f2SGordon Ross return (err);
227a90cf9f2SGordon Ross }
228a90cf9f2SGordon Ross len = strlen(usepath);
2299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
2309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
2319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
232a90cf9f2SGordon Ross if (sr != NULL) {
2331bc6aeeeSMatt Barden if (sr->session->dialect >= SMB_VERS_2_BASE) {
234a90cf9f2SGordon Ross chk_vss = sr->arg.open.create_timewarp;
2351bc6aeeeSMatt Barden } else {
236a90cf9f2SGordon Ross chk_vss = (sr->smb_flg2 &
237a90cf9f2SGordon Ross SMB_FLAGS2_REPARSE_PATH) != 0;
23889dc44ceSjose borrego
2391bc6aeeeSMatt Barden if (chk_vss) {
2401bc6aeeeSMatt Barden gmttoken = kmem_alloc(SMB_VSS_GMT_SIZE,
2411bc6aeeeSMatt Barden KM_SLEEP);
2421bc6aeeeSMatt Barden err = smb_vss_extract_gmttoken(usepath,
2431bc6aeeeSMatt Barden gmttoken);
2441bc6aeeeSMatt Barden if (err != 0) {
2451bc6aeeeSMatt Barden kmem_free(usepath, SMB_MAXPATHLEN);
2461bc6aeeeSMatt Barden kmem_free(gmttoken, SMB_VSS_GMT_SIZE);
2471bc6aeeeSMatt Barden return (err);
2481bc6aeeeSMatt Barden }
2491bc6aeeeSMatt Barden len = strlen(usepath);
2501bc6aeeeSMatt Barden }
25189dc44ceSjose borrego }
2521bc6aeeeSMatt Barden if (chk_vss)
2531bc6aeeeSMatt Barden (void) pn_alloc(&mnt_pn);
25489dc44ceSjose borrego }
25589dc44ceSjose borrego
25689dc44ceSjose borrego if (usepath[len - 1] == '/')
25789dc44ceSjose borrego trailing_slash = 1;
25889dc44ceSjose borrego
25989dc44ceSjose borrego (void) strcanon(usepath, "/");
26089dc44ceSjose borrego
261b24e356bSPeer Dampmann (void) pn_alloc_sz(&ppn, SMB_MAXPATHLEN);
262da6c28aaSamw
263da6c28aaSamw if ((err = pn_set(&ppn, usepath)) != 0) {
264da6c28aaSamw (void) pn_free(&ppn);
265b24e356bSPeer Dampmann kmem_free(usepath, SMB_MAXPATHLEN);
2661bc6aeeeSMatt Barden if (chk_vss)
2671bc6aeeeSMatt Barden (void) pn_free(&mnt_pn);
2681bc6aeeeSMatt Barden if (gmttoken != NULL)
2691bc6aeeeSMatt Barden kmem_free(gmttoken, SMB_VSS_GMT_SIZE);
270da6c28aaSamw return (err);
271da6c28aaSamw }
272da6c28aaSamw
273da6c28aaSamw /*
274da6c28aaSamw * If a path does not have a trailing slash, strip off the
275da6c28aaSamw * last component. (We only need to return an smb_node for
276da6c28aaSamw * the second to last component; a name is returned for the
277da6c28aaSamw * last component.)
2781bc6aeeeSMatt Barden *
2791bc6aeeeSMatt Barden * For VSS requests, the last component might be a filesystem of its
2801bc6aeeeSMatt Barden * own, and we need to discover that before exiting this function,
2811bc6aeeeSMatt Barden * so allow the lookup to happen on the last component.
2821bc6aeeeSMatt Barden * We'll correct this later when we convert to the snapshot.
283da6c28aaSamw */
284da6c28aaSamw
2851bc6aeeeSMatt Barden if (!chk_vss) {
2861bc6aeeeSMatt Barden if (trailing_slash) {
2871bc6aeeeSMatt Barden (void) strlcpy(last_component, ".", MAXNAMELEN);
2881bc6aeeeSMatt Barden } else {
2891bc6aeeeSMatt Barden (void) pn_setlast(&ppn);
29046a7047cSGordon Ross if (ppn.pn_pathlen >= MAXNAMELEN) {
29146a7047cSGordon Ross err = ENAMETOOLONG;
29246a7047cSGordon Ross goto end_not_vss;
29346a7047cSGordon Ross }
2941bc6aeeeSMatt Barden (void) strlcpy(last_component, ppn.pn_path, MAXNAMELEN);
2951bc6aeeeSMatt Barden ppn.pn_path[0] = '\0';
2961bc6aeeeSMatt Barden }
297da6c28aaSamw }
298da6c28aaSamw
299fc724630SAlan Wright if ((strcmp(ppn.pn_buf, "/") == 0) || (ppn.pn_buf[0] == '\0')) {
30089dc44ceSjose borrego smb_node_ref(local_cur_node);
30189dc44ceSjose borrego *dir_node = local_cur_node;
302da6c28aaSamw } else {
30389dc44ceSjose borrego err = smb_pathname(sr, ppn.pn_buf, lookup_flags,
3041bc6aeeeSMatt Barden local_root_node, local_cur_node, NULL, dir_node, cred,
3051bc6aeeeSMatt Barden chk_vss ? &mnt_pn : NULL);
306da6c28aaSamw }
307da6c28aaSamw
30846a7047cSGordon Ross end_not_vss:
309da6c28aaSamw (void) pn_free(&ppn);
310b24e356bSPeer Dampmann kmem_free(usepath, SMB_MAXPATHLEN);
311da6c28aaSamw
3121bc6aeeeSMatt Barden /*
3131bc6aeeeSMatt Barden * We need to try and convert to snapshots, even on error.
3141bc6aeeeSMatt Barden * This is to handle the following cases:
3151bc6aeeeSMatt Barden * - We're on the lowest level filesystem, but a directory got renamed
3161bc6aeeeSMatt Barden * on the live version. We'll get ENOENT, but can still find it in
3171bc6aeeeSMatt Barden * the snapshot.
3181bc6aeeeSMatt Barden * - The last component was actually a file. We need to leave the last
3191bc6aeeeSMatt Barden * component in in case it is, itself, a mountpoint, but that means
3201bc6aeeeSMatt Barden * we might get ENOTDIR if it's not actually a directory.
3211bc6aeeeSMatt Barden *
3221bc6aeeeSMatt Barden * Note that if you change the share-relative name of a mountpoint,
3231bc6aeeeSMatt Barden * you won't be able to access previous versions of files under it.
3241bc6aeeeSMatt Barden */
3251bc6aeeeSMatt Barden if (chk_vss && *dir_node != NULL) {
3261bc6aeeeSMatt Barden if ((err = smb_vss_lookup_nodes(sr, *dir_node, &vss_node,
3271bc6aeeeSMatt Barden gmttoken)) == 0) {
3281bc6aeeeSMatt Barden char *p = mnt_pn.pn_path;
3291bc6aeeeSMatt Barden size_t pathleft;
3301bc6aeeeSMatt Barden
3311bc6aeeeSMatt Barden smb_node_release(*dir_node);
3321bc6aeeeSMatt Barden *dir_node = NULL;
3331bc6aeeeSMatt Barden pathleft = pn_pathleft(&mnt_pn);
3341bc6aeeeSMatt Barden
3351bc6aeeeSMatt Barden if (pathleft == 0 || trailing_slash) {
3361bc6aeeeSMatt Barden (void) strlcpy(last_component, ".", MAXNAMELEN);
3371bc6aeeeSMatt Barden } else {
3381bc6aeeeSMatt Barden (void) pn_setlast(&mnt_pn);
33946a7047cSGordon Ross if (ppn.pn_pathlen >= MAXNAMELEN) {
34046a7047cSGordon Ross err = ENAMETOOLONG;
34146a7047cSGordon Ross goto end_chk_vss;
34246a7047cSGordon Ross }
3431bc6aeeeSMatt Barden (void) strlcpy(last_component, mnt_pn.pn_path,
3441bc6aeeeSMatt Barden MAXNAMELEN);
3451bc6aeeeSMatt Barden mnt_pn.pn_path[0] = '\0';
3461bc6aeeeSMatt Barden pathleft -= strlen(last_component);
3471bc6aeeeSMatt Barden }
3481bc6aeeeSMatt Barden
3491bc6aeeeSMatt Barden if (pathleft != 0) {
3501bc6aeeeSMatt Barden err = smb_pathname(sr, p, lookup_flags,
3511bc6aeeeSMatt Barden vss_node, vss_node, NULL, dir_node, cred,
3521bc6aeeeSMatt Barden NULL);
3531bc6aeeeSMatt Barden } else {
3541bc6aeeeSMatt Barden *dir_node = vss_node;
3551bc6aeeeSMatt Barden vss_node = NULL;
3561bc6aeeeSMatt Barden }
3571bc6aeeeSMatt Barden }
3581bc6aeeeSMatt Barden }
3591bc6aeeeSMatt Barden
36046a7047cSGordon Ross end_chk_vss:
3611bc6aeeeSMatt Barden if (chk_vss)
3621bc6aeeeSMatt Barden (void) pn_free(&mnt_pn);
3631bc6aeeeSMatt Barden if (gmttoken != NULL)
3641bc6aeeeSMatt Barden kmem_free(gmttoken, SMB_VSS_GMT_SIZE);
3651bc6aeeeSMatt Barden
366da6c28aaSamw /*
3675f1ef25cSAram Hăvărneanu * Prevent traversal to another file system if mount point
3685f1ef25cSAram Hăvărneanu * traversal is disabled.
369da6c28aaSamw *
370da6c28aaSamw * Note that we disregard whether the traversal of the path went
371da6c28aaSamw * outside of the file system and then came back (say via a link).
3725f1ef25cSAram Hăvărneanu * This means that only symlinks that are expressed relatively to
3735f1ef25cSAram Hăvărneanu * the share root work.
3745f1ef25cSAram Hăvărneanu *
3755f1ef25cSAram Hăvărneanu * share_root_node is NULL when mapping a share, so we disregard
3765f1ef25cSAram Hăvărneanu * that case.
377da6c28aaSamw */
378da6c28aaSamw
379da6c28aaSamw if ((err == 0) && share_root_node) {
3805f1ef25cSAram Hăvărneanu if (share_root_node->vp->v_vfsp != (*dir_node)->vp->v_vfsp) {
381da6c28aaSamw err = EACCES;
3825f1ef25cSAram Hăvărneanu if ((sr) && (sr)->tid_tree &&
3835f1ef25cSAram Hăvărneanu smb_tree_has_feature((sr)->tid_tree,
3845f1ef25cSAram Hăvărneanu SMB_TREE_TRAVERSE_MOUNTS))
3855f1ef25cSAram Hăvărneanu err = 0;
3865f1ef25cSAram Hăvărneanu }
387da6c28aaSamw }
388da6c28aaSamw
389da6c28aaSamw if (err) {
390da6c28aaSamw if (*dir_node) {
391da6c28aaSamw (void) smb_node_release(*dir_node);
392da6c28aaSamw *dir_node = NULL;
393da6c28aaSamw }
394da6c28aaSamw *last_component = 0;
395da6c28aaSamw }
396da6c28aaSamw
3971bc6aeeeSMatt Barden if (vss_node != NULL)
3981bc6aeeeSMatt Barden (void) smb_node_release(vss_node);
399da6c28aaSamw return (err);
400da6c28aaSamw }
401da6c28aaSamw
402da6c28aaSamw /*
4038b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * smb_pathname()
4048b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * wrapper to lookuppnvp(). Handles name unmangling.
405da6c28aaSamw *
406da6c28aaSamw * *dir_node is the true directory of the target *node.
407da6c28aaSamw *
408da6c28aaSamw * If any component but the last in the path is not found, ENOTDIR instead of
409da6c28aaSamw * ENOENT will be returned.
410da6c28aaSamw *
411da6c28aaSamw * Path components are processed one at a time so that smb_nodes can be
4121fcced4cSJordan Brown * created for each component. This allows the n_dnode field in the
413da6c28aaSamw * smb_node to be properly populated.
414da6c28aaSamw *
4158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * Because of the above, links are also processed in this routine
4168b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * (i.e., we do not pass the FOLLOW flag to lookuppnvp()). This
4178b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * will allow smb_nodes to be created for each component of a link.
4188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States *
4198b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * Mangle checking is per component. If a name is mangled, when the
4208b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * unmangled name is passed to smb_pathname_lookup() do not pass
4218b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * FIGNORECASE, since the unmangled name is the real on-disk name.
4228b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * Otherwise pass FIGNORECASE if it's set in flags. This will cause the
4238b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * file system to return "first match" in the event of a case collision.
4248b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States *
4258b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * If CATIA character translation is enabled it is applied to each
4268b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * component before passing the component to smb_pathname_lookup().
4278b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * After smb_pathname_lookup() the reverse translation is applied.
428da6c28aaSamw */
429da6c28aaSamw
430da6c28aaSamw int
smb_pathname(smb_request_t * sr,char * path,int flags,smb_node_t * root_node,smb_node_t * cur_node,smb_node_t ** dir_node,smb_node_t ** ret_node,cred_t * cred,pathname_t * mnt_pn)4318b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname(smb_request_t *sr, char *path, int flags,
4328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_node_t *root_node, smb_node_t *cur_node, smb_node_t **dir_node,
4331bc6aeeeSMatt Barden smb_node_t **ret_node, cred_t *cred, pathname_t *mnt_pn)
434da6c28aaSamw {
4358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States char *component, *real_name, *namep;
4368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States pathname_t pn, rpn, upn, link_pn;
4371bc6aeeeSMatt Barden smb_node_t *dnode, *fnode, *mnt_node;
4389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_attr_t attr;
4398b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States vnode_t *rootvp, *vp;
440da6c28aaSamw size_t pathleft;
441da6c28aaSamw int err = 0;
442da6c28aaSamw int nlink = 0;
443da6c28aaSamw int local_flags;
444e3f2c991SKeyur Desai uint32_t abe_flag = 0;
4458b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States char namebuf[MAXNAMELEN];
4461bc6aeeeSMatt Barden vnode_t *fsrootvp = NULL;
447da6c28aaSamw
448da6c28aaSamw if (path == NULL)
449da6c28aaSamw return (EINVAL);
450da6c28aaSamw
451da6c28aaSamw ASSERT(root_node);
452da6c28aaSamw ASSERT(cur_node);
453da6c28aaSamw ASSERT(ret_node);
454da6c28aaSamw
455da6c28aaSamw *ret_node = NULL;
456da6c28aaSamw
457da6c28aaSamw if (dir_node)
458da6c28aaSamw *dir_node = NULL;
459da6c28aaSamw
460b24e356bSPeer Dampmann (void) pn_alloc_sz(&upn, SMB_MAXPATHLEN);
461da6c28aaSamw
462da6c28aaSamw if ((err = pn_set(&upn, path)) != 0) {
463da6c28aaSamw (void) pn_free(&upn);
464da6c28aaSamw return (err);
465da6c28aaSamw }
466da6c28aaSamw
4671bc6aeeeSMatt Barden if (mnt_pn != NULL && (err = pn_set(mnt_pn, path) != 0)) {
4681bc6aeeeSMatt Barden (void) pn_free(&upn);
4691bc6aeeeSMatt Barden return (err);
4701bc6aeeeSMatt Barden }
4711bc6aeeeSMatt Barden
472e3f2c991SKeyur Desai if (SMB_TREE_SUPPORTS_ABE(sr))
473e3f2c991SKeyur Desai abe_flag = SMB_ABE;
474e3f2c991SKeyur Desai
475da6c28aaSamw (void) pn_alloc(&pn);
476da6c28aaSamw (void) pn_alloc(&rpn);
477da6c28aaSamw
478da6c28aaSamw component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
479da6c28aaSamw real_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
480da6c28aaSamw
4811bc6aeeeSMatt Barden if (mnt_pn != NULL) {
4821bc6aeeeSMatt Barden mnt_node = cur_node;
4831bc6aeeeSMatt Barden smb_node_ref(cur_node);
4841bc6aeeeSMatt Barden } else
4851bc6aeeeSMatt Barden mnt_node = NULL;
4868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States fnode = NULL;
487da6c28aaSamw dnode = cur_node;
488da6c28aaSamw smb_node_ref(dnode);
4898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States rootvp = root_node->vp;
49055bf511dSas
491da6c28aaSamw while ((pathleft = pn_pathleft(&upn)) != 0) {
492da6c28aaSamw if (fnode) {
493da6c28aaSamw smb_node_release(dnode);
494da6c28aaSamw dnode = fnode;
495da6c28aaSamw fnode = NULL;
496da6c28aaSamw }
497da6c28aaSamw
498da6c28aaSamw if ((err = pn_getcomponent(&upn, component)) != 0)
499da6c28aaSamw break;
500da6c28aaSamw
5018b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if ((namep = smb_pathname_catia_v5tov4(sr, component,
5028b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States namebuf, sizeof (namebuf))) == NULL) {
5038b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States err = EILSEQ;
5048b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States break;
505da6c28aaSamw }
506da6c28aaSamw
507da6c28aaSamw if ((err = pn_set(&pn, namep)) != 0)
508da6c28aaSamw break;
509da6c28aaSamw
5108d94f651SGordon Ross /* We want the DOS attributes. */
5118d94f651SGordon Ross bzero(&attr, sizeof (attr));
5128d94f651SGordon Ross attr.sa_mask = SMB_AT_DOSATTR;
5138d94f651SGordon Ross
5148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States local_flags = flags & FIGNORECASE;
5158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States err = smb_pathname_lookup(&pn, &rpn, local_flags,
5169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &vp, rootvp, dnode->vp, &attr, cred);
517da6c28aaSamw
5188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (err) {
519cb174861Sjoyce mcintosh if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
520cb174861Sjoyce mcintosh !smb_maybe_mangled(component))
5218b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States break;
5228b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
523148c5f43SAlan Wright if ((err = smb_unmangle(dnode, component,
524e3f2c991SKeyur Desai real_name, MAXNAMELEN, abe_flag)) != 0)
5258b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States break;
526da6c28aaSamw
5278b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if ((namep = smb_pathname_catia_v5tov4(sr, real_name,
5288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States namebuf, sizeof (namebuf))) == NULL) {
5298b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States err = EILSEQ;
5308b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States break;
5318b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
532da6c28aaSamw
5338b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if ((err = pn_set(&pn, namep)) != 0)
5348b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States break;
5358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
5368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States local_flags = 0;
5378b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States err = smb_pathname_lookup(&pn, &rpn, local_flags,
5389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States &vp, rootvp, dnode->vp, &attr, cred);
5398b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (err)
5408b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States break;
5418b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
542da6c28aaSamw
5439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
5449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * This check MUST be done before symlink check
5459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * since a reparse point is of type VLNK but should
5469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * not be handled like a regular symlink.
5479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
5489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) {
5499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States err = EREMOTE;
5509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States VN_RELE(vp);
5519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
5529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
5539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
554da6c28aaSamw if ((vp->v_type == VLNK) &&
555da6c28aaSamw ((flags & FOLLOW) || pn_pathleft(&upn))) {
556da6c28aaSamw
557da6c28aaSamw if (++nlink > MAXSYMLINKS) {
558da6c28aaSamw err = ELOOP;
5597f667e74Sjose borrego VN_RELE(vp);
560da6c28aaSamw break;
561da6c28aaSamw }
562da6c28aaSamw
563da6c28aaSamw (void) pn_alloc(&link_pn);
564da6c28aaSamw err = pn_getsymlink(vp, &link_pn, cred);
5657f667e74Sjose borrego VN_RELE(vp);
566da6c28aaSamw
5678b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (err == 0) {
5688b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (pn_pathleft(&link_pn) == 0)
5698b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) pn_set(&link_pn, ".");
5708b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States err = pn_insert(&upn, &link_pn,
5718b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States strlen(component));
572da6c28aaSamw }
573da6c28aaSamw pn_free(&link_pn);
574da6c28aaSamw
575da6c28aaSamw if (err)
576da6c28aaSamw break;
577da6c28aaSamw
578da6c28aaSamw if (upn.pn_pathlen == 0) {
579da6c28aaSamw err = ENOENT;
580da6c28aaSamw break;
581da6c28aaSamw }
582da6c28aaSamw
583da6c28aaSamw if (upn.pn_path[0] == '/') {
584da6c28aaSamw fnode = root_node;
585da6c28aaSamw smb_node_ref(fnode);
586da6c28aaSamw }
587da6c28aaSamw
588da6c28aaSamw if (pn_fixslash(&upn))
589da6c28aaSamw flags |= FOLLOW;
590da6c28aaSamw
591da6c28aaSamw } else {
592da6c28aaSamw if (flags & FIGNORECASE) {
593da6c28aaSamw if (strcmp(rpn.pn_path, "/") != 0)
594da6c28aaSamw pn_setlast(&rpn);
595da6c28aaSamw namep = rpn.pn_path;
5968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } else {
597da6c28aaSamw namep = pn.pn_path;
5988b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
5998b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
6008b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States namep = smb_pathname_catia_v4tov5(sr, namep,
6018b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States namebuf, sizeof (namebuf));
602da6c28aaSamw
603da6c28aaSamw fnode = smb_node_lookup(sr, NULL, cred, vp, namep,
604037cac00Sjoyce mcintosh dnode, NULL);
6057f667e74Sjose borrego VN_RELE(vp);
606da6c28aaSamw
607da6c28aaSamw if (fnode == NULL) {
608da6c28aaSamw err = ENOMEM;
609da6c28aaSamw break;
610da6c28aaSamw }
611da6c28aaSamw }
612da6c28aaSamw
613da6c28aaSamw while (upn.pn_path[0] == '/') {
614da6c28aaSamw upn.pn_path++;
615da6c28aaSamw upn.pn_pathlen--;
616da6c28aaSamw }
6177f667e74Sjose borrego
6181bc6aeeeSMatt Barden /*
6191bc6aeeeSMatt Barden * If the node we looked up is the root of a filesystem,
6201bc6aeeeSMatt Barden * snapshot the lookup so we can replay this after discovering
6211bc6aeeeSMatt Barden * the lowest mounted filesystem.
6221bc6aeeeSMatt Barden */
6231bc6aeeeSMatt Barden if (mnt_pn != NULL &&
6241bc6aeeeSMatt Barden fnode != NULL &&
6251bc6aeeeSMatt Barden (err = VFS_ROOT(fnode->vp->v_vfsp, &fsrootvp)) == 0) {
6261bc6aeeeSMatt Barden if (fsrootvp == fnode->vp) {
6271bc6aeeeSMatt Barden mnt_pn->pn_pathlen = pn_pathleft(&upn);
6281bc6aeeeSMatt Barden mnt_pn->pn_path = mnt_pn->pn_buf +
6291bc6aeeeSMatt Barden ((ptrdiff_t)upn.pn_path -
6301bc6aeeeSMatt Barden (ptrdiff_t)upn.pn_buf);
6311bc6aeeeSMatt Barden
6321bc6aeeeSMatt Barden smb_node_ref(fnode);
6331bc6aeeeSMatt Barden if (mnt_node != NULL)
6341bc6aeeeSMatt Barden smb_node_release(mnt_node);
6351bc6aeeeSMatt Barden mnt_node = fnode;
6361bc6aeeeSMatt Barden
6371bc6aeeeSMatt Barden }
6381bc6aeeeSMatt Barden VN_RELE(fsrootvp);
6391bc6aeeeSMatt Barden }
640da6c28aaSamw }
641da6c28aaSamw
642da6c28aaSamw if ((pathleft) && (err == ENOENT))
643da6c28aaSamw err = ENOTDIR;
644da6c28aaSamw
6451bc6aeeeSMatt Barden if (mnt_node == NULL)
6461bc6aeeeSMatt Barden mnt_pn = NULL;
6471bc6aeeeSMatt Barden
6481bc6aeeeSMatt Barden /*
6491bc6aeeeSMatt Barden * We always want to return a node when we're doing VSS
6501bc6aeeeSMatt Barden * (mnt_pn != NULL)
6511bc6aeeeSMatt Barden */
6521bc6aeeeSMatt Barden if (mnt_pn == NULL && err != 0) {
653da6c28aaSamw if (fnode)
654da6c28aaSamw smb_node_release(fnode);
655da6c28aaSamw if (dnode)
656da6c28aaSamw smb_node_release(dnode);
657da6c28aaSamw } else {
6581bc6aeeeSMatt Barden if (mnt_pn != NULL) {
6591bc6aeeeSMatt Barden *ret_node = mnt_node;
6601bc6aeeeSMatt Barden if (fnode != NULL)
6611bc6aeeeSMatt Barden smb_node_release(fnode);
6621bc6aeeeSMatt Barden } else {
6631bc6aeeeSMatt Barden *ret_node = fnode;
6641bc6aeeeSMatt Barden }
665da6c28aaSamw
666da6c28aaSamw if (dir_node)
667da6c28aaSamw *dir_node = dnode;
668da6c28aaSamw else
669da6c28aaSamw smb_node_release(dnode);
670da6c28aaSamw }
671da6c28aaSamw
672da6c28aaSamw kmem_free(component, MAXNAMELEN);
673da6c28aaSamw kmem_free(real_name, MAXNAMELEN);
674da6c28aaSamw (void) pn_free(&pn);
675da6c28aaSamw (void) pn_free(&rpn);
676da6c28aaSamw (void) pn_free(&upn);
677da6c28aaSamw
678da6c28aaSamw return (err);
679da6c28aaSamw }
68089dc44ceSjose borrego
6818b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States /*
6828b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * Holds on dvp and rootvp (if not rootdir) are required by lookuppnvp()
6838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * and will be released within lookuppnvp().
6848b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States */
6858b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static int
smb_pathname_lookup(pathname_t * pn,pathname_t * rpn,int flags,vnode_t ** vp,vnode_t * rootvp,vnode_t * dvp,smb_attr_t * attr,cred_t * cred)6868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_lookup(pathname_t *pn, pathname_t *rpn, int flags,
6879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States vnode_t **vp, vnode_t *rootvp, vnode_t *dvp, smb_attr_t *attr, cred_t *cred)
6888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States {
6898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States int err;
6908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
6918b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States *vp = NULL;
6928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States VN_HOLD(dvp);
6938b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (rootvp != rootdir)
6948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States VN_HOLD(rootvp);
6958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
696*680069d3SMatt Barden #ifdef _KERNEL
697*680069d3SMatt Barden /*
698*680069d3SMatt Barden * When BYPASS_TRAVERSE_CHECKING is enabled, avoid EXECUTE access
699*680069d3SMatt Barden * checks. See: smb_vop_lookup().
700*680069d3SMatt Barden */
701*680069d3SMatt Barden if (smb_vop_priv_check(cred, PRIV_FILE_DAC_SEARCH, B_FALSE, dvp))
702*680069d3SMatt Barden flags |= LOOKUP_NOACLCHECK;
703*680069d3SMatt Barden #endif
704*680069d3SMatt Barden
7058b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States err = lookuppnvp(pn, rpn, flags, NULL, vp, rootvp, dvp, cred);
7069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((err == 0) && (attr != NULL))
7078622ec45SGordon Ross (void) smb_vop_getattr(*vp, NULL, attr, 0, zone_kcred());
7089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
7098b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (err);
7108b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
7118b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
7128b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States /*
7138b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * CATIA Translation of a pathname component prior to passing it to lookuppnvp
7148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States *
7158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * If the translated component name contains a '/' NULL is returned.
7168b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * The caller should treat this as error EILSEQ. It is not valid to
7178b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * have a directory name with a '/'.
7188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States */
7198b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static char *
smb_pathname_catia_v5tov4(smb_request_t * sr,char * name,char * namebuf,int buflen)7208b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_catia_v5tov4(smb_request_t *sr, char *name,
7218b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States char *namebuf, int buflen)
7228b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States {
7238b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States char *namep;
7248b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
7258b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (SMB_TREE_SUPPORTS_CATIA(sr)) {
7268b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States namep = smb_vop_catia_v5tov4(name, namebuf, buflen);
7278b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (strchr(namep, '/') != NULL)
7288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (NULL);
7298b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (namep);
7308b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
7318b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
7328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (name);
7338b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
7348b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
7358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States /*
7368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * CATIA translation of a pathname component after returning from lookuppnvp
7378b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States */
7388b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static char *
smb_pathname_catia_v4tov5(smb_request_t * sr,char * name,char * namebuf,int buflen)7398b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_catia_v4tov5(smb_request_t *sr, char *name,
7408b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States char *namebuf, int buflen)
7418b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States {
7428b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (SMB_TREE_SUPPORTS_CATIA(sr)) {
7438b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_vop_catia_v4tov5(name, namebuf, buflen);
7448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (namebuf);
7458b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
7468b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
7478b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (name);
7488b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States }
7498b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
75089dc44ceSjose borrego /*
75189dc44ceSjose borrego * sr - needed to check for case sense
75289dc44ceSjose borrego * path - non mangled path needed to be looked up from the startvp
75389dc44ceSjose borrego * startvp - the vnode to start the lookup from
75489dc44ceSjose borrego * rootvp - the vnode of the root of the filesystem
75589dc44ceSjose borrego * returns the vnode found when starting at startvp and using the path
75689dc44ceSjose borrego *
75789dc44ceSjose borrego * Finds a vnode starting at startvp and parsing the non mangled path
75889dc44ceSjose borrego */
75989dc44ceSjose borrego
76089dc44ceSjose borrego vnode_t *
smb_lookuppathvptovp(smb_request_t * sr,char * path,vnode_t * startvp,vnode_t * rootvp)76189dc44ceSjose borrego smb_lookuppathvptovp(smb_request_t *sr, char *path, vnode_t *startvp,
76289dc44ceSjose borrego vnode_t *rootvp)
76389dc44ceSjose borrego {
76489dc44ceSjose borrego pathname_t pn;
76589dc44ceSjose borrego vnode_t *vp = NULL;
76689dc44ceSjose borrego int lookup_flags = FOLLOW;
76789dc44ceSjose borrego
76889dc44ceSjose borrego if (SMB_TREE_IS_CASEINSENSITIVE(sr))
76989dc44ceSjose borrego lookup_flags |= FIGNORECASE;
77089dc44ceSjose borrego
77189dc44ceSjose borrego (void) pn_alloc(&pn);
77289dc44ceSjose borrego
77389dc44ceSjose borrego if (pn_set(&pn, path) == 0) {
774037cac00Sjoyce mcintosh VN_HOLD(startvp);
77589dc44ceSjose borrego if (rootvp != rootdir)
77689dc44ceSjose borrego VN_HOLD(rootvp);
77789dc44ceSjose borrego
77889dc44ceSjose borrego /* lookuppnvp should release the holds */
77989dc44ceSjose borrego if (lookuppnvp(&pn, NULL, lookup_flags, NULL, &vp,
7808622ec45SGordon Ross rootvp, startvp, zone_kcred()) != 0) {
78189dc44ceSjose borrego pn_free(&pn);
78289dc44ceSjose borrego return (NULL);
78389dc44ceSjose borrego }
78489dc44ceSjose borrego }
78589dc44ceSjose borrego
78689dc44ceSjose borrego pn_free(&pn);
78789dc44ceSjose borrego return (vp);
78889dc44ceSjose borrego }
789fe1c642dSBill Krier
790fe1c642dSBill Krier /*
791fe1c642dSBill Krier * smb_pathname_init
792fe1c642dSBill Krier * Parse path: pname\\fname:sname:stype
793fe1c642dSBill Krier *
794fe1c642dSBill Krier * Elements of the smb_pathname_t structure are allocated using request
795fe1c642dSBill Krier * specific storage and will be free'd when the sr is destroyed.
796fe1c642dSBill Krier *
797fe1c642dSBill Krier * Populate pn structure elements with the individual elements
798fe1c642dSBill Krier * of pn->pn_path. pn->pn_sname will contain the whole stream name
799fe1c642dSBill Krier * including the stream type and preceding colon: :sname:%DATA
800fe1c642dSBill Krier * pn_stype will point to the stream type within pn_sname.
801fe1c642dSBill Krier *
8029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * If the pname element is missing pn_pname will be set to NULL.
803fe1c642dSBill Krier * If any other element is missing the pointer in pn will be NULL.
804fe1c642dSBill Krier */
805fe1c642dSBill Krier void
smb_pathname_init(smb_request_t * sr,smb_pathname_t * pn,char * path)806fe1c642dSBill Krier smb_pathname_init(smb_request_t *sr, smb_pathname_t *pn, char *path)
807fe1c642dSBill Krier {
808fe1c642dSBill Krier char *pname, *fname, *sname;
809fe1c642dSBill Krier int len;
810fe1c642dSBill Krier
811fe1c642dSBill Krier bzero(pn, sizeof (smb_pathname_t));
812fe1c642dSBill Krier pn->pn_path = smb_pathname_strdup(sr, path);
813fe1c642dSBill Krier
814fe1c642dSBill Krier smb_pathname_preprocess(sr, pn);
815fe1c642dSBill Krier
816fe1c642dSBill Krier /* parse pn->pn_path into its constituent parts */
817fe1c642dSBill Krier pname = pn->pn_path;
818fe1c642dSBill Krier
819b219643fSGordon Ross /*
820b219643fSGordon Ross * Split the string between the directory and filename.
821b219643fSGordon Ross * Either part may be empty.
822b219643fSGordon Ross *
823b219643fSGordon Ross * Fill in pn->pn_pname (the path name)
824b219643fSGordon Ross */
825b219643fSGordon Ross fname = strrchr(pname, '\\');
826b219643fSGordon Ross if (fname != NULL) {
827fe1c642dSBill Krier if (fname == pname) {
828b219643fSGordon Ross /*
829b219643fSGordon Ross * Last '/' is at start of string.
830b219643fSGordon Ross * No directory part (dir is root)
831b219643fSGordon Ross */
8329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States pn->pn_pname = NULL;
833fe1c642dSBill Krier } else {
834b219643fSGordon Ross /*
835b219643fSGordon Ross * Directory part ends at the last '/'
836b219643fSGordon Ross * Temporarily truncate and copy
837b219643fSGordon Ross */
838fe1c642dSBill Krier *fname = '\0';
839fe1c642dSBill Krier pn->pn_pname =
840fe1c642dSBill Krier smb_pathname_strdup(sr, pname);
841fe1c642dSBill Krier *fname = '\\';
842fe1c642dSBill Krier }
843fe1c642dSBill Krier ++fname;
844b219643fSGordon Ross /* fname is just after the '/' */
845fe1c642dSBill Krier } else {
846b219643fSGordon Ross /*
847b219643fSGordon Ross * No '/' at all in the string.
848b219643fSGordon Ross * It's all filename
849b219643fSGordon Ross */
850fe1c642dSBill Krier fname = pname;
8519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States pn->pn_pname = NULL;
852fe1c642dSBill Krier }
853fe1c642dSBill Krier
854b219643fSGordon Ross /*
855b219643fSGordon Ross * Find end of the filename part of the string,
856b219643fSGordon Ross * which may be the null terminator, or may be
857b219643fSGordon Ross * the start of the optional :sname suffix.
858b219643fSGordon Ross */
859b219643fSGordon Ross sname = strchr(fname, ':');
860b219643fSGordon Ross if (sname == NULL) {
861b219643fSGordon Ross /*
862b219643fSGordon Ross * No :sname suffix. We're done.
863b219643fSGordon Ross */
864b219643fSGordon Ross pn->pn_fname = smb_pathname_strdup(sr, fname);
865fe1c642dSBill Krier return;
866fe1c642dSBill Krier }
867fe1c642dSBill Krier
868b219643fSGordon Ross /*
869b219643fSGordon Ross * We have a stream name, and maybe a stream type.
870b219643fSGordon Ross * Can't use smb_is_stream_name(fname) here because
871b219643fSGordon Ross * we need to allow sname="::$DATA"
872b219643fSGordon Ross */
873b219643fSGordon Ross if (sname == fname) {
874b219643fSGordon Ross /*
875b219643fSGordon Ross * The ":sname" part is at the start of
876b219643fSGordon Ross * the file name, which means that the
877b219643fSGordon Ross * file name is "" and this pathname
878b219643fSGordon Ross * refers to a stream on the directory.
879b219643fSGordon Ross */
880b219643fSGordon Ross pn->pn_fname = NULL;
881b219643fSGordon Ross } else {
882b219643fSGordon Ross /*
883b219643fSGordon Ross * The filename part ends at the ':'
884b219643fSGordon Ross * Temporarily truncate and copy
885b219643fSGordon Ross */
886b219643fSGordon Ross *sname = '\0';
887fe1c642dSBill Krier pn->pn_fname = smb_pathname_strdup(sr, fname);
888b219643fSGordon Ross *sname = ':';
889fe1c642dSBill Krier }
890fe1c642dSBill Krier
891fe1c642dSBill Krier /*
892b219643fSGordon Ross * Special case "::$DATA" which "points to"
893b219643fSGordon Ross * the "unnamed" stream (the file itself).
894b219643fSGordon Ross * Basically ignore the "::$DATA"
895fe1c642dSBill Krier */
896b219643fSGordon Ross if (strcasecmp(sname, "::$DATA") == 0) {
897b219643fSGordon Ross ASSERT(sname >= pname &&
898b219643fSGordon Ross sname < (pname + strlen(pname)));
899fe1c642dSBill Krier *sname = '\0';
900b219643fSGordon Ross return;
901fe1c642dSBill Krier }
902fe1c642dSBill Krier
903b219643fSGordon Ross /*
904b219643fSGordon Ross * sname points to ":sname:stype" in pn_path
905b219643fSGordon Ross * If ":stype" is missing, add it, then set
906b219643fSGordon Ross * pn_stype to point after the 2nd ':'
907b219643fSGordon Ross *
908b219643fSGordon Ross * Caller knows pn_stype is NOT allocated.
909b219643fSGordon Ross * Allocations here are free'd via smb_srm_fini
910b219643fSGordon Ross */
911fe1c642dSBill Krier pn->pn_sname = smb_pathname_strdup(sr, sname);
912fe1c642dSBill Krier pn->pn_stype = strchr(pn->pn_sname + 1, ':');
913fe1c642dSBill Krier if (pn->pn_stype) {
914fe1c642dSBill Krier (void) smb_strupr(pn->pn_stype);
915fe1c642dSBill Krier } else {
916fe1c642dSBill Krier len = strlen(pn->pn_sname);
917fe1c642dSBill Krier pn->pn_sname = smb_pathname_strcat(sr, pn->pn_sname, ":$DATA");
918fe1c642dSBill Krier pn->pn_stype = pn->pn_sname + len;
919fe1c642dSBill Krier }
920fe1c642dSBill Krier ++pn->pn_stype;
921fe1c642dSBill Krier }
922fe1c642dSBill Krier
923fe1c642dSBill Krier /*
924fe1c642dSBill Krier * smb_pathname_preprocess
925fe1c642dSBill Krier *
926fe1c642dSBill Krier * Perform common pre-processing of pn->pn_path:
927fe1c642dSBill Krier * - if the pn_path is blank, set it to '\\'
928fe1c642dSBill Krier * - perform unicode wildcard converstion.
929fe1c642dSBill Krier * - convert any '/' to '\\'
930fe1c642dSBill Krier * - eliminate duplicate slashes
931fe1c642dSBill Krier * - remove trailing slashes
9329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * - quota directory specific pre-processing
933fe1c642dSBill Krier */
934fe1c642dSBill Krier static void
smb_pathname_preprocess(smb_request_t * sr,smb_pathname_t * pn)935fe1c642dSBill Krier smb_pathname_preprocess(smb_request_t *sr, smb_pathname_t *pn)
936fe1c642dSBill Krier {
937fe1c642dSBill Krier char *p;
938fe1c642dSBill Krier
939fe1c642dSBill Krier /* treat empty path as "\\" */
940fe1c642dSBill Krier if (strlen(pn->pn_path) == 0) {
941fe1c642dSBill Krier pn->pn_path = smb_pathname_strdup(sr, "\\");
942fe1c642dSBill Krier return;
943fe1c642dSBill Krier }
944fe1c642dSBill Krier
945c13be35aSGordon Ross if (sr->session->dialect < NT_LM_0_12)
946c13be35aSGordon Ross smb_convert_wildcards(pn->pn_path);
947fe1c642dSBill Krier
948fe1c642dSBill Krier /* treat '/' as '\\' */
949fe1c642dSBill Krier (void) strsubst(pn->pn_path, '/', '\\');
950fe1c642dSBill Krier
951fe1c642dSBill Krier (void) strcanon(pn->pn_path, "\\");
952fe1c642dSBill Krier
953fe1c642dSBill Krier /* remove trailing '\\' */
954fe1c642dSBill Krier p = pn->pn_path + strlen(pn->pn_path) - 1;
955fe1c642dSBill Krier if ((p != pn->pn_path) && (*p == '\\'))
956fe1c642dSBill Krier *p = '\0';
9579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_preprocess_quota(sr, pn);
9599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_preprocess_adminshare(sr, pn);
9609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
9619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
9639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * smb_pathname_preprocess_quota
9649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
9659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * There is a special file required by windows so that the quota
9669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * tab will be displayed by windows clients. This is created in
9679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * a special directory, $EXTEND, at the root of the shared file
9689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * system. To hide this directory prepend a '.' (dot).
9699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
9709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_pathname_preprocess_quota(smb_request_t * sr,smb_pathname_t * pn)9719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_preprocess_quota(smb_request_t *sr, smb_pathname_t *pn)
9729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
9739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char *name = "$EXTEND";
9749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char *new_name = ".$EXTEND";
9759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char *p, *slash;
9769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int len;
9779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (!smb_node_is_vfsroot(sr->tid_tree->t_snode))
9799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
9809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States p = pn->pn_path;
9829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* ignore any initial "\\" */
9849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States p += strspn(p, "\\");
9859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_strcasecmp(p, name, strlen(name)) != 0)
9869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
9879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States p += strlen(name);
9899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((*p != ':') && (*p != '\\') && (*p != '\0'))
9909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
9919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States slash = (pn->pn_path[0] == '\\') ? "\\" : "";
9939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States len = strlen(pn->pn_path) + 2;
9949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States pn->pn_path = smb_srm_alloc(sr, len);
9959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) snprintf(pn->pn_path, len, "%s%s%s", slash, new_name, p);
9969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_strupr(pn->pn_path);
9979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
9989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
10009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * smb_pathname_preprocess_adminshare
10019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
10029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Convert any path with share name "C$" or "c$" (Admin share) in to lower case.
10039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
10049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_pathname_preprocess_adminshare(smb_request_t * sr,smb_pathname_t * pn)10059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_preprocess_adminshare(smb_request_t *sr, smb_pathname_t *pn)
10069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
10079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (strcasecmp(sr->tid_tree->t_sharename, "c$") == 0)
10089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_strlwr(pn->pn_path);
1009fe1c642dSBill Krier }
1010fe1c642dSBill Krier
1011fe1c642dSBill Krier /*
1012fe1c642dSBill Krier * smb_pathname_strdup
1013fe1c642dSBill Krier *
1014fe1c642dSBill Krier * Duplicate NULL terminated string s.
1015fe1c642dSBill Krier *
1016fe1c642dSBill Krier * The new string is allocated using request specific storage and will
1017fe1c642dSBill Krier * be free'd when the sr is destroyed.
1018fe1c642dSBill Krier */
1019fe1c642dSBill Krier static char *
smb_pathname_strdup(smb_request_t * sr,const char * s)1020fe1c642dSBill Krier smb_pathname_strdup(smb_request_t *sr, const char *s)
1021fe1c642dSBill Krier {
1022fe1c642dSBill Krier char *s2;
1023fe1c642dSBill Krier size_t n;
1024fe1c642dSBill Krier
1025fe1c642dSBill Krier n = strlen(s) + 1;
10269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States s2 = smb_srm_zalloc(sr, n);
1027fe1c642dSBill Krier (void) strlcpy(s2, s, n);
1028fe1c642dSBill Krier return (s2);
1029fe1c642dSBill Krier }
1030fe1c642dSBill Krier
1031fe1c642dSBill Krier /*
1032fe1c642dSBill Krier * smb_pathname_strcat
1033fe1c642dSBill Krier *
1034fe1c642dSBill Krier * Reallocate NULL terminated string s1 to accommodate
1035fe1c642dSBill Krier * concatenating NULL terminated string s2.
1036fe1c642dSBill Krier * Append s2 and return resulting NULL terminated string.
1037fe1c642dSBill Krier *
1038fe1c642dSBill Krier * The string buffer is reallocated using request specific
1039fe1c642dSBill Krier * storage and will be free'd when the sr is destroyed.
1040fe1c642dSBill Krier */
1041fe1c642dSBill Krier static char *
smb_pathname_strcat(smb_request_t * sr,char * s1,const char * s2)1042fe1c642dSBill Krier smb_pathname_strcat(smb_request_t *sr, char *s1, const char *s2)
1043fe1c642dSBill Krier {
1044fe1c642dSBill Krier size_t n;
1045fe1c642dSBill Krier
1046fe1c642dSBill Krier n = strlen(s1) + strlen(s2) + 1;
10479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States s1 = smb_srm_rezalloc(sr, s1, n);
1048fe1c642dSBill Krier (void) strlcat(s1, s2, n);
1049fe1c642dSBill Krier return (s1);
1050fe1c642dSBill Krier }
1051fe1c642dSBill Krier
1052fe1c642dSBill Krier /*
1053fe1c642dSBill Krier * smb_pathname_validate
1054fe1c642dSBill Krier *
1055fe1c642dSBill Krier * Perform basic validation of pn:
1056fe1c642dSBill Krier * - If first component of pn->path is ".." -> PATH_SYNTAX_BAD
1057fe1c642dSBill Krier * - If there are wildcards in pn->pn_pname -> OBJECT_NAME_INVALID
1058fe1c642dSBill Krier * - If fname is "." -> INVALID_OBJECT_NAME
1059fe1c642dSBill Krier *
1060fe1c642dSBill Krier * On unix .. at the root of a file system links to the root. Thus
1061fe1c642dSBill Krier * an attempt to lookup "/../../.." will be the same as looking up "/"
1062fe1c642dSBill Krier * CIFs clients expect the above to result in
1063fe1c642dSBill Krier * NT_STATUS_OBJECT_PATH_SYNTAX_BAD. It is currently not possible
1064fe1c642dSBill Krier * (and questionable if it's desirable) to deal with all cases
1065fe1c642dSBill Krier * but paths beginning with \\.. are handled.
1066fe1c642dSBill Krier *
1067fe1c642dSBill Krier * Returns: B_TRUE if pn is valid,
1068fe1c642dSBill Krier * otherwise returns B_FALSE and sets error status in sr.
1069a90cf9f2SGordon Ross *
1070a90cf9f2SGordon Ross * XXX: Get rid of smbsr_error calls for SMB2
1071fe1c642dSBill Krier */
1072fe1c642dSBill Krier boolean_t
smb_pathname_validate(smb_request_t * sr,smb_pathname_t * pn)1073fe1c642dSBill Krier smb_pathname_validate(smb_request_t *sr, smb_pathname_t *pn)
1074fe1c642dSBill Krier {
1075fe1c642dSBill Krier char *path = pn->pn_path;
1076fe1c642dSBill Krier
1077fe1c642dSBill Krier /* ignore any initial "\\" */
1078fe1c642dSBill Krier path += strspn(path, "\\");
1079fe1c642dSBill Krier
1080fe1c642dSBill Krier /* If first component of path is ".." -> PATH_SYNTAX_BAD */
1081fe1c642dSBill Krier if ((strcmp(path, "..") == 0) || (strncmp(path, "..\\", 3) == 0)) {
1082fe1c642dSBill Krier smbsr_error(sr, NT_STATUS_OBJECT_PATH_SYNTAX_BAD,
1083fe1c642dSBill Krier ERRDOS, ERROR_BAD_PATHNAME);
1084fe1c642dSBill Krier return (B_FALSE);
1085fe1c642dSBill Krier }
1086fe1c642dSBill Krier
1087fe1c642dSBill Krier /* If there are wildcards in pn->pn_pname -> OBJECT_NAME_INVALID */
1088fe1c642dSBill Krier if (pn->pn_pname && smb_contains_wildcards(pn->pn_pname)) {
1089fe1c642dSBill Krier smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
1090fe1c642dSBill Krier ERRDOS, ERROR_INVALID_NAME);
1091fe1c642dSBill Krier return (B_FALSE);
1092fe1c642dSBill Krier }
1093fe1c642dSBill Krier
1094c5f48fa5SGordon Ross /* If fname is "." -> OBJECT_NAME_INVALID */
1095fe1c642dSBill Krier if (pn->pn_fname && (strcmp(pn->pn_fname, ".") == 0)) {
1096fe1c642dSBill Krier smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
1097c5f48fa5SGordon Ross ERRDOS, ERROR_INVALID_NAME);
1098fe1c642dSBill Krier return (B_FALSE);
1099fe1c642dSBill Krier }
1100fe1c642dSBill Krier
1101fe1c642dSBill Krier return (B_TRUE);
1102fe1c642dSBill Krier }
1103fe1c642dSBill Krier
1104fe1c642dSBill Krier /*
1105fe1c642dSBill Krier * smb_validate_dirname
1106fe1c642dSBill Krier *
1107fe1c642dSBill Krier * smb_pathname_validate() should have already been performed on pn.
1108fe1c642dSBill Krier *
1109fe1c642dSBill Krier * Very basic directory name validation: checks for colons in a path.
1110fe1c642dSBill Krier * Need to skip the drive prefix since it contains a colon.
1111fe1c642dSBill Krier *
1112fe1c642dSBill Krier * Returns: B_TRUE if the name is valid,
1113fe1c642dSBill Krier * otherwise returns B_FALSE and sets error status in sr.
1114fe1c642dSBill Krier */
1115fe1c642dSBill Krier boolean_t
smb_validate_dirname(smb_request_t * sr,smb_pathname_t * pn)1116fe1c642dSBill Krier smb_validate_dirname(smb_request_t *sr, smb_pathname_t *pn)
1117fe1c642dSBill Krier {
1118fe1c642dSBill Krier char *name;
1119fe1c642dSBill Krier char *path = pn->pn_path;
1120fe1c642dSBill Krier
1121fe1c642dSBill Krier if ((name = path) != 0) {
1122fe1c642dSBill Krier name += strspn(name, "\\");
1123fe1c642dSBill Krier
1124fe1c642dSBill Krier if (strchr(name, ':') != 0) {
1125fe1c642dSBill Krier smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
1126fe1c642dSBill Krier ERRDOS, ERROR_INVALID_NAME);
1127fe1c642dSBill Krier return (B_FALSE);
1128fe1c642dSBill Krier }
1129fe1c642dSBill Krier }
1130fe1c642dSBill Krier
1131b219643fSGordon Ross if (pn->pn_sname)
1132b219643fSGordon Ross return (smb_validate_stream_name(sr, pn));
1133b219643fSGordon Ross
1134fe1c642dSBill Krier return (B_TRUE);
1135fe1c642dSBill Krier }
1136fe1c642dSBill Krier
1137fe1c642dSBill Krier /*
1138fe1c642dSBill Krier * smb_validate_object_name
1139fe1c642dSBill Krier *
1140fe1c642dSBill Krier * smb_pathname_validate() should have already been pertformed on pn.
1141fe1c642dSBill Krier *
1142fe1c642dSBill Krier * Very basic file name validation.
1143fe1c642dSBill Krier * For filenames, we check for names of the form "AAAn:". Names that
1144fe1c642dSBill Krier * contain three characters, a single digit and a colon (:) are reserved
1145fe1c642dSBill Krier * as DOS device names, i.e. "COM1:".
1146fe1c642dSBill Krier * Stream name validation is handed off to smb_validate_stream_name
1147fe1c642dSBill Krier *
1148fe1c642dSBill Krier * Returns: B_TRUE if pn->pn_fname is valid,
1149fe1c642dSBill Krier * otherwise returns B_FALSE and sets error status in sr.
1150fe1c642dSBill Krier */
1151fe1c642dSBill Krier boolean_t
smb_validate_object_name(smb_request_t * sr,smb_pathname_t * pn)1152fe1c642dSBill Krier smb_validate_object_name(smb_request_t *sr, smb_pathname_t *pn)
1153fe1c642dSBill Krier {
1154fe1c642dSBill Krier if (pn->pn_fname &&
1155fe1c642dSBill Krier strlen(pn->pn_fname) == 5 &&
1156fe1c642dSBill Krier smb_isdigit(pn->pn_fname[3]) &&
1157fe1c642dSBill Krier pn->pn_fname[4] == ':') {
1158fe1c642dSBill Krier smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
1159fe1c642dSBill Krier ERRDOS, ERROR_INVALID_NAME);
1160fe1c642dSBill Krier return (B_FALSE);
1161fe1c642dSBill Krier }
1162fe1c642dSBill Krier
1163fe1c642dSBill Krier if (pn->pn_sname)
1164fe1c642dSBill Krier return (smb_validate_stream_name(sr, pn));
1165fe1c642dSBill Krier
1166fe1c642dSBill Krier return (B_TRUE);
1167fe1c642dSBill Krier }
1168fe1c642dSBill Krier
1169fe1c642dSBill Krier /*
1170fe1c642dSBill Krier * smb_stream_parse_name
1171fe1c642dSBill Krier *
1172fe1c642dSBill Krier * smb_stream_parse_name should only be called for a path that
1173fe1c642dSBill Krier * contains a valid named stream. Path validation should have
1174d082c877SGordon Ross * been performed before this function is called, typically by
1175d082c877SGordon Ross * calling smb_is_stream_name() just before this.
1176fe1c642dSBill Krier *
1177fe1c642dSBill Krier * Find the last component of path and split it into filename
1178fe1c642dSBill Krier * and stream name.
1179fe1c642dSBill Krier *
1180fe1c642dSBill Krier * On return the named stream type will be present. The stream
1181fe1c642dSBill Krier * type defaults to ":$DATA", if it has not been defined
1182d082c877SGordon Ross * For example, 'stream' contains :<sname>:$DATA
1183d082c877SGordon Ross *
1184d082c877SGordon Ross * Output args: filename, stream both MAXNAMELEN
1185fe1c642dSBill Krier */
1186fe1c642dSBill Krier void
smb_stream_parse_name(char * path,char * filename,char * stream)1187fe1c642dSBill Krier smb_stream_parse_name(char *path, char *filename, char *stream)
1188fe1c642dSBill Krier {
1189fe1c642dSBill Krier char *fname, *sname, *stype;
1190d082c877SGordon Ross size_t flen, slen;
1191fe1c642dSBill Krier
1192fe1c642dSBill Krier ASSERT(path);
1193fe1c642dSBill Krier ASSERT(filename);
1194fe1c642dSBill Krier ASSERT(stream);
1195fe1c642dSBill Krier
1196fe1c642dSBill Krier fname = strrchr(path, '\\');
1197fe1c642dSBill Krier fname = (fname == NULL) ? path : fname + 1;
1198d082c877SGordon Ross sname = strchr(fname, ':');
1199d082c877SGordon Ross /* Caller makes sure there is a ':' in path. */
1200d082c877SGordon Ross VERIFY(sname != NULL);
1201d082c877SGordon Ross /* LINTED: possible ptrdiff_t overflow */
1202d082c877SGordon Ross flen = sname - fname;
1203d082c877SGordon Ross slen = strlen(sname);
1204d082c877SGordon Ross
1205d082c877SGordon Ross if (flen > (MAXNAMELEN-1))
1206d082c877SGordon Ross flen = (MAXNAMELEN-1);
1207d082c877SGordon Ross (void) strncpy(filename, fname, flen);
1208d082c877SGordon Ross filename[flen] = '\0';
1209d082c877SGordon Ross
1210d082c877SGordon Ross if (slen > (MAXNAMELEN-1))
1211d082c877SGordon Ross slen = (MAXNAMELEN-1);
1212d082c877SGordon Ross (void) strncpy(stream, sname, slen);
1213d082c877SGordon Ross stream[slen] = '\0';
1214d082c877SGordon Ross
1215d082c877SGordon Ross /* Add a "stream type" if there isn't one. */
1216fe1c642dSBill Krier stype = strchr(stream + 1, ':');
1217fe1c642dSBill Krier if (stype == NULL)
1218fe1c642dSBill Krier (void) strlcat(stream, ":$DATA", MAXNAMELEN);
1219fe1c642dSBill Krier else
1220fe1c642dSBill Krier (void) smb_strupr(stype);
1221fe1c642dSBill Krier }
1222fe1c642dSBill Krier
1223fe1c642dSBill Krier /*
1224fe1c642dSBill Krier * smb_is_stream_name
1225fe1c642dSBill Krier *
1226fe1c642dSBill Krier * Determines if 'path' specifies a named stream.
1227fe1c642dSBill Krier *
1228fe1c642dSBill Krier * path is a NULL terminated string which could be a stream path.
1229fe1c642dSBill Krier * [pathname/]fname[:stream_name[:stream_type]]
1230fe1c642dSBill Krier *
1231fe1c642dSBill Krier * - If there is no colon in the path or it's the last char
1232fe1c642dSBill Krier * then it's not a stream name
1233fe1c642dSBill Krier *
1234fe1c642dSBill Krier * - '::' is a non-stream and is commonly used by Windows to designate
1235fe1c642dSBill Krier * the unamed stream in the form "::$DATA"
1236fe1c642dSBill Krier */
1237fe1c642dSBill Krier boolean_t
smb_is_stream_name(char * path)1238fe1c642dSBill Krier smb_is_stream_name(char *path)
1239fe1c642dSBill Krier {
1240fe1c642dSBill Krier char *colonp;
1241fe1c642dSBill Krier
1242fe1c642dSBill Krier if (path == NULL)
1243fe1c642dSBill Krier return (B_FALSE);
1244fe1c642dSBill Krier
1245fe1c642dSBill Krier colonp = strchr(path, ':');
1246fe1c642dSBill Krier if ((colonp == NULL) || (*(colonp+1) == '\0'))
1247fe1c642dSBill Krier return (B_FALSE);
1248fe1c642dSBill Krier
1249fe1c642dSBill Krier if (strstr(path, "::"))
1250fe1c642dSBill Krier return (B_FALSE);
1251fe1c642dSBill Krier
1252fe1c642dSBill Krier return (B_TRUE);
1253fe1c642dSBill Krier }
1254fe1c642dSBill Krier
12558d94f651SGordon Ross /*
12568d94f651SGordon Ross * Is this stream node a "restricted" type?
12578d94f651SGordon Ross */
12588d94f651SGordon Ross boolean_t
smb_strname_restricted(char * strname)12598d94f651SGordon Ross smb_strname_restricted(char *strname)
12608d94f651SGordon Ross {
12618d94f651SGordon Ross char *stype;
12628d94f651SGordon Ross
12638d94f651SGordon Ross stype = strrchr(strname, ':');
12648d94f651SGordon Ross if (stype == NULL)
12658d94f651SGordon Ross return (B_FALSE);
12668d94f651SGordon Ross
12678d94f651SGordon Ross /*
12688d94f651SGordon Ross * Only ":$CA" is restricted (for now).
12698d94f651SGordon Ross */
12708d94f651SGordon Ross if (strcmp(stype, ":$CA") == 0)
12718d94f651SGordon Ross return (B_TRUE);
12728d94f651SGordon Ross
12738d94f651SGordon Ross return (B_FALSE);
12748d94f651SGordon Ross }
12758d94f651SGordon Ross
1276fe1c642dSBill Krier /*
1277fe1c642dSBill Krier * smb_validate_stream_name
1278fe1c642dSBill Krier *
1279fe1c642dSBill Krier * B_FALSE will be returned, and the error status ser in the sr, if:
1280fe1c642dSBill Krier * - the path is not a stream name
1281fe1c642dSBill Krier * - a path is specified but the fname is ommitted.
1282fe1c642dSBill Krier * - the stream_type is specified but not valid.
1283fe1c642dSBill Krier *
1284fe1c642dSBill Krier * Note: the stream type is case-insensitive.
1285fe1c642dSBill Krier */
1286fe1c642dSBill Krier boolean_t
smb_validate_stream_name(smb_request_t * sr,smb_pathname_t * pn)1287fe1c642dSBill Krier smb_validate_stream_name(smb_request_t *sr, smb_pathname_t *pn)
1288fe1c642dSBill Krier {
1289fe1c642dSBill Krier static char *strmtype[] = {
12908d94f651SGordon Ross "$CA",
1291fe1c642dSBill Krier "$DATA",
1292fe1c642dSBill Krier "$INDEX_ALLOCATION"
1293fe1c642dSBill Krier };
1294fe1c642dSBill Krier int i;
1295fe1c642dSBill Krier
1296fe1c642dSBill Krier ASSERT(pn);
1297fe1c642dSBill Krier ASSERT(pn->pn_sname);
1298fe1c642dSBill Krier
1299fe1c642dSBill Krier if (pn->pn_stype != NULL) {
1300fe1c642dSBill Krier for (i = 0; i < sizeof (strmtype) / sizeof (strmtype[0]); ++i) {
1301fe1c642dSBill Krier if (strcasecmp(pn->pn_stype, strmtype[i]) == 0)
1302fe1c642dSBill Krier return (B_TRUE);
1303fe1c642dSBill Krier }
1304fe1c642dSBill Krier
1305fe1c642dSBill Krier smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
1306fe1c642dSBill Krier ERRDOS, ERROR_INVALID_NAME);
1307fe1c642dSBill Krier return (B_FALSE);
1308fe1c642dSBill Krier }
1309fe1c642dSBill Krier
1310fe1c642dSBill Krier return (B_TRUE);
1311fe1c642dSBill Krier }
13129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
13149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * valid DFS I/O path:
13159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
13169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * \server-or-domain\share
13179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * \server-or-domain\share\path
13189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
13199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * All the returned errors by this function needs to be
13209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * checked against Windows.
13219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
13229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int
smb_pathname_dfs_preprocess(smb_request_t * sr,char * path,size_t pathsz)13239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_dfs_preprocess(smb_request_t *sr, char *path, size_t pathsz)
13249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
13259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_t unc;
13269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char *linkpath;
13279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int rc;
13289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (sr->tid_tree == NULL)
13309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (0);
13319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((rc = smb_unc_init(path, &unc)) != 0)
13339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (rc);
13349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_strcasecmp(unc.unc_share, sr->tid_tree->t_sharename, 0)) {
13369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_free(&unc);
13379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (EINVAL);
13389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
13399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States linkpath = unc.unc_path;
13419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) snprintf(path, pathsz, "/%s", (linkpath) ? linkpath : "");
13429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_unc_free(&unc);
13449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (0);
13459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
1346