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