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