xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_tree.c (revision 8b4261085e0d677be9a3253ff6b4c290e402576d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2016 by Delphix. All rights reserved.
25  * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
26  */
27 
28 /*
29  * General Structures Layout
30  * -------------------------
31  *
32  * This is a simplified diagram showing the relationship between most of the
33  * main structures.
34  *
35  * +-------------------+
36  * |     SMB_INFO      |
37  * +-------------------+
38  *          |
39  *          |
40  *          v
41  * +-------------------+       +-------------------+      +-------------------+
42  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
43  * +-------------------+       +-------------------+      +-------------------+
44  *   |          |
45  *   |          |
46  *   |          v
47  *   |  +-------------------+     +-------------------+   +-------------------+
48  *   |  |       USER        |<--->|       USER        |...|       USER        |
49  *   |  +-------------------+     +-------------------+   +-------------------+
50  *   |
51  *   |
52  *   v
53  * +-------------------+       +-------------------+      +-------------------+
54  * |       TREE        |<----->|       TREE        |......|       TREE        |
55  * +-------------------+       +-------------------+      +-------------------+
56  *      |         |
57  *      |         |
58  *      |         v
59  *      |     +-------+       +-------+      +-------+
60  *      |     | OFILE |<----->| OFILE |......| OFILE |
61  *      |     +-------+       +-------+      +-------+
62  *      |
63  *      |
64  *      v
65  *  +-------+       +------+      +------+
66  *  | ODIR  |<----->| ODIR |......| ODIR |
67  *  +-------+       +------+      +------+
68  *
69  *
70  * Tree State Machine
71  * ------------------
72  *
73  *    +-----------------------------+	 T0
74  *    |  SMB_TREE_STATE_CONNECTED   |<----------- Creation/Allocation
75  *    +-----------------------------+
76  *		    |
77  *		    | T1
78  *		    |
79  *		    v
80  *    +------------------------------+
81  *    | SMB_TREE_STATE_DISCONNECTING |
82  *    +------------------------------+
83  *		    |
84  *		    | T2
85  *		    |
86  *		    v
87  *    +-----------------------------+    T3
88  *    | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free
89  *    +-----------------------------+
90  *
91  * SMB_TREE_STATE_CONNECTED
92  *
93  *    While in this state:
94  *      - The tree is queued in the list of trees of its user.
95  *      - References will be given out if the tree is looked up.
96  *      - Files under that tree can be accessed.
97  *
98  * SMB_TREE_STATE_DISCONNECTING
99  *
100  *    While in this state:
101  *      - The tree is queued in the list of trees of its user.
102  *      - References will not be given out if the tree is looked up.
103  *      - The files and directories open under the tree are being closed.
104  *      - The resources associated with the tree remain.
105  *
106  * SMB_TREE_STATE_DISCONNECTED
107  *
108  *    While in this state:
109  *      - The tree is queued in the list of trees of its user.
110  *      - References will not be given out if the tree is looked up.
111  *      - The tree has no more files and directories opened.
112  *      - The resources associated with the tree remain.
113  *
114  * Transition T0
115  *
116  *    This transition occurs in smb_tree_connect(). A new tree is created and
117  *    added to the list of trees of a user.
118  *
119  * Transition T1
120  *
121  *    This transition occurs in smb_tree_disconnect().
122  *
123  * Transition T2
124  *
125  *    This transition occurs in smb_tree_disconnect()
126  *
127  * Transition T3
128  *
129  *    This transition occurs in smb_tree_release(). The resources associated
130  *    with the tree are freed as well as the tree structure. For the transition
131  *    to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the
132  *    reference count must be zero.
133  *
134  * Comments
135  * --------
136  *
137  *    The state machine of the tree structures is controlled by 3 elements:
138  *      - The list of trees of the user it belongs to.
139  *      - The mutex embedded in the structure itself.
140  *      - The reference count.
141  *
142  *    There's a mutex embedded in the tree structure used to protect its fields
143  *    and there's a lock embedded in the list of trees of a user. To
144  *    increment or to decrement the reference count the mutex must be entered.
145  *    To insert the tree into the list of trees of the user and to remove
146  *    the tree from it, the lock must be entered in RW_WRITER mode.
147  *
148  *    Rules of access to a tree structure:
149  *
150  *    1) In order to avoid deadlocks, when both (mutex and lock of the user
151  *       list) have to be entered, the lock must be entered first. Additionally,
152  *       when both the (mutex and lock of the ofile list) have to be entered,
153  *       the mutex must be entered first. However, the ofile list lock must NOT
154  *       be dropped while the mutex is held in such a way that the ofile deleteq
155  *       is flushed.
156  *
157  *    2) All actions applied to a tree require a reference count.
158  *
159  *    3) There are 2 ways of getting a reference count: when a tree is
160  *       connected and when a tree is looked up.
161  *
162  *    It should be noted that the reference count of a tree registers the
163  *    number of references to the tree in other structures (such as an smb
164  *    request). The reference count is not incremented in these 2 instances:
165  *
166  *    1) The tree is connected. An tree is anchored by its state. If there's
167  *       no activity involving a tree currently connected, the reference
168  *       count of that tree is zero.
169  *
170  *    2) The tree is queued in the list of trees of the user. The fact of
171  *       being queued in that list is NOT registered by incrementing the
172  *       reference count.
173  */
174 
175 #include <sys/refstr_impl.h>
176 #include <smbsrv/smb_kproto.h>
177 #include <smbsrv/smb_ktypes.h>
178 #include <smbsrv/smb_fsops.h>
179 #include <smbsrv/smb_share.h>
180 
181 int smb_tcon_mute = 0;
182 
183 uint32_t	smb_tree_connect_core(smb_request_t *);
184 uint32_t	smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *);
185 uint32_t	smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *);
186 uint32_t	smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *);
187 static void smb_tree_dealloc(void *);
188 static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
189 static char *smb_tree_get_sharename(char *);
190 static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *);
191 static void smb_tree_get_creation(smb_node_t *, smb_tree_t *);
192 static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
193 static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *);
194 static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
195 static void smb_tree_close_odirs(smb_tree_t *, uint32_t);
196 static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int);
197 static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *);
198 static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *);
199 static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *);
200 static void smb_tree_netinfo_fini(smb_netconnectinfo_t *);
201 
202 uint32_t
203 smb_tree_connect(smb_request_t *sr)
204 {
205 	smb_server_t	*sv = sr->sr_server;
206 	uint32_t status;
207 
208 	if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) {
209 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
210 	}
211 
212 	status = smb_tree_connect_core(sr);
213 	smb_threshold_exit(&sv->sv_tcon_ct);
214 	return (status);
215 }
216 
217 /*
218  * Lookup the share name dispatch the appropriate stype handler.
219  * Share names are case insensitive so we map the share name to
220  * lower-case as a convenience for internal processing.
221  *
222  * Valid service values are:
223  *	A:      Disk share
224  *	LPT1:   Printer
225  *	IPC     Named pipe (IPC$ is reserved as the named pipe share).
226  *	COMM    Communications device
227  *	?????   Any type of device (wildcard)
228  */
229 uint32_t
230 smb_tree_connect_core(smb_request_t *sr)
231 {
232 	smb_arg_tcon_t	*tcon = &sr->sr_tcon;
233 	smb_kshare_t	*si;
234 	char		*name;
235 	uint32_t	status;
236 
237 	(void) smb_strlwr(tcon->path);
238 
239 	if ((name = smb_tree_get_sharename(tcon->path)) == NULL) {
240 		smb_tree_log(sr, tcon->path, "invalid UNC path");
241 		return (NT_STATUS_BAD_NETWORK_NAME);
242 	}
243 
244 	si = smb_kshare_lookup(sr->sr_server, name);
245 	if (si == NULL) {
246 		smb_tree_log(sr, name, "share not found");
247 		return (NT_STATUS_BAD_NETWORK_NAME);
248 	}
249 
250 	if (!strcasecmp(SMB_SHARE_PRINT, name)) {
251 		smb_kshare_release(sr->sr_server, si);
252 		smb_tree_log(sr, name, "access not permitted");
253 		return (NT_STATUS_ACCESS_DENIED);
254 	}
255 
256 	/* NB: name points into tcon->path - don't free it. */
257 	tcon->name = name;
258 	sr->sr_tcon.si = si;
259 
260 	/*
261 	 * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request
262 	 *
263 	 * If we support 3.x, RejectUnencryptedAccess is TRUE,
264 	 * if Tcon.EncryptData is TRUE or global EncryptData is TRUE,
265 	 * and the connection doesn't support encryption,
266 	 * return ACCESS_DENIED.
267 	 *
268 	 * If RejectUnencryptedAccess is TRUE, we force max_protocol
269 	 * to at least 3.0. Additionally, if the tree requires encryption,
270 	 * we don't care what we support, we still enforce encryption.
271 	 */
272 	if ((sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED ||
273 	    si->shr_encrypt == SMB_CONFIG_REQUIRED) &&
274 	    (sr->session->srv_cap & SMB2_CAP_ENCRYPTION) == 0) {
275 		status = NT_STATUS_ACCESS_DENIED;
276 		goto out;
277 	}
278 
279 	switch (si->shr_type & STYPE_MASK) {
280 	case STYPE_DISKTREE:
281 		status = smb_tree_connect_disk(sr, &sr->sr_tcon);
282 		break;
283 	case STYPE_IPC:
284 		status = smb_tree_connect_ipc(sr, &sr->sr_tcon);
285 		break;
286 	case STYPE_PRINTQ:
287 		status = smb_tree_connect_printq(sr, &sr->sr_tcon);
288 		break;
289 	default:
290 		status = NT_STATUS_BAD_DEVICE_TYPE;
291 		break;
292 	}
293 
294 out:
295 	smb_kshare_release(sr->sr_server, si);
296 	sr->sr_tcon.si = NULL;
297 
298 	return (status);
299 }
300 
301 /*
302  * Disconnect a tree.
303  *
304  * The "do_exec" arg is obsolete and ignored.
305  */
306 void
307 smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec)
308 {
309 	_NOTE(ARGUNUSED(do_exec))
310 	smb_shr_execinfo_t execinfo;
311 
312 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
313 
314 	mutex_enter(&tree->t_mutex);
315 	ASSERT(tree->t_refcnt);
316 
317 	if (!smb_tree_is_connected_locked(tree)) {
318 		mutex_exit(&tree->t_mutex);
319 		return;
320 	}
321 
322 	/*
323 	 * Indicate that the disconnect process has started.
324 	 */
325 	tree->t_state = SMB_TREE_STATE_DISCONNECTING;
326 	mutex_exit(&tree->t_mutex);
327 
328 	/*
329 	 * The files opened under this tree are closed.
330 	 */
331 	smb_ofile_close_all(tree, 0);
332 	/*
333 	 * The directories opened under this tree are closed.
334 	 */
335 	smb_tree_close_odirs(tree, 0);
336 
337 	if ((tree->t_execflags & SMB_EXEC_UNMAP) != 0) {
338 		smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP);
339 		(void) smb_kshare_exec(tree->t_server, &execinfo);
340 	}
341 }
342 
343 /*
344  * Take a reference on a tree.
345  */
346 boolean_t
347 smb_tree_hold(
348     smb_tree_t		*tree)
349 {
350 	SMB_TREE_VALID(tree);
351 
352 	mutex_enter(&tree->t_mutex);
353 
354 	if (smb_tree_is_connected_locked(tree)) {
355 		tree->t_refcnt++;
356 		mutex_exit(&tree->t_mutex);
357 		return (B_TRUE);
358 	}
359 
360 	mutex_exit(&tree->t_mutex);
361 	return (B_FALSE);
362 }
363 
364 /*
365  * Bump the hold count regardless of the tree state.  This is used in
366  * some internal code paths where we've already checked that we had a
367  * valid tree connection, and don't want to deal with the possiblity
368  * that the tree state might have changed to disconnecting after our
369  * original hold was taken.  It's correct to continue processing a
370  * request even when new requests cannot lookup that tree anymore.
371  */
372 void
373 smb_tree_hold_internal(
374     smb_tree_t		*tree)
375 {
376 	SMB_TREE_VALID(tree);
377 
378 	mutex_enter(&tree->t_mutex);
379 	tree->t_refcnt++;
380 	mutex_exit(&tree->t_mutex);
381 }
382 
383 /*
384  * Release a reference on a tree.  If the tree is disconnected and the
385  * reference count falls to zero, post the object for deletion.
386  * Object deletion is deferred to avoid modifying a list while an
387  * iteration may be in progress.
388  */
389 void
390 smb_tree_release(
391     smb_tree_t		*tree)
392 {
393 	SMB_TREE_VALID(tree);
394 
395 	/* flush the ofile and odir lists' delete queues */
396 	smb_llist_flush(&tree->t_ofile_list);
397 	smb_llist_flush(&tree->t_odir_list);
398 
399 	mutex_enter(&tree->t_mutex);
400 	ASSERT(tree->t_refcnt);
401 	tree->t_refcnt--;
402 
403 	switch (tree->t_state) {
404 	case SMB_TREE_STATE_DISCONNECTING:
405 		if (tree->t_refcnt == 0) {
406 			smb_session_t *ssn = tree->t_session;
407 			tree->t_state = SMB_TREE_STATE_DISCONNECTED;
408 			smb_llist_post(&ssn->s_tree_list, tree,
409 			    smb_tree_dealloc);
410 		}
411 		break;
412 	case SMB_TREE_STATE_CONNECTED:
413 		break;
414 	default:
415 		ASSERT(0);
416 		break;
417 	}
418 
419 	mutex_exit(&tree->t_mutex);
420 }
421 
422 /*
423  * Close ofiles and odirs that match pid.
424  */
425 void
426 smb_tree_close_pid(
427     smb_tree_t		*tree,
428     uint32_t		pid)
429 {
430 	ASSERT(tree);
431 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
432 
433 	smb_ofile_close_all(tree, pid);
434 	smb_tree_close_odirs(tree, pid);
435 }
436 
437 /*
438  * Check whether or not a tree supports the features identified by flags.
439  */
440 boolean_t
441 smb_tree_has_feature(smb_tree_t *tree, uint32_t flags)
442 {
443 	ASSERT(tree);
444 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
445 
446 	return ((tree->t_flags & flags) == flags);
447 }
448 
449 /*
450  * If the enumeration request is for tree data, handle the request
451  * here.  Otherwise, pass it on to the ofiles.
452  *
453  * This function should be called with a hold on the tree.
454  */
455 int
456 smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
457 {
458 	smb_llist_t	*of_list;
459 	smb_ofile_t	*of;
460 	int		rc = 0;
461 
462 	if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE)
463 		return (smb_tree_enum_private(tree, svcenum));
464 
465 	of_list = &tree->t_ofile_list;
466 	smb_llist_enter(of_list, RW_READER);
467 
468 	of = smb_llist_head(of_list);
469 	while (of) {
470 		if (smb_ofile_hold(of)) {
471 			rc = smb_ofile_enum(of, svcenum);
472 			smb_ofile_release(of);
473 		}
474 		if (rc != 0)
475 			break;
476 		of = smb_llist_next(of_list, of);
477 	}
478 
479 	smb_llist_exit(of_list);
480 
481 	return (rc);
482 }
483 
484 /*
485  * Close a file by its unique id.
486  */
487 int
488 smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid)
489 {
490 	smb_ofile_t	*of;
491 
492 	ASSERT(tree);
493 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
494 
495 	/*
496 	 * Note that ORPHANED ofiles aren't fclosable, as they have
497 	 * no session, user, or tree by which they might be found.
498 	 * They will eventually expire.
499 	 */
500 	if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL)
501 		return (ENOENT);
502 
503 	if (smb_ofile_disallow_fclose(of)) {
504 		smb_ofile_release(of);
505 		return (EACCES);
506 	}
507 
508 	smb_ofile_close(of, 0);
509 	smb_ofile_release(of);
510 	return (0);
511 }
512 
513 /* *************************** Static Functions ***************************** */
514 
515 #define	SHARES_DIR	".zfs/shares/"
516 
517 /*
518  * Calculates permissions given by the share's ACL to the
519  * user in the passed request.  The default is full access.
520  * If any error occurs, full access is granted.
521  *
522  * Using the vnode of the share path find the root directory
523  * of the mounted file system. Then look to see if there is a
524  * .zfs/shares directory and if there is, lookup the file with
525  * the same name as the share name in it. The ACL set for this
526  * file is the share's ACL which is used for access check here.
527  */
528 static uint32_t
529 smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp)
530 {
531 	smb_user_t	*user;
532 	cred_t		*cred;
533 	int		rc;
534 	vfs_t		*vfsp;
535 	vnode_t		*root = NULL;
536 	vnode_t		*sharevp = NULL;
537 	char		*sharepath;
538 	struct pathname	pnp;
539 	size_t		size;
540 	uint32_t	access;
541 
542 	user = sr->uid_user;
543 	cred = user->u_cred;
544 	access = ACE_ALL_PERMS;
545 
546 	if (si->shr_flags & SMB_SHRF_AUTOHOME) {
547 		/*
548 		 * An autohome share owner gets full access to the share.
549 		 * Everyone else is denied access.
550 		 */
551 		if (si->shr_uid != crgetuid(cred))
552 			access = 0;
553 
554 		return (access);
555 	}
556 
557 	/*
558 	 * The hold on 'root' is released by the lookuppnvp() that follows
559 	 */
560 	vfsp = pathvp->v_vfsp;
561 	if (vfsp != NULL)
562 		rc = VFS_ROOT(vfsp, &root);
563 	else
564 		rc = ENOENT;
565 
566 	if (rc != 0)
567 		return (access);
568 
569 
570 	size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1;
571 	sharepath = smb_srm_alloc(sr, size);
572 	(void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name);
573 
574 	pn_alloc(&pnp);
575 	(void) pn_set(&pnp, sharepath);
576 	rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root,
577 	    zone_kcred());
578 	pn_free(&pnp);
579 
580 	/*
581 	 * Now get the effective access value based on cred and ACL values.
582 	 */
583 	if (rc == 0) {
584 		smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL,
585 		    cred);
586 		VN_RELE(sharevp);
587 	}
588 
589 	return (access);
590 }
591 
592 /*
593  * Performs the following access checks for a disk share:
594  *
595  *  - No IPC/anonymous user is allowed
596  *
597  *  - If user is Guest, guestok property of the share should be
598  *    enabled
599  *
600  *  - If this is an Admin share, the user should have administrative
601  *    privileges
602  *
603  *  - Host based access control lists
604  *
605  *  - Share ACL
606  *
607  *  Returns the access allowed or 0 if access is denied.
608  */
609 static uint32_t
610 smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp)
611 {
612 	smb_user_t *user = sr->uid_user;
613 	char *sharename = shr->shr_name;
614 	uint32_t host_access;
615 	uint32_t acl_access;
616 	uint32_t access;
617 
618 	if (user->u_flags & SMB_USER_FLAG_ANON) {
619 		smb_tree_log(sr, sharename, "access denied: IPC only");
620 		return (0);
621 	}
622 
623 	if ((user->u_flags & SMB_USER_FLAG_GUEST) &&
624 	    ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) {
625 		smb_tree_log(sr, sharename, "access denied: guest disabled");
626 		return (0);
627 	}
628 
629 	if ((shr->shr_flags & SMB_SHRF_ADMIN) && !smb_user_is_admin(user)) {
630 		smb_tree_log(sr, sharename, "access denied: not admin");
631 		return (0);
632 	}
633 
634 	host_access = smb_kshare_hostaccess(shr, sr->session);
635 	if ((host_access & ACE_ALL_PERMS) == 0) {
636 		smb_tree_log(sr, sharename, "access denied: host access");
637 		return (0);
638 	}
639 
640 	acl_access = smb_tree_acl_access(sr, shr, vp);
641 	if ((acl_access & ACE_ALL_PERMS) == 0) {
642 		smb_tree_log(sr, sharename, "access denied: share ACL");
643 		return (0);
644 	}
645 
646 	access = host_access & acl_access;
647 	if ((access & ACE_ALL_PERMS) == 0) {
648 		smb_tree_log(sr, sharename, "access denied");
649 		return (0);
650 	}
651 
652 	return (access);
653 }
654 
655 /* How long should tree connect wait for DH import to complete? */
656 int smb_tcon_import_wait = 20; /* sec. */
657 
658 /*
659  * Connect a share for use with files and directories.
660  */
661 uint32_t
662 smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon)
663 {
664 	char			*sharename = tcon->path;
665 	const char		*any = "?????";
666 	smb_user_t		*user = sr->uid_user;
667 	smb_node_t		*snode = NULL;
668 	smb_kshare_t		*si = tcon->si;
669 	char			*service = tcon->service;
670 	smb_tree_t		*tree;
671 	int			rc;
672 	uint32_t		access;
673 	smb_shr_execinfo_t	execinfo;
674 	clock_t	time;
675 
676 	ASSERT(user);
677 	ASSERT(user->u_cred);
678 
679 	if (service != NULL &&
680 	    strcmp(service, any) != 0 &&
681 	    strcasecmp(service, "A:") != 0) {
682 		smb_tree_log(sr, sharename, "invalid service (%s)", service);
683 		return (NT_STATUS_BAD_DEVICE_TYPE);
684 	}
685 
686 	/*
687 	 * Check that the shared directory exists.
688 	 */
689 	snode = si->shr_root_node;
690 	if (snode == NULL) {
691 		smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
692 		return (NT_STATUS_BAD_NETWORK_NAME);
693 	}
694 
695 	if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
696 		return (NT_STATUS_ACCESS_DENIED);
697 	}
698 
699 	/*
700 	 * Wait for DH import of persistent handles to finish.
701 	 * If we timeout, it's not clear what status to return,
702 	 * but as the share is not really available yet, let's
703 	 * return the status for "no such share".
704 	 */
705 	time = SEC_TO_TICK(smb_tcon_import_wait) + ddi_get_lbolt();
706 	mutex_enter(&si->shr_mutex);
707 	while (si->shr_import_busy != NULL) {
708 		if (cv_timedwait(&si->shr_cv, &si->shr_mutex, time) < 0) {
709 			mutex_exit(&si->shr_mutex);
710 			return (NT_STATUS_BAD_NETWORK_NAME);
711 		}
712 	}
713 	mutex_exit(&si->shr_mutex);
714 
715 	/*
716 	 * Set up the OptionalSupport for this share.
717 	 */
718 	tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
719 
720 	switch (si->shr_flags & SMB_SHRF_CSC_MASK) {
721 	case SMB_SHRF_CSC_DISABLED:
722 		tcon->optional_support |= SMB_CSC_CACHE_NONE;
723 		break;
724 	case SMB_SHRF_CSC_AUTO:
725 		tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT;
726 		break;
727 	case SMB_SHRF_CSC_VDO:
728 		tcon->optional_support |= SMB_CSC_CACHE_VDO;
729 		break;
730 	case SMB_SHRF_CSC_MANUAL:
731 	default:
732 		/*
733 		 * Default to SMB_CSC_CACHE_MANUAL_REINT.
734 		 */
735 		break;
736 	}
737 
738 	/* ABE support */
739 	if (si->shr_flags & SMB_SHRF_ABE)
740 		tcon->optional_support |=
741 		    SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM;
742 
743 	if (si->shr_flags & SMB_SHRF_DFSROOT)
744 		tcon->optional_support |= SMB_SHARE_IS_IN_DFS;
745 
746 	tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
747 
748 	if (tree == NULL)
749 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
750 
751 	if (tree->t_flags & SMB_TREE_SHORTNAMES)
752 		tcon->optional_support |= SMB_UNIQUE_FILE_NAME;
753 
754 	if (tree->t_execflags & SMB_EXEC_MAP) {
755 		smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
756 
757 		rc = smb_kshare_exec(tree->t_server, &execinfo);
758 
759 		if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
760 			/*
761 			 * Inline parts of: smb_tree_disconnect()
762 			 * Not using smb_tree_disconnect() for cleanup
763 			 * here because: we don't want an exec up-call,
764 			 * and there can't be any opens as we never
765 			 * returned this TID to the client.
766 			 */
767 			mutex_enter(&tree->t_mutex);
768 			tree->t_state = SMB_TREE_STATE_DISCONNECTING;
769 			mutex_exit(&tree->t_mutex);
770 
771 			smb_tree_release(tree);
772 			return (NT_STATUS_ACCESS_DENIED);
773 		}
774 	}
775 
776 	sr->tid_tree = tree;
777 	sr->smb_tid  = tree->t_tid;
778 
779 	return (0);
780 }
781 
782 /*
783  * Shares have both a share and host based access control.  The access
784  * granted will be minimum permissions based on both hostaccess
785  * (permissions allowed by host based access) and aclaccess (from the
786  * share ACL).
787  */
788 uint32_t
789 smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
790 {
791 	char			*sharename = tcon->path;
792 	const char		*any = "?????";
793 	smb_user_t		*user = sr->uid_user;
794 	smb_node_t		*dnode = NULL;
795 	smb_node_t		*snode = NULL;
796 	smb_kshare_t		*si = tcon->si;
797 	char			*service = tcon->service;
798 	char			last_component[MAXNAMELEN];
799 	smb_tree_t		*tree;
800 	int			rc;
801 	uint32_t		access;
802 
803 	ASSERT(user);
804 	ASSERT(user->u_cred);
805 
806 	if (sr->sr_server->sv_cfg.skc_print_enable == 0) {
807 		smb_tree_log(sr, sharename, "printing disabled");
808 		return (NT_STATUS_BAD_NETWORK_NAME);
809 	}
810 
811 	if (service != NULL &&
812 	    strcmp(service, any) != 0 &&
813 	    strcasecmp(service, "LPT1:") != 0) {
814 		smb_tree_log(sr, sharename, "invalid service (%s)", service);
815 		return (NT_STATUS_BAD_DEVICE_TYPE);
816 	}
817 
818 	/*
819 	 * Check that the shared directory exists.
820 	 */
821 	rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
822 	    last_component);
823 	if (rc == 0) {
824 		rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
825 		    sr->sr_server->si_root_smb_node, dnode, last_component,
826 		    &snode);
827 
828 		smb_node_release(dnode);
829 	}
830 
831 	if (rc) {
832 		if (snode)
833 			smb_node_release(snode);
834 
835 		smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
836 		return (NT_STATUS_BAD_NETWORK_NAME);
837 	}
838 
839 	if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
840 		smb_node_release(snode);
841 		return (NT_STATUS_ACCESS_DENIED);
842 	}
843 
844 	tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
845 
846 	tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
847 
848 	smb_node_release(snode);
849 
850 	if (tree == NULL)
851 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
852 
853 	sr->tid_tree = tree;
854 	sr->smb_tid  = tree->t_tid;
855 
856 	return (0);
857 }
858 
859 /*
860  * Connect an IPC share for use with named pipes.
861  */
862 uint32_t
863 smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon)
864 {
865 	char		*name = tcon->path;
866 	const char	*any = "?????";
867 	smb_user_t	*user = sr->uid_user;
868 	smb_tree_t	*tree;
869 	smb_kshare_t	*si = tcon->si;
870 	char		*service = tcon->service;
871 
872 	ASSERT(user);
873 
874 	if (service != NULL &&
875 	    strcmp(service, any) != 0 &&
876 	    strcasecmp(service, "IPC") != 0) {
877 		smb_tree_log(sr, name, "invalid service (%s)", service);
878 		return (NT_STATUS_BAD_DEVICE_TYPE);
879 	}
880 
881 	if ((user->u_flags & SMB_USER_FLAG_ANON) &&
882 	    sr->sr_cfg->skc_restrict_anon) {
883 		smb_tree_log(sr, name, "access denied: restrict anonymous");
884 		return (NT_STATUS_ACCESS_DENIED);
885 	}
886 
887 	tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
888 
889 	tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
890 	if (tree == NULL)
891 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
892 
893 	sr->tid_tree = tree;
894 	sr->smb_tid  = tree->t_tid;
895 
896 	return (0);
897 }
898 
899 /*
900  * Allocate a tree.
901  */
902 smb_tree_t *
903 smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
904     smb_node_t *snode, uint32_t access, uint32_t execflags)
905 {
906 	smb_session_t	*session = sr->session;
907 	smb_tree_t	*tree;
908 	uint32_t	stype = si->shr_type;
909 	uint16_t	tid;
910 
911 	if (smb_idpool_alloc(&session->s_tid_pool, &tid))
912 		return (NULL);
913 
914 	tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP);
915 	bzero(tree, sizeof (smb_tree_t));
916 
917 	tree->t_session = session;
918 	tree->t_server = session->s_server;
919 
920 	if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
921 		if (smb_tree_getattr(si, snode, tree) != 0) {
922 			smb_idpool_free(&session->s_tid_pool, tid);
923 			kmem_cache_free(smb_cache_tree, tree);
924 			return (NULL);
925 		}
926 	}
927 
928 	if (smb_idpool_constructor(&tree->t_fid_pool)) {
929 		smb_idpool_free(&session->s_tid_pool, tid);
930 		kmem_cache_free(smb_cache_tree, tree);
931 		return (NULL);
932 	}
933 
934 	if (smb_idpool_constructor(&tree->t_odid_pool)) {
935 		smb_idpool_destructor(&tree->t_fid_pool);
936 		smb_idpool_free(&session->s_tid_pool, tid);
937 		kmem_cache_free(smb_cache_tree, tree);
938 		return (NULL);
939 	}
940 
941 	smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
942 	    offsetof(smb_ofile_t, f_tree_lnd));
943 
944 	smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
945 	    offsetof(smb_odir_t, d_lnd));
946 
947 	(void) strlcpy(tree->t_sharename, si->shr_name,
948 	    sizeof (tree->t_sharename));
949 	(void) strlcpy(tree->t_resource, si->shr_path,
950 	    sizeof (tree->t_resource));
951 
952 	mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
953 
954 	tree->t_refcnt = 1;
955 	tree->t_tid = tid;
956 	tree->t_res_type = stype;
957 	tree->t_state = SMB_TREE_STATE_CONNECTED;
958 	tree->t_magic = SMB_TREE_MAGIC;
959 	tree->t_access = access;
960 	tree->t_connect_time = gethrestime_sec();
961 	tree->t_execflags = execflags;
962 
963 	/* grab a ref for tree->t_owner */
964 	smb_user_hold_internal(sr->uid_user);
965 	smb_user_inc_trees(sr->uid_user);
966 	tree->t_owner = sr->uid_user;
967 
968 	/* if FS is readonly, enforce that here */
969 	if (tree->t_flags & SMB_TREE_READONLY)
970 		tree->t_access &= ~ACE_ALL_WRITE_PERMS;
971 
972 	if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
973 		smb_node_ref(snode);
974 		tree->t_snode = snode;
975 		tree->t_acltype = smb_fsop_acltype(snode);
976 	}
977 
978 	smb_llist_enter(&session->s_tree_list, RW_WRITER);
979 	smb_llist_insert_head(&session->s_tree_list, tree);
980 	smb_llist_exit(&session->s_tree_list);
981 	atomic_inc_32(&session->s_tree_cnt);
982 	smb_server_inc_trees(session->s_server);
983 	return (tree);
984 }
985 
986 /*
987  * Deallocate a tree.  The open file and open directory lists should be
988  * empty.
989  *
990  * Remove the tree from the user's tree list before freeing resources
991  * associated with the tree.
992  */
993 static void
994 smb_tree_dealloc(void *arg)
995 {
996 	smb_session_t	*session;
997 	smb_tree_t	*tree = (smb_tree_t *)arg;
998 
999 	SMB_TREE_VALID(tree);
1000 	ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
1001 	ASSERT(tree->t_refcnt == 0);
1002 
1003 	smb_server_dec_trees(tree->t_server);
1004 
1005 	session = tree->t_session;
1006 	smb_llist_enter(&session->s_tree_list, RW_WRITER);
1007 	smb_llist_remove(&session->s_tree_list, tree);
1008 	smb_idpool_free(&session->s_tid_pool, tree->t_tid);
1009 	atomic_dec_32(&session->s_tree_cnt);
1010 	smb_llist_exit(&session->s_tree_list);
1011 
1012 	/*
1013 	 * This tree is no longer on s_tree_list, however...
1014 	 *
1015 	 * This is called via smb_llist_post, which means it may run
1016 	 * BEFORE smb_tree_release drops t_mutex (if another thread
1017 	 * flushes the delete queue before we do).  Synchronize.
1018 	 */
1019 	mutex_enter(&tree->t_mutex);
1020 	mutex_exit(&tree->t_mutex);
1021 
1022 	tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
1023 
1024 	if (tree->t_snode)
1025 		smb_node_release(tree->t_snode);
1026 
1027 	mutex_destroy(&tree->t_mutex);
1028 	smb_llist_destructor(&tree->t_ofile_list);
1029 	smb_llist_destructor(&tree->t_odir_list);
1030 	smb_idpool_destructor(&tree->t_fid_pool);
1031 	smb_idpool_destructor(&tree->t_odid_pool);
1032 
1033 	SMB_USER_VALID(tree->t_owner);
1034 	smb_user_dec_trees(tree->t_owner);
1035 	smb_user_release(tree->t_owner);
1036 
1037 	kmem_cache_free(smb_cache_tree, tree);
1038 }
1039 
1040 /*
1041  * Determine whether or not a tree is connected.
1042  * This function must be called with the tree mutex held.
1043  */
1044 static boolean_t
1045 smb_tree_is_connected_locked(smb_tree_t *tree)
1046 {
1047 	switch (tree->t_state) {
1048 	case SMB_TREE_STATE_CONNECTED:
1049 		return (B_TRUE);
1050 
1051 	case SMB_TREE_STATE_DISCONNECTING:
1052 	case SMB_TREE_STATE_DISCONNECTED:
1053 		/*
1054 		 * The tree exists but is being disconnected or destroyed.
1055 		 */
1056 		return (B_FALSE);
1057 
1058 	default:
1059 		ASSERT(0);
1060 		return (B_FALSE);
1061 	}
1062 }
1063 
1064 /*
1065  * Return a pointer to the share name within a share resource path.
1066  *
1067  * The share path may be a Uniform Naming Convention (UNC) string
1068  * (\\server\share) or simply the share name.  We validate the UNC
1069  * format but we don't look at the server name.
1070  */
1071 static char *
1072 smb_tree_get_sharename(char *unc_path)
1073 {
1074 	char *sharename = unc_path;
1075 
1076 	if (sharename[0] == '\\') {
1077 		/*
1078 		 * Looks like a UNC path, validate the format.
1079 		 */
1080 		if (sharename[1] != '\\')
1081 			return (NULL);
1082 
1083 		if ((sharename = strchr(sharename+2, '\\')) == NULL)
1084 			return (NULL);
1085 
1086 		++sharename;
1087 	} else if (strchr(sharename, '\\') != NULL) {
1088 		/*
1089 		 * This should be a share name (no embedded \'s).
1090 		 */
1091 		return (NULL);
1092 	}
1093 
1094 	return (sharename);
1095 }
1096 
1097 /*
1098  * Obtain the tree attributes: volume name, typename and flags.
1099  * Called only with DISK and PRINTQ shares.
1100  */
1101 static int
1102 smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1103 {
1104 	vfs_t *vfsp = SMB_NODE_VFS(node);
1105 	vfs_t *realvfsp;
1106 	smb_cfg_val_t srv_encrypt;
1107 
1108 	ASSERT(vfsp);
1109 
1110 	smb_tree_get_creation(node, tree);
1111 	smb_tree_get_volname(vfsp, tree);
1112 
1113 	/*
1114 	 * In the case of an lofs mount, we need to ask the (real)
1115 	 * underlying filesystem about capabilities, where the
1116 	 * passed in vfs_t will be from lofs.
1117 	 */
1118 	realvfsp = getvfs(&vfsp->vfs_fsid);
1119 	if (realvfsp != NULL) {
1120 		smb_tree_get_flags(si, realvfsp, tree);
1121 		VFS_RELE(realvfsp);
1122 	} else {
1123 		cmn_err(CE_NOTE, "Failed getting info for share: %s",
1124 		    si->shr_name);
1125 		/* do the best we can without realvfsp */
1126 		smb_tree_get_flags(si, vfsp, tree);
1127 	}
1128 
1129 	srv_encrypt = tree->t_session->s_server->sv_cfg.skc_encrypt;
1130 	if (tree->t_session->dialect >= SMB_VERS_3_0) {
1131 		if (si->shr_encrypt == SMB_CONFIG_REQUIRED ||
1132 		    srv_encrypt == SMB_CONFIG_REQUIRED)
1133 			tree->t_encrypt = SMB_CONFIG_REQUIRED;
1134 		else if (si->shr_encrypt == SMB_CONFIG_ENABLED ||
1135 		    srv_encrypt == SMB_CONFIG_ENABLED)
1136 			tree->t_encrypt = SMB_CONFIG_ENABLED;
1137 		else
1138 			tree->t_encrypt = SMB_CONFIG_DISABLED;
1139 	} else
1140 		tree->t_encrypt = SMB_CONFIG_DISABLED;
1141 
1142 	return (0);
1143 }
1144 
1145 /*
1146  * File volume creation time
1147  */
1148 static void
1149 smb_tree_get_creation(smb_node_t *node, smb_tree_t *tree)
1150 {
1151 	smb_attr_t	attr;
1152 	cred_t		*kcr = zone_kcred();
1153 
1154 	bzero(&attr, sizeof (attr));
1155 	attr.sa_mask = SMB_AT_CRTIME;
1156 	(void) smb_node_getattr(NULL, node, kcr, NULL, &attr);
1157 	/* On failure we'll have time zero, which is OK */
1158 
1159 	tree->t_create_time = attr.sa_crtime;
1160 }
1161 
1162 /*
1163  * Extract the volume name.
1164  */
1165 static void
1166 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1167 {
1168 #ifdef	_FAKE_KERNEL
1169 	_NOTE(ARGUNUSED(vfsp))
1170 	(void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN);
1171 #else	/* _FAKE_KERNEL */
1172 	refstr_t *vfs_mntpoint;
1173 	const char *s;
1174 	char *name;
1175 
1176 	vfs_mntpoint = vfs_getmntpoint(vfsp);
1177 
1178 	s = refstr_value(vfs_mntpoint);
1179 	s += strspn(s, "/");
1180 	(void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN);
1181 
1182 	refstr_rele(vfs_mntpoint);
1183 
1184 	name = tree->t_volume;
1185 	(void) strsep((char **)&name, "/");
1186 #endif	/* _FAKE_KERNEL */
1187 }
1188 
1189 /*
1190  * Get flags from the VFS (and other places) for a new tree.
1191  * Called only with DISK and PRINTQ shares.
1192  *
1193  * Always set "unicode on disk" because we always use utf8 names locally.
1194  * Always set ACL support because the VFS will fake ACLs for file systems
1195  * that don't support them.
1196  *
1197  * Some flags are dependent on the typename, which is also set up here.
1198  * File system types are hardcoded in uts/common/os/vfs_conf.c.
1199  */
1200 static void
1201 smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
1202 {
1203 	smb_session_t *ssn = tree->t_session;
1204 	struct vfssw	*vswp;
1205 
1206 	typedef struct smb_mtype {
1207 		char		*mt_name;
1208 		size_t		mt_namelen;
1209 		uint32_t	mt_flags;
1210 	} smb_mtype_t;
1211 
1212 	static smb_mtype_t smb_mtype[] = {
1213 #ifdef	_FAKE_KERNEL
1214 		/* See libfksmbsrv:fake_vfs.c */
1215 		{ "fake",    3,	SMB_TREE_SPARSE},
1216 #endif	/* _FAKE_KERNEL */
1217 		{ "zfs",    3,	SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1218 		{ "ufs",    3,	0 },
1219 		{ "nfs",    3,	SMB_TREE_NFS_MOUNTED },
1220 		{ "tmpfs",  5,	SMB_TREE_NO_EXPORT }
1221 	};
1222 	smb_mtype_t	*mtype;
1223 	char		*name;
1224 	uint32_t	flags =
1225 	    SMB_TREE_SUPPORTS_ACLS |
1226 	    SMB_TREE_UNICODE_ON_DISK;
1227 	int		i;
1228 
1229 	if (si->shr_flags & SMB_SHRF_DFSROOT)
1230 		flags |= SMB_TREE_DFSROOT;
1231 
1232 	if (si->shr_flags & SMB_SHRF_CATIA)
1233 		flags |= SMB_TREE_CATIA;
1234 
1235 	if (si->shr_flags & SMB_SHRF_ABE)
1236 		flags |= SMB_TREE_ABE;
1237 
1238 	if (si->shr_flags & SMB_SHRF_CA)
1239 		flags |= SMB_TREE_CA;
1240 
1241 	if (si->shr_flags & SMB_SHRF_FSO)
1242 		flags |= SMB_TREE_FORCE_L2_OPLOCK;
1243 
1244 	if (ssn->s_cfg.skc_oplock_enable)
1245 		flags |= SMB_TREE_OPLOCKS;
1246 
1247 	if (ssn->s_cfg.skc_traverse_mounts)
1248 		flags |= SMB_TREE_TRAVERSE_MOUNTS;
1249 
1250 	if (ssn->s_cfg.skc_short_names)
1251 		flags |= SMB_TREE_SHORTNAMES;
1252 
1253 	if (vfsp->vfs_flag & VFS_RDONLY)
1254 		flags |= SMB_TREE_READONLY;
1255 
1256 	if (vfsp->vfs_flag & VFS_XATTR)
1257 		flags |= SMB_TREE_STREAMS;
1258 
1259 	vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
1260 	if (vswp != NULL) {
1261 		name = vswp->vsw_name;
1262 		vfs_unrefvfssw(vswp);
1263 	} else {
1264 		name = "?";
1265 	}
1266 
1267 	for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1268 		mtype = &smb_mtype[i];
1269 		if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1270 			flags |= mtype->mt_flags;
1271 	}
1272 
1273 	/*
1274 	 * SMB_TREE_QUOTA will be on here if the FS is ZFS.  We want to
1275 	 * turn it OFF when the share property says false.
1276 	 */
1277 	if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0)
1278 		flags &= ~SMB_TREE_QUOTA;
1279 
1280 	(void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1281 	(void) smb_strupr((char *)tree->t_typename);
1282 
1283 	if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1284 		flags |= SMB_TREE_XVATTR;
1285 
1286 	if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1287 		flags |= SMB_TREE_CASEINSENSITIVE;
1288 
1289 	if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
1290 		flags |= SMB_TREE_NO_CASESENSITIVE;
1291 
1292 	if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS))
1293 		flags |= SMB_TREE_DIRENTFLAGS;
1294 
1295 	if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE))
1296 		flags |= SMB_TREE_ACLONCREATE;
1297 
1298 	if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
1299 		flags |= SMB_TREE_ACEMASKONACCESS;
1300 
1301 	DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name);
1302 
1303 
1304 	tree->t_flags = flags;
1305 }
1306 
1307 /*
1308  * Report share access result to syslog.
1309  */
1310 static void
1311 smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...)
1312 {
1313 	va_list ap;
1314 	char buf[128];
1315 	smb_user_t *user = sr->uid_user;
1316 
1317 	ASSERT(user);
1318 
1319 	if (smb_tcon_mute)
1320 		return;
1321 
1322 	if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) {
1323 		/*
1324 		 * Only report normal users, i.e. ignore W2K misuse
1325 		 * of the IPC connection by filtering out internal
1326 		 * names such as nobody and root.
1327 		 */
1328 		if ((strcmp(user->u_name, "root") == 0) ||
1329 		    (strcmp(user->u_name, "nobody") == 0)) {
1330 			return;
1331 		}
1332 	}
1333 
1334 	va_start(ap, fmt);
1335 	(void) vsnprintf(buf, 128, fmt, ap);
1336 	va_end(ap);
1337 
1338 	cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s",
1339 	    user->u_domain, user->u_name, sharename, buf);
1340 }
1341 
1342 /*
1343  * smb_tree_lookup_odir
1344  *
1345  * Find the specified odir in the tree's list of odirs, and
1346  * attempt to obtain a hold on the odir.
1347  *
1348  * Returns NULL if odir not found or a hold cannot be obtained.
1349  */
1350 smb_odir_t *
1351 smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid)
1352 {
1353 	smb_odir_t	*od;
1354 	smb_llist_t	*od_list;
1355 	smb_tree_t	*tree = sr->tid_tree;
1356 
1357 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1358 
1359 	od_list = &tree->t_odir_list;
1360 
1361 	smb_llist_enter(od_list, RW_READER);
1362 	od = smb_llist_head(od_list);
1363 	while (od) {
1364 		if (od->d_odid == odid)
1365 			break;
1366 		od = smb_llist_next(od_list, od);
1367 	}
1368 	if (od == NULL)
1369 		goto out;
1370 
1371 	/*
1372 	 * Only allow use of a given Search ID with the same UID that
1373 	 * was used to create it.  MS-CIFS 3.3.5.14
1374 	 */
1375 	if (od->d_user != sr->uid_user) {
1376 		od = NULL;
1377 		goto out;
1378 	}
1379 	if (!smb_odir_hold(od))
1380 		od = NULL;
1381 
1382 out:
1383 	smb_llist_exit(od_list);
1384 	return (od);
1385 }
1386 
1387 boolean_t
1388 smb_tree_is_connected(smb_tree_t *tree)
1389 {
1390 	boolean_t	rb;
1391 
1392 	mutex_enter(&tree->t_mutex);
1393 	rb = smb_tree_is_connected_locked(tree);
1394 	mutex_exit(&tree->t_mutex);
1395 	return (rb);
1396 }
1397 
1398 /*
1399  * smb_tree_close_odirs
1400  *
1401  * Close all open odirs in the tree's list which were opened by
1402  * the process identified by pid.
1403  * If pid is zero, close all open odirs in the tree's list.
1404  */
1405 static void
1406 smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid)
1407 {
1408 	smb_llist_t	*od_list;
1409 	smb_odir_t	*od;
1410 
1411 	ASSERT(tree);
1412 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1413 
1414 	od_list = &tree->t_odir_list;
1415 	smb_llist_enter(od_list, RW_READER);
1416 
1417 	for (od = smb_llist_head(od_list);
1418 	    od != NULL;
1419 	    od = smb_llist_next(od_list, od)) {
1420 
1421 		ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1422 		ASSERT(od->d_tree == tree);
1423 
1424 		if (pid != 0 && od->d_opened_by_pid != pid)
1425 			continue;
1426 
1427 		if (smb_odir_hold(od)) {
1428 			smb_odir_close(od);
1429 			smb_odir_release(od);
1430 		}
1431 	}
1432 
1433 	smb_llist_exit(od_list);
1434 }
1435 
1436 static void
1437 smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
1438     int exec_type)
1439 {
1440 	exec->e_sharename = tree->t_sharename;
1441 	exec->e_winname = tree->t_owner->u_name;
1442 	exec->e_userdom = tree->t_owner->u_domain;
1443 	exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
1444 	exec->e_cli_ipaddr = tree->t_session->ipaddr;
1445 	exec->e_cli_netbiosname = tree->t_session->workstation;
1446 	exec->e_uid = crgetuid(tree->t_owner->u_cred);
1447 	exec->e_type = exec_type;
1448 }
1449 
1450 /*
1451  * Private function to support smb_tree_enum.
1452  */
1453 static int
1454 smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum)
1455 {
1456 	uint8_t *pb;
1457 	uint_t nbytes;
1458 	int rc;
1459 
1460 	if (svcenum->se_nskip > 0) {
1461 		svcenum->se_nskip--;
1462 		return (0);
1463 	}
1464 
1465 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
1466 		svcenum->se_nitems = svcenum->se_nlimit;
1467 		return (0);
1468 	}
1469 
1470 	pb = &svcenum->se_buf[svcenum->se_bused];
1471 	rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes);
1472 	if (rc == 0) {
1473 		svcenum->se_bavail -= nbytes;
1474 		svcenum->se_bused += nbytes;
1475 		svcenum->se_nitems++;
1476 	}
1477 
1478 	return (rc);
1479 }
1480 
1481 /*
1482  * Encode connection information into a buffer: connection information
1483  * needed in user space to support RPC requests.
1484  */
1485 static int
1486 smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
1487     uint32_t *nbytes)
1488 {
1489 	smb_netconnectinfo_t	info;
1490 	int			rc;
1491 
1492 	smb_tree_netinfo_init(tree, &info);
1493 	rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes);
1494 	smb_tree_netinfo_fini(&info);
1495 
1496 	return (rc);
1497 }
1498 
1499 static void
1500 smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen)
1501 {
1502 	smb_user_t		*user = tree->t_owner;
1503 
1504 	/*
1505 	 * u_domain_len and u_name_len include the '\0' in their
1506 	 * lengths, hence the sum of the two lengths gives us room
1507 	 * for both the '\\' and '\0' chars.
1508 	 */
1509 	ASSERT(namestr);
1510 	ASSERT(namelen);
1511 	ASSERT(user->u_domain_len > 0);
1512 	ASSERT(user->u_name_len > 0);
1513 	*namelen = user->u_domain_len + user->u_name_len;
1514 	*namestr = kmem_alloc(*namelen, KM_SLEEP);
1515 	(void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain,
1516 	    user->u_name);
1517 }
1518 
1519 /*
1520  * Note: ci_numusers should be the number of users connected to
1521  * the share rather than the number of references on the tree but
1522  * we don't have a mechanism to track users/share in smbsrv yet.
1523  */
1524 static void
1525 smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
1526 {
1527 	ASSERT(tree);
1528 
1529 	info->ci_id = tree->t_tid;
1530 	info->ci_type = tree->t_res_type;
1531 	info->ci_numopens = tree->t_open_files;
1532 	info->ci_numusers = tree->t_refcnt;
1533 	info->ci_time = gethrestime_sec() - tree->t_connect_time;
1534 
1535 	info->ci_sharelen = strlen(tree->t_sharename) + 1;
1536 	info->ci_share = smb_mem_strdup(tree->t_sharename);
1537 
1538 	smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen);
1539 }
1540 
1541 static void
1542 smb_tree_netinfo_fini(smb_netconnectinfo_t *info)
1543 {
1544 	if (info == NULL)
1545 		return;
1546 
1547 	if (info->ci_username)
1548 		kmem_free(info->ci_username, info->ci_namelen);
1549 	if (info->ci_share)
1550 		smb_mem_free(info->ci_share);
1551 
1552 	bzero(info, sizeof (smb_netconnectinfo_t));
1553 }
1554