xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_tree.c (revision 25a9a7aaf35c7e4a2b5a57d3875af906147710d5)
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 2019 Nexenta 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 	/* if 'smb' zfs property: shortnames=disabled */
747 	if (!smb_shortnames)
748 		sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
749 
750 	tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
751 
752 	if (tree == NULL)
753 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
754 
755 	if (tree->t_execflags & SMB_EXEC_MAP) {
756 		smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP);
757 
758 		rc = smb_kshare_exec(tree->t_server, &execinfo);
759 
760 		if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) {
761 			/*
762 			 * Inline parts of: smb_tree_disconnect()
763 			 * Not using smb_tree_disconnect() for cleanup
764 			 * here because: we don't want an exec up-call,
765 			 * and there can't be any opens as we never
766 			 * returned this TID to the client.
767 			 */
768 			mutex_enter(&tree->t_mutex);
769 			tree->t_state = SMB_TREE_STATE_DISCONNECTING;
770 			mutex_exit(&tree->t_mutex);
771 
772 			smb_tree_release(tree);
773 			return (NT_STATUS_ACCESS_DENIED);
774 		}
775 	}
776 
777 	sr->tid_tree = tree;
778 	sr->smb_tid  = tree->t_tid;
779 
780 	return (0);
781 }
782 
783 /*
784  * Shares have both a share and host based access control.  The access
785  * granted will be minimum permissions based on both hostaccess
786  * (permissions allowed by host based access) and aclaccess (from the
787  * share ACL).
788  */
789 uint32_t
790 smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon)
791 {
792 	char			*sharename = tcon->path;
793 	const char		*any = "?????";
794 	smb_user_t		*user = sr->uid_user;
795 	smb_node_t		*dnode = NULL;
796 	smb_node_t		*snode = NULL;
797 	smb_kshare_t		*si = tcon->si;
798 	char			*service = tcon->service;
799 	char			last_component[MAXNAMELEN];
800 	smb_tree_t		*tree;
801 	int			rc;
802 	uint32_t		access;
803 
804 	ASSERT(user);
805 	ASSERT(user->u_cred);
806 
807 	if (sr->sr_server->sv_cfg.skc_print_enable == 0) {
808 		smb_tree_log(sr, sharename, "printing disabled");
809 		return (NT_STATUS_BAD_NETWORK_NAME);
810 	}
811 
812 	if (service != NULL &&
813 	    strcmp(service, any) != 0 &&
814 	    strcasecmp(service, "LPT1:") != 0) {
815 		smb_tree_log(sr, sharename, "invalid service (%s)", service);
816 		return (NT_STATUS_BAD_DEVICE_TYPE);
817 	}
818 
819 	/*
820 	 * Check that the shared directory exists.
821 	 */
822 	rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode,
823 	    last_component);
824 	if (rc == 0) {
825 		rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS,
826 		    sr->sr_server->si_root_smb_node, dnode, last_component,
827 		    &snode);
828 
829 		smb_node_release(dnode);
830 	}
831 
832 	if (rc) {
833 		if (snode)
834 			smb_node_release(snode);
835 
836 		smb_tree_log(sr, sharename, "bad path: %s", si->shr_path);
837 		return (NT_STATUS_BAD_NETWORK_NAME);
838 	}
839 
840 	if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) {
841 		smb_node_release(snode);
842 		return (NT_STATUS_ACCESS_DENIED);
843 	}
844 
845 	tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
846 
847 	tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
848 
849 	smb_node_release(snode);
850 
851 	if (tree == NULL)
852 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
853 
854 	sr->tid_tree = tree;
855 	sr->smb_tid  = tree->t_tid;
856 
857 	return (0);
858 }
859 
860 /*
861  * Connect an IPC share for use with named pipes.
862  */
863 uint32_t
864 smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon)
865 {
866 	char		*name = tcon->path;
867 	const char	*any = "?????";
868 	smb_user_t	*user = sr->uid_user;
869 	smb_tree_t	*tree;
870 	smb_kshare_t	*si = tcon->si;
871 	char		*service = tcon->service;
872 
873 	ASSERT(user);
874 
875 	if (service != NULL &&
876 	    strcmp(service, any) != 0 &&
877 	    strcasecmp(service, "IPC") != 0) {
878 		smb_tree_log(sr, name, "invalid service (%s)", service);
879 		return (NT_STATUS_BAD_DEVICE_TYPE);
880 	}
881 
882 	if ((user->u_flags & SMB_USER_FLAG_ANON) &&
883 	    sr->sr_cfg->skc_restrict_anon) {
884 		smb_tree_log(sr, name, "access denied: restrict anonymous");
885 		return (NT_STATUS_ACCESS_DENIED);
886 	}
887 
888 	tcon->optional_support = SMB_SUPPORT_SEARCH_BITS;
889 
890 	tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
891 	if (tree == NULL)
892 		return (NT_STATUS_INSUFF_SERVER_RESOURCES);
893 
894 	sr->tid_tree = tree;
895 	sr->smb_tid  = tree->t_tid;
896 
897 	return (0);
898 }
899 
900 /*
901  * Allocate a tree.
902  */
903 smb_tree_t *
904 smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
905     smb_node_t *snode, uint32_t access, uint32_t execflags)
906 {
907 	smb_session_t	*session = sr->session;
908 	smb_tree_t	*tree;
909 	uint32_t	stype = si->shr_type;
910 	uint16_t	tid;
911 
912 	if (smb_idpool_alloc(&session->s_tid_pool, &tid))
913 		return (NULL);
914 
915 	tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP);
916 	bzero(tree, sizeof (smb_tree_t));
917 
918 	tree->t_session = session;
919 	tree->t_server = session->s_server;
920 
921 	/* grab a ref for tree->t_owner */
922 	smb_user_hold_internal(sr->uid_user);
923 	tree->t_owner = sr->uid_user;
924 
925 	if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
926 		if (smb_tree_getattr(si, snode, tree) != 0) {
927 			smb_idpool_free(&session->s_tid_pool, tid);
928 			kmem_cache_free(smb_cache_tree, tree);
929 			return (NULL);
930 		}
931 	}
932 
933 	if (smb_idpool_constructor(&tree->t_fid_pool)) {
934 		smb_idpool_free(&session->s_tid_pool, tid);
935 		kmem_cache_free(smb_cache_tree, tree);
936 		return (NULL);
937 	}
938 
939 	if (smb_idpool_constructor(&tree->t_odid_pool)) {
940 		smb_idpool_destructor(&tree->t_fid_pool);
941 		smb_idpool_free(&session->s_tid_pool, tid);
942 		kmem_cache_free(smb_cache_tree, tree);
943 		return (NULL);
944 	}
945 
946 	smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
947 	    offsetof(smb_ofile_t, f_tree_lnd));
948 
949 	smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
950 	    offsetof(smb_odir_t, d_lnd));
951 
952 	(void) strlcpy(tree->t_sharename, si->shr_name,
953 	    sizeof (tree->t_sharename));
954 	(void) strlcpy(tree->t_resource, si->shr_path,
955 	    sizeof (tree->t_resource));
956 
957 	mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);
958 
959 	tree->t_refcnt = 1;
960 	tree->t_tid = tid;
961 	tree->t_res_type = stype;
962 	tree->t_state = SMB_TREE_STATE_CONNECTED;
963 	tree->t_magic = SMB_TREE_MAGIC;
964 	tree->t_access = access;
965 	tree->t_connect_time = gethrestime_sec();
966 	tree->t_execflags = execflags;
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_release(tree->t_owner);
1035 
1036 	kmem_cache_free(smb_cache_tree, tree);
1037 }
1038 
1039 /*
1040  * Determine whether or not a tree is connected.
1041  * This function must be called with the tree mutex held.
1042  */
1043 static boolean_t
1044 smb_tree_is_connected_locked(smb_tree_t *tree)
1045 {
1046 	switch (tree->t_state) {
1047 	case SMB_TREE_STATE_CONNECTED:
1048 		return (B_TRUE);
1049 
1050 	case SMB_TREE_STATE_DISCONNECTING:
1051 	case SMB_TREE_STATE_DISCONNECTED:
1052 		/*
1053 		 * The tree exists but is being disconnected or destroyed.
1054 		 */
1055 		return (B_FALSE);
1056 
1057 	default:
1058 		ASSERT(0);
1059 		return (B_FALSE);
1060 	}
1061 }
1062 
1063 /*
1064  * Return a pointer to the share name within a share resource path.
1065  *
1066  * The share path may be a Uniform Naming Convention (UNC) string
1067  * (\\server\share) or simply the share name.  We validate the UNC
1068  * format but we don't look at the server name.
1069  */
1070 static char *
1071 smb_tree_get_sharename(char *unc_path)
1072 {
1073 	char *sharename = unc_path;
1074 
1075 	if (sharename[0] == '\\') {
1076 		/*
1077 		 * Looks like a UNC path, validate the format.
1078 		 */
1079 		if (sharename[1] != '\\')
1080 			return (NULL);
1081 
1082 		if ((sharename = strchr(sharename+2, '\\')) == NULL)
1083 			return (NULL);
1084 
1085 		++sharename;
1086 	} else if (strchr(sharename, '\\') != NULL) {
1087 		/*
1088 		 * This should be a share name (no embedded \'s).
1089 		 */
1090 		return (NULL);
1091 	}
1092 
1093 	return (sharename);
1094 }
1095 
1096 /*
1097  * Obtain the tree attributes: volume name, typename and flags.
1098  */
1099 static int
1100 smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree)
1101 {
1102 	vfs_t *vfsp = SMB_NODE_VFS(node);
1103 	smb_cfg_val_t srv_encrypt;
1104 
1105 	ASSERT(vfsp);
1106 
1107 	if (getvfs(&vfsp->vfs_fsid) != vfsp)
1108 		return (ESTALE);
1109 
1110 	smb_tree_get_creation(node, tree);
1111 	smb_tree_get_volname(vfsp, tree);
1112 	smb_tree_get_flags(si, vfsp, tree);
1113 
1114 	srv_encrypt = tree->t_session->s_server->sv_cfg.skc_encrypt;
1115 	if (tree->t_session->dialect >= SMB_VERS_3_0) {
1116 		if (si->shr_encrypt == SMB_CONFIG_REQUIRED ||
1117 		    srv_encrypt == SMB_CONFIG_REQUIRED)
1118 			tree->t_encrypt = SMB_CONFIG_REQUIRED;
1119 		else if (si->shr_encrypt == SMB_CONFIG_ENABLED ||
1120 		    srv_encrypt == SMB_CONFIG_ENABLED)
1121 			tree->t_encrypt = SMB_CONFIG_ENABLED;
1122 		else
1123 			tree->t_encrypt = SMB_CONFIG_DISABLED;
1124 	} else
1125 		tree->t_encrypt = SMB_CONFIG_DISABLED;
1126 
1127 	VFS_RELE(vfsp);
1128 	return (0);
1129 }
1130 
1131 /*
1132  * File volume creation time
1133  */
1134 static void
1135 smb_tree_get_creation(smb_node_t *node, smb_tree_t *tree)
1136 {
1137 	smb_attr_t	attr;
1138 	cred_t		*kcr = zone_kcred();
1139 
1140 	bzero(&attr, sizeof (attr));
1141 	attr.sa_mask = SMB_AT_CRTIME;
1142 	(void) smb_node_getattr(NULL, node, kcr, NULL, &attr);
1143 	/* On failure we'll have time zero, which is OK */
1144 
1145 	tree->t_create_time = attr.sa_crtime;
1146 }
1147 
1148 /*
1149  * Extract the volume name.
1150  */
1151 static void
1152 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
1153 {
1154 #ifdef	_FAKE_KERNEL
1155 	_NOTE(ARGUNUSED(vfsp))
1156 	(void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN);
1157 #else	/* _FAKE_KERNEL */
1158 	refstr_t *vfs_mntpoint;
1159 	const char *s;
1160 	char *name;
1161 
1162 	vfs_mntpoint = vfs_getmntpoint(vfsp);
1163 
1164 	s = refstr_value(vfs_mntpoint);
1165 	s += strspn(s, "/");
1166 	(void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN);
1167 
1168 	refstr_rele(vfs_mntpoint);
1169 
1170 	name = tree->t_volume;
1171 	(void) strsep((char **)&name, "/");
1172 #endif	/* _FAKE_KERNEL */
1173 }
1174 
1175 /*
1176  * Always set "unicode on disk" because we always use utf8 names locally.
1177  * Always set ACL support because the VFS will fake ACLs for file systems
1178  * that don't support them.
1179  *
1180  * Some flags are dependent on the typename, which is also set up here.
1181  * File system types are hardcoded in uts/common/os/vfs_conf.c.
1182  */
1183 static void
1184 smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
1185 {
1186 	smb_session_t *ssn = tree->t_session;
1187 	struct vfssw	*vswp;
1188 
1189 	typedef struct smb_mtype {
1190 		char		*mt_name;
1191 		size_t		mt_namelen;
1192 		uint32_t	mt_flags;
1193 	} smb_mtype_t;
1194 
1195 	static smb_mtype_t smb_mtype[] = {
1196 #ifdef	_FAKE_KERNEL
1197 		/* See libfksmbsrv:fake_vfs.c */
1198 		{ "fake",    3,	SMB_TREE_SPARSE},
1199 #endif	/* _FAKE_KERNEL */
1200 		{ "zfs",    3,	SMB_TREE_QUOTA | SMB_TREE_SPARSE},
1201 		{ "ufs",    3,	0 },
1202 		{ "nfs",    3,	SMB_TREE_NFS_MOUNTED },
1203 		{ "tmpfs",  5,	SMB_TREE_NO_EXPORT }
1204 	};
1205 	smb_mtype_t	*mtype;
1206 	char		*name;
1207 	uint32_t	flags =
1208 	    SMB_TREE_SUPPORTS_ACLS |
1209 	    SMB_TREE_UNICODE_ON_DISK;
1210 	int		i;
1211 
1212 	if (si->shr_flags & SMB_SHRF_DFSROOT)
1213 		flags |= SMB_TREE_DFSROOT;
1214 
1215 	if (si->shr_flags & SMB_SHRF_CATIA)
1216 		flags |= SMB_TREE_CATIA;
1217 
1218 	if (si->shr_flags & SMB_SHRF_ABE)
1219 		flags |= SMB_TREE_ABE;
1220 
1221 	if (si->shr_flags & SMB_SHRF_CA)
1222 		flags |= SMB_TREE_CA;
1223 
1224 	if (si->shr_flags & SMB_SHRF_FSO)
1225 		flags |= SMB_TREE_FORCE_L2_OPLOCK;
1226 
1227 	if (ssn->s_cfg.skc_oplock_enable) {
1228 		/* if 'smb' zfs property: oplocks=enabled */
1229 		flags |= SMB_TREE_OPLOCKS;
1230 	}
1231 
1232 	/* Global config option for now.  Later make per-share. */
1233 	if (ssn->s_cfg.skc_traverse_mounts)
1234 		flags |= SMB_TREE_TRAVERSE_MOUNTS;
1235 
1236 	/* if 'smb' zfs property: shortnames=enabled */
1237 	if (smb_shortnames)
1238 		flags |= SMB_TREE_SHORTNAMES;
1239 
1240 	if (vfsp->vfs_flag & VFS_RDONLY)
1241 		flags |= SMB_TREE_READONLY;
1242 
1243 	if (vfsp->vfs_flag & VFS_XATTR)
1244 		flags |= SMB_TREE_STREAMS;
1245 
1246 	vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
1247 	if (vswp != NULL) {
1248 		name = vswp->vsw_name;
1249 		vfs_unrefvfssw(vswp);
1250 	} else {
1251 		name = "?";
1252 	}
1253 
1254 	for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
1255 		mtype = &smb_mtype[i];
1256 		if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0)
1257 			flags |= mtype->mt_flags;
1258 	}
1259 
1260 	/*
1261 	 * SMB_TREE_QUOTA will be on here if the FS is ZFS.  We want to
1262 	 * turn it OFF when the share property says false.
1263 	 */
1264 	if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0)
1265 		flags &= ~SMB_TREE_QUOTA;
1266 
1267 	(void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN);
1268 	(void) smb_strupr((char *)tree->t_typename);
1269 
1270 	if (vfs_has_feature(vfsp, VFSFT_XVATTR))
1271 		flags |= SMB_TREE_XVATTR;
1272 
1273 	if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE))
1274 		flags |= SMB_TREE_CASEINSENSITIVE;
1275 
1276 	if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE))
1277 		flags |= SMB_TREE_NO_CASESENSITIVE;
1278 
1279 	if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS))
1280 		flags |= SMB_TREE_DIRENTFLAGS;
1281 
1282 	if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE))
1283 		flags |= SMB_TREE_ACLONCREATE;
1284 
1285 	if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS))
1286 		flags |= SMB_TREE_ACEMASKONACCESS;
1287 
1288 	DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name);
1289 
1290 
1291 	tree->t_flags = flags;
1292 }
1293 
1294 /*
1295  * Report share access result to syslog.
1296  */
1297 static void
1298 smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...)
1299 {
1300 	va_list ap;
1301 	char buf[128];
1302 	smb_user_t *user = sr->uid_user;
1303 
1304 	ASSERT(user);
1305 
1306 	if (smb_tcon_mute)
1307 		return;
1308 
1309 	if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) {
1310 		/*
1311 		 * Only report normal users, i.e. ignore W2K misuse
1312 		 * of the IPC connection by filtering out internal
1313 		 * names such as nobody and root.
1314 		 */
1315 		if ((strcmp(user->u_name, "root") == 0) ||
1316 		    (strcmp(user->u_name, "nobody") == 0)) {
1317 			return;
1318 		}
1319 	}
1320 
1321 	va_start(ap, fmt);
1322 	(void) vsnprintf(buf, 128, fmt, ap);
1323 	va_end(ap);
1324 
1325 	cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s",
1326 	    user->u_domain, user->u_name, sharename, buf);
1327 }
1328 
1329 /*
1330  * smb_tree_lookup_odir
1331  *
1332  * Find the specified odir in the tree's list of odirs, and
1333  * attempt to obtain a hold on the odir.
1334  *
1335  * Returns NULL if odir not found or a hold cannot be obtained.
1336  */
1337 smb_odir_t *
1338 smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid)
1339 {
1340 	smb_odir_t	*od;
1341 	smb_llist_t	*od_list;
1342 	smb_tree_t	*tree = sr->tid_tree;
1343 
1344 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1345 
1346 	od_list = &tree->t_odir_list;
1347 
1348 	smb_llist_enter(od_list, RW_READER);
1349 	od = smb_llist_head(od_list);
1350 	while (od) {
1351 		if (od->d_odid == odid)
1352 			break;
1353 		od = smb_llist_next(od_list, od);
1354 	}
1355 	if (od == NULL)
1356 		goto out;
1357 
1358 	/*
1359 	 * Only allow use of a given Search ID with the same UID that
1360 	 * was used to create it.  MS-CIFS 3.3.5.14
1361 	 */
1362 	if (od->d_user != sr->uid_user) {
1363 		od = NULL;
1364 		goto out;
1365 	}
1366 	if (!smb_odir_hold(od))
1367 		od = NULL;
1368 
1369 out:
1370 	smb_llist_exit(od_list);
1371 	return (od);
1372 }
1373 
1374 boolean_t
1375 smb_tree_is_connected(smb_tree_t *tree)
1376 {
1377 	boolean_t	rb;
1378 
1379 	mutex_enter(&tree->t_mutex);
1380 	rb = smb_tree_is_connected_locked(tree);
1381 	mutex_exit(&tree->t_mutex);
1382 	return (rb);
1383 }
1384 
1385 /*
1386  * smb_tree_close_odirs
1387  *
1388  * Close all open odirs in the tree's list which were opened by
1389  * the process identified by pid.
1390  * If pid is zero, close all open odirs in the tree's list.
1391  */
1392 static void
1393 smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid)
1394 {
1395 	smb_llist_t	*od_list;
1396 	smb_odir_t	*od;
1397 
1398 	ASSERT(tree);
1399 	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
1400 
1401 	od_list = &tree->t_odir_list;
1402 	smb_llist_enter(od_list, RW_READER);
1403 
1404 	for (od = smb_llist_head(od_list);
1405 	    od != NULL;
1406 	    od = smb_llist_next(od_list, od)) {
1407 
1408 		ASSERT(od->d_magic == SMB_ODIR_MAGIC);
1409 		ASSERT(od->d_tree == tree);
1410 
1411 		if (pid != 0 && od->d_opened_by_pid != pid)
1412 			continue;
1413 
1414 		if (smb_odir_hold(od)) {
1415 			smb_odir_close(od);
1416 			smb_odir_release(od);
1417 		}
1418 	}
1419 
1420 	smb_llist_exit(od_list);
1421 }
1422 
1423 static void
1424 smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
1425     int exec_type)
1426 {
1427 	exec->e_sharename = tree->t_sharename;
1428 	exec->e_winname = tree->t_owner->u_name;
1429 	exec->e_userdom = tree->t_owner->u_domain;
1430 	exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
1431 	exec->e_cli_ipaddr = tree->t_session->ipaddr;
1432 	exec->e_cli_netbiosname = tree->t_session->workstation;
1433 	exec->e_uid = crgetuid(tree->t_owner->u_cred);
1434 	exec->e_type = exec_type;
1435 }
1436 
1437 /*
1438  * Private function to support smb_tree_enum.
1439  */
1440 static int
1441 smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum)
1442 {
1443 	uint8_t *pb;
1444 	uint_t nbytes;
1445 	int rc;
1446 
1447 	if (svcenum->se_nskip > 0) {
1448 		svcenum->se_nskip--;
1449 		return (0);
1450 	}
1451 
1452 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
1453 		svcenum->se_nitems = svcenum->se_nlimit;
1454 		return (0);
1455 	}
1456 
1457 	pb = &svcenum->se_buf[svcenum->se_bused];
1458 	rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes);
1459 	if (rc == 0) {
1460 		svcenum->se_bavail -= nbytes;
1461 		svcenum->se_bused += nbytes;
1462 		svcenum->se_nitems++;
1463 	}
1464 
1465 	return (rc);
1466 }
1467 
1468 /*
1469  * Encode connection information into a buffer: connection information
1470  * needed in user space to support RPC requests.
1471  */
1472 static int
1473 smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
1474     uint32_t *nbytes)
1475 {
1476 	smb_netconnectinfo_t	info;
1477 	int			rc;
1478 
1479 	smb_tree_netinfo_init(tree, &info);
1480 	rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes);
1481 	smb_tree_netinfo_fini(&info);
1482 
1483 	return (rc);
1484 }
1485 
1486 static void
1487 smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen)
1488 {
1489 	smb_user_t		*user = tree->t_owner;
1490 
1491 	/*
1492 	 * u_domain_len and u_name_len include the '\0' in their
1493 	 * lengths, hence the sum of the two lengths gives us room
1494 	 * for both the '\\' and '\0' chars.
1495 	 */
1496 	ASSERT(namestr);
1497 	ASSERT(namelen);
1498 	ASSERT(user->u_domain_len > 0);
1499 	ASSERT(user->u_name_len > 0);
1500 	*namelen = user->u_domain_len + user->u_name_len;
1501 	*namestr = kmem_alloc(*namelen, KM_SLEEP);
1502 	(void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain,
1503 	    user->u_name);
1504 }
1505 
1506 /*
1507  * Note: ci_numusers should be the number of users connected to
1508  * the share rather than the number of references on the tree but
1509  * we don't have a mechanism to track users/share in smbsrv yet.
1510  */
1511 static void
1512 smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
1513 {
1514 	ASSERT(tree);
1515 
1516 	info->ci_id = tree->t_tid;
1517 	info->ci_type = tree->t_res_type;
1518 	info->ci_numopens = tree->t_open_files;
1519 	info->ci_numusers = tree->t_refcnt;
1520 	info->ci_time = gethrestime_sec() - tree->t_connect_time;
1521 
1522 	info->ci_sharelen = strlen(tree->t_sharename) + 1;
1523 	info->ci_share = smb_mem_strdup(tree->t_sharename);
1524 
1525 	smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen);
1526 }
1527 
1528 static void
1529 smb_tree_netinfo_fini(smb_netconnectinfo_t *info)
1530 {
1531 	if (info == NULL)
1532 		return;
1533 
1534 	if (info->ci_username)
1535 		kmem_free(info->ci_username, info->ci_namelen);
1536 	if (info->ci_share)
1537 		smb_mem_free(info->ci_share);
1538 
1539 	bzero(info, sizeof (smb_netconnectinfo_t));
1540 }
1541