xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_user.c (revision 040524e83cbd2eb410edc795626783c095f877e3)
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  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
24  * Copyright (c) 2016 by Delphix. All rights reserved.
25  */
26 
27 /*
28  * General Structures Layout
29  * -------------------------
30  *
31  * This is a simplified diagram showing the relationship between most of the
32  * main structures.
33  *
34  * +-------------------+
35  * |     SMB_INFO      |
36  * +-------------------+
37  *          |
38  *          |
39  *          v
40  * +-------------------+       +-------------------+      +-------------------+
41  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
42  * +-------------------+       +-------------------+      +-------------------+
43  *   |          |
44  *   |          |
45  *   |          v
46  *   |  +-------------------+     +-------------------+   +-------------------+
47  *   |  |       USER        |<--->|       USER        |...|       USER        |
48  *   |  +-------------------+     +-------------------+   +-------------------+
49  *   |
50  *   |
51  *   v
52  * +-------------------+       +-------------------+      +-------------------+
53  * |       TREE        |<----->|       TREE        |......|       TREE        |
54  * +-------------------+       +-------------------+      +-------------------+
55  *      |         |
56  *      |         |
57  *      |         v
58  *      |     +-------+       +-------+      +-------+
59  *      |     | OFILE |<----->| OFILE |......| OFILE |
60  *      |     +-------+       +-------+      +-------+
61  *      |
62  *      |
63  *      v
64  *  +-------+       +------+      +------+
65  *  | ODIR  |<----->| ODIR |......| ODIR |
66  *  +-------+       +------+      +------+
67  *
68  *
69  * User State Machine
70  * ------------------
71  *
72  *
73  *		    | T0:  Creation/Allocation
74  *		    |	   (1st session setup)
75  *		    v
76  *    +-----------------------------+
77  *    |  SMB_USER_STATE_LOGGING_ON  |<----------+
78  *    +-----------------------------+	 addl. session setup
79  *		    |		|	(more proc. required)
80  *		    | T2	|		^
81  *		    |		|		| T1: (cont.)
82  *		    |		+------->-------?
83  *		    v				| T3: (fail)
84  *    +-----------------------------+		v
85  *    |  SMB_USER_STATE_LOGGED_ON   |	    (logged off)
86  *    +-----------------------------+
87  *		    |
88  *		    | T4
89  *		    |
90  *		    v
91  *    +-----------------------------+
92  *    |  SMB_USER_STATE_LOGGING_OFF |
93  *    +-----------------------------+
94  *		    |
95  *		    | T5
96  *		    |
97  *		    v
98  *    +-----------------------------+    T6
99  *    |  SMB_USER_STATE_LOGGED_OFF  |----------> Deletion/Free
100  *    +-----------------------------+
101  *
102  * SMB_USER_STATE_LOGGING_ON
103  *
104  *    While in this state:
105  *      - The user is in the list of users for their session.
106  *      - References will be given out ONLY for session setup.
107  *      - This user can not access anything yet.
108  *
109  * SMB_USER_STATE_LOGGED_ON
110  *
111  *    While in this state:
112  *      - The user is in the list of users for their session.
113  *      - References will be given out if the user is looked up.
114  *      - The user can access files and pipes.
115  *
116  * SMB_USER_STATE_LOGGING_OFF
117  *
118  *    While in this state:
119  *      - The user is in the list of users for their session.
120  *      - References will not be given out if the user is looked up.
121  *      - The trees the user connected are being disconnected.
122  *      - The resources associated with the user remain.
123  *
124  * SMB_USER_STATE_LOGGED_OFF
125  *
126  *    While in this state:
127  *      - The user is queued in the list of users of their session.
128  *      - References will not be given out if the user is looked up.
129  *      - The user has no more trees connected.
130  *      - The resources associated with the user remain.
131  *
132  * Transition T0
133  *
134  *    First request in an SMB Session Setup sequence creates a
135  *    new user object and adds it to the list of users for
136  *    this session.  User UID is assigned and returned.
137  *
138  * Transition T1
139  *
140  *    Subsequent SMB Session Setup requests (on the same UID
141  *    assigned in T0) update the state of this user object,
142  *    communicating with smbd for the crypto work.
143  *
144  * Transition T2
145  *
146  *    If the SMB Session Setup sequence is successful, T2
147  *    makes the new user object available for requests.
148  *
149  * Transition T3
150  *
151  *    If an Session Setup request gets an error other than
152  *    the expected "more processing required", then T3
153  *    leads to state "LOGGED_OFF" and then tear-down of the
154  *    partially constructed user.
155  *
156  * Transition T4
157  *
158  *    Normal SMB User Logoff request, or session tear-down.
159  *
160  * Transition T5
161  *
162  *    This transition occurs in smb_user_release(). The resources associated
163  *    with the user are deleted as well as the user. For the transition to
164  *    occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the
165  *    reference count be zero.
166  *
167  * Comments
168  * --------
169  *
170  *    The state machine of the user structures is controlled by 3 elements:
171  *      - The list of users of the session they belong to.
172  *      - The mutex embedded in the structure itself.
173  *      - The reference count.
174  *
175  *    There's a mutex embedded in the user structure used to protect its fields
176  *    and there's a lock embedded in the list of users of a session. To
177  *    increment or to decrement the reference count the mutex must be entered.
178  *    To insert the user into the list of users of the session and to remove
179  *    the user from it, the lock must be entered in RW_WRITER mode.
180  *
181  *    Rules of access to a user structure:
182  *
183  *    1) In order to avoid deadlocks, when both (mutex and lock of the session
184  *       list) have to be entered, the lock must be entered first. Additionally,
185  *       one may NOT flush the deleteq of either the tree list or the ofile list
186  *       while the user mutex is held.
187  *
188  *    2) All actions applied to a user require a reference count.
189  *
190  *    3) There are 2 ways of getting a reference count. One is when the user
191  *       logs in. The other when the user is looked up.
192  *
193  *    It should be noted that the reference count of a user registers the
194  *    number of references to the user in other structures (such as an smb
195  *    request). The reference count is not incremented in these 2 instances:
196  *
197  *    1) The user is logged in. An user is anchored by their state. If there's
198  *       no activity involving a user currently logged in, the reference
199  *       count of that user is zero.
200  *
201  *    2) The user is queued in the list of users of the session. The fact of
202  *       being queued in that list is NOT registered by incrementing the
203  *       reference count.
204  */
205 #include <sys/types.h>
206 #include <sys/sid.h>
207 #include <sys/priv_names.h>
208 #include <sys/priv.h>
209 #include <sys/policy.h>
210 #include <smbsrv/smb_kproto.h>
211 #include <smbsrv/smb_door.h>
212 
213 #define	ADMINISTRATORS_SID	"S-1-5-32-544"
214 
215 /* Don't leak object addresses */
216 #define	SMB_USER_SSNID(u) \
217 	((uintptr_t)&smb_cache_user ^ (uintptr_t)(u))
218 
219 static void smb_user_delete(void *);
220 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
221 static void smb_user_auth_logoff(smb_user_t *);
222 static void smb_user_logoff_tq(void *);
223 
224 /*
225  * Create a new user.
226  *
227  * For SMB2 and later, session IDs (u_ssnid) need to be unique among all
228  * current and "recent" sessions.  The session ID is derived from the
229  * address of the smb_user object (obscured by XOR with a constant).
230  * This adds a 3-bit generation number in the low bits, incremented
231  * when we allocate an smb_user_t from its kmem cache, so it can't
232  * be confused with a (recent) previous incarnation of this object.
233  */
234 smb_user_t *
235 smb_user_new(smb_session_t *session)
236 {
237 	smb_user_t	*user;
238 	uint_t		gen;	// generation (low 3 bits of ssnid)
239 	uint32_t	ucount;
240 
241 	ASSERT(session);
242 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
243 
244 	user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
245 	gen = (user->u_ssnid + 1) & 7;
246 	bzero(user, sizeof (smb_user_t));
247 
248 	user->u_refcnt = 1;
249 	user->u_session = session;
250 	user->u_server = session->s_server;
251 	user->u_logon_time = gethrestime_sec();
252 
253 	if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
254 		goto errout;
255 	user->u_ssnid = SMB_USER_SSNID(user) + gen;
256 
257 	mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
258 	user->u_state = SMB_USER_STATE_LOGGING_ON;
259 	user->u_magic = SMB_USER_MAGIC;
260 
261 	smb_llist_enter(&session->s_user_list, RW_WRITER);
262 	ucount = smb_llist_get_count(&session->s_user_list);
263 	smb_llist_insert_tail(&session->s_user_list, user);
264 	smb_llist_exit(&session->s_user_list);
265 	smb_server_inc_users(session->s_server);
266 
267 	/*
268 	 * If we added the first user to the session, cancel the
269 	 * timeout that was started in smb_session_receiver().
270 	 */
271 	if (ucount == 0) {
272 		timeout_id_t tmo = NULL;
273 
274 		smb_rwx_rwenter(&session->s_lock, RW_WRITER);
275 		tmo = session->s_auth_tmo;
276 		session->s_auth_tmo = NULL;
277 		smb_rwx_rwexit(&session->s_lock);
278 
279 		if (tmo != NULL)
280 			(void) untimeout(tmo);
281 	}
282 
283 	return (user);
284 
285 errout:
286 	if (user->u_uid != 0)
287 		smb_idpool_free(&session->s_uid_pool, user->u_uid);
288 	kmem_cache_free(smb_cache_user, user);
289 	return (NULL);
290 }
291 
292 /*
293  * Fill in the details of a user, meaning a transition
294  * from state LOGGING_ON to state LOGGED_ON.
295  */
296 int
297 smb_user_logon(
298     smb_user_t		*user,
299     cred_t		*cr,
300     char		*domain_name,
301     char		*account_name,
302     uint32_t		flags,
303     uint32_t		privileges,
304     uint32_t		audit_sid)
305 {
306 	ksocket_t authsock = NULL;
307 	timeout_id_t tmo = NULL;
308 
309 	ASSERT(user->u_magic == SMB_USER_MAGIC);
310 	ASSERT(cr);
311 	ASSERT(account_name);
312 	ASSERT(domain_name);
313 
314 	mutex_enter(&user->u_mutex);
315 
316 	if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
317 		mutex_exit(&user->u_mutex);
318 		return (-1);
319 	}
320 
321 	/*
322 	 * In the transition from LOGGING_ON to LOGGED_ON,
323 	 * we always have an auth. socket to close.
324 	 */
325 	authsock = user->u_authsock;
326 	user->u_authsock = NULL;
327 	tmo = user->u_auth_tmo;
328 	user->u_auth_tmo = NULL;
329 
330 	user->u_state = SMB_USER_STATE_LOGGED_ON;
331 	user->u_flags = flags;
332 	user->u_name_len = strlen(account_name) + 1;
333 	user->u_domain_len = strlen(domain_name) + 1;
334 	user->u_name = smb_mem_strdup(account_name);
335 	user->u_domain = smb_mem_strdup(domain_name);
336 	user->u_audit_sid = audit_sid;
337 
338 	smb_user_setcred(user, cr, privileges);
339 
340 	mutex_exit(&user->u_mutex);
341 
342 	/* Timeout callback takes u_mutex. See untimeout(9f) */
343 	if (tmo != NULL)
344 		(void) untimeout(tmo);
345 
346 	/* This close can block, so not under the mutex. */
347 	if (authsock != NULL)
348 		smb_authsock_close(user, authsock);
349 
350 	return (0);
351 }
352 
353 /*
354  * smb_user_logoff
355  *
356  * Change the user state to "logging off" and disconnect trees.
357  * The user list must not be entered or modified here.
358  *
359  * We remain in state "logging off" until the last ref. is gone,
360  * then smb_user_release takes us to state "logged off".
361  */
362 void
363 smb_user_logoff(
364     smb_user_t		*user)
365 {
366 	ksocket_t authsock = NULL;
367 	timeout_id_t tmo = NULL;
368 
369 	ASSERT(user->u_magic == SMB_USER_MAGIC);
370 
371 	mutex_enter(&user->u_mutex);
372 	ASSERT(user->u_refcnt);
373 	switch (user->u_state) {
374 	case SMB_USER_STATE_LOGGING_ON:
375 		authsock = user->u_authsock;
376 		user->u_authsock = NULL;
377 		tmo = user->u_auth_tmo;
378 		user->u_auth_tmo = NULL;
379 		user->u_state = SMB_USER_STATE_LOGGING_OFF;
380 		mutex_exit(&user->u_mutex);
381 
382 		/* Timeout callback takes u_mutex. See untimeout(9f) */
383 		if (tmo != NULL)
384 			(void) untimeout(tmo);
385 		/* This close can block, so not under the mutex. */
386 		if (authsock != NULL)
387 			smb_authsock_close(user, authsock);
388 		break;
389 
390 	case SMB_USER_STATE_LOGGED_ON:
391 		/*
392 		 * The user is moved into a state indicating that the log off
393 		 * process has started.
394 		 */
395 		user->u_state = SMB_USER_STATE_LOGGING_OFF;
396 		mutex_exit(&user->u_mutex);
397 		smb_session_disconnect_owned_trees(user->u_session, user);
398 		smb_user_auth_logoff(user);
399 		break;
400 
401 	case SMB_USER_STATE_LOGGED_OFF:
402 	case SMB_USER_STATE_LOGGING_OFF:
403 		mutex_exit(&user->u_mutex);
404 		break;
405 
406 	default:
407 		ASSERT(0);
408 		mutex_exit(&user->u_mutex);
409 		break;
410 	}
411 }
412 
413 /*
414  * Take a reference on a user.  Do not return a reference unless the user is in
415  * the logged-in state.
416  */
417 boolean_t
418 smb_user_hold(smb_user_t *user)
419 {
420 	SMB_USER_VALID(user);
421 
422 	mutex_enter(&user->u_mutex);
423 
424 	if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
425 		user->u_refcnt++;
426 		mutex_exit(&user->u_mutex);
427 		return (B_TRUE);
428 	}
429 
430 	mutex_exit(&user->u_mutex);
431 	return (B_FALSE);
432 }
433 
434 /*
435  * Unconditionally take a reference on a user.
436  */
437 void
438 smb_user_hold_internal(smb_user_t *user)
439 {
440 	SMB_USER_VALID(user);
441 
442 	mutex_enter(&user->u_mutex);
443 	user->u_refcnt++;
444 	mutex_exit(&user->u_mutex);
445 }
446 
447 /*
448  * Release a reference on a user.  If the reference count falls to
449  * zero and the user has logged off, post the object for deletion.
450  * Object deletion is deferred to avoid modifying a list while an
451  * iteration may be in progress.
452  */
453 void
454 smb_user_release(
455     smb_user_t		*user)
456 {
457 	smb_session_t *ssn = user->u_session;
458 
459 	SMB_USER_VALID(user);
460 
461 	/* flush the tree list delete queue */
462 	smb_llist_flush(&ssn->s_tree_list);
463 
464 	mutex_enter(&user->u_mutex);
465 	ASSERT(user->u_refcnt);
466 	user->u_refcnt--;
467 
468 	switch (user->u_state) {
469 	case SMB_USER_STATE_LOGGING_OFF:
470 		if (user->u_refcnt == 0) {
471 			smb_session_t *ssn = user->u_session;
472 			user->u_state = SMB_USER_STATE_LOGGED_OFF;
473 			smb_llist_post(&ssn->s_user_list, user,
474 			    smb_user_delete);
475 		}
476 		break;
477 
478 	case SMB_USER_STATE_LOGGING_ON:
479 	case SMB_USER_STATE_LOGGED_ON:
480 		break;
481 
482 	case SMB_USER_STATE_LOGGED_OFF:
483 	default:
484 		ASSERT(0);
485 		break;
486 	}
487 	mutex_exit(&user->u_mutex);
488 }
489 
490 /*
491  * Timeout handler for user logons that stay too long in
492  * state SMB_USER_STATE_LOGGING_ON.  This is setup by a
493  * timeout call in smb_authsock_open, and called in a
494  * callout thread, so schedule a taskq job to do the
495  * real work of logging off this user.
496  */
497 void
498 smb_user_auth_tmo(void *arg)
499 {
500 	smb_user_t *user = arg;
501 	smb_request_t *sr;
502 	taskqid_t tqid;
503 
504 	SMB_USER_VALID(user);
505 
506 	/*
507 	 * If we can't allocate a request, it means the
508 	 * session is being torn down, so nothing to do.
509 	 */
510 	sr = smb_request_alloc(user->u_session, 0);
511 	if (sr == NULL)
512 		return;
513 
514 	/*
515 	 * Check user state, and take a hold if it's
516 	 * still logging on.  If not, we're done.
517 	 */
518 	mutex_enter(&user->u_mutex);
519 	if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
520 		mutex_exit(&user->u_mutex);
521 		smb_request_free(sr);
522 		return;
523 	}
524 	/* smb_user_hold_internal */
525 	user->u_refcnt++;
526 	mutex_exit(&user->u_mutex);
527 
528 	/*
529 	 * The user hold is given to the SR, and released in
530 	 * smb_user_logoff_tq / smb_request_free
531 	 */
532 	sr->uid_user = user;
533 	sr->user_cr = user->u_cred;
534 	sr->sr_state = SMB_REQ_STATE_SUBMITTED;
535 	tqid = taskq_dispatch(
536 	    user->u_server->sv_worker_pool,
537 	    smb_user_logoff_tq, sr, TQ_SLEEP);
538 	VERIFY(tqid != TASKQID_INVALID);
539 }
540 
541 /*
542  * Helper for smb_user_auth_tmo()
543  */
544 static void
545 smb_user_logoff_tq(void *arg)
546 {
547 	smb_request_t	*sr = arg;
548 
549 	SMB_REQ_VALID(sr);
550 
551 	mutex_enter(&sr->sr_mutex);
552 	sr->sr_worker = curthread;
553 	sr->sr_state = SMB_REQ_STATE_ACTIVE;
554 	mutex_exit(&sr->sr_mutex);
555 
556 	smb_user_logoff(sr->uid_user);
557 
558 	sr->sr_state = SMB_REQ_STATE_COMPLETED;
559 	smb_request_free(sr);
560 }
561 
562 /*
563  * Determine whether or not the user is an administrator.
564  * Members of the administrators group have administrative rights.
565  */
566 boolean_t
567 smb_user_is_admin(smb_user_t *user)
568 {
569 #ifdef	_KERNEL
570 	char		sidstr[SMB_SID_STRSZ];
571 	ksidlist_t	*ksidlist;
572 	ksid_t		ksid1;
573 	ksid_t		*ksid2;
574 	int		i;
575 #endif	/* _KERNEL */
576 	boolean_t	rc = B_FALSE;
577 
578 	ASSERT(user);
579 	ASSERT(user->u_cred);
580 
581 	if (SMB_USER_IS_ADMIN(user))
582 		return (B_TRUE);
583 
584 #ifdef	_KERNEL
585 	bzero(&ksid1, sizeof (ksid_t));
586 	(void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ);
587 	ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0);
588 	ksid1.ks_domain = ksid_lookupdomain(sidstr);
589 
590 	ksidlist = crgetsidlist(user->u_cred);
591 	ASSERT(ksidlist);
592 	ASSERT(ksid1.ks_domain);
593 	ASSERT(ksid1.ks_domain->kd_name);
594 
595 	i = 0;
596 	ksid2 = crgetsid(user->u_cred, KSID_USER);
597 	do {
598 		ASSERT(ksid2->ks_domain);
599 		ASSERT(ksid2->ks_domain->kd_name);
600 
601 		if (strcmp(ksid1.ks_domain->kd_name,
602 		    ksid2->ks_domain->kd_name) == 0 &&
603 		    ksid1.ks_rid == ksid2->ks_rid) {
604 			user->u_flags |= SMB_USER_FLAG_ADMIN;
605 			rc = B_TRUE;
606 			break;
607 		}
608 
609 		ksid2 = &ksidlist->ksl_sids[i];
610 	} while (i++ < ksidlist->ksl_nsid);
611 
612 	ksid_rele(&ksid1);
613 #endif	/* _KERNEL */
614 	return (rc);
615 }
616 
617 /*
618  * This function should be called with a hold on the user.
619  */
620 boolean_t
621 smb_user_namecmp(smb_user_t *user, const char *name)
622 {
623 	char		*fq_name;
624 	boolean_t	match;
625 
626 	if (smb_strcasecmp(name, user->u_name, 0) == 0)
627 		return (B_TRUE);
628 
629 	fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
630 
631 	(void) snprintf(fq_name, MAXNAMELEN, "%s\\%s",
632 	    user->u_domain, user->u_name);
633 
634 	match = (smb_strcasecmp(name, fq_name, 0) == 0);
635 	if (!match) {
636 		(void) snprintf(fq_name, MAXNAMELEN, "%s@%s",
637 		    user->u_name, user->u_domain);
638 
639 		match = (smb_strcasecmp(name, fq_name, 0) == 0);
640 	}
641 
642 	kmem_free(fq_name, MAXNAMELEN);
643 	return (match);
644 }
645 
646 /*
647  * If the enumeration request is for user data, handle the request
648  * here.  Otherwise, pass it on to the trees.
649  *
650  * This function should be called with a hold on the user.
651  */
652 int
653 smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
654 {
655 	int		rc = 0;
656 
657 	ASSERT(user);
658 	ASSERT(user->u_magic == SMB_USER_MAGIC);
659 
660 	if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
661 		return (smb_user_enum_private(user, svcenum));
662 
663 	return (rc);
664 }
665 
666 /*
667  * Count references by trees this user owns,
668  * and allow waiting for them to go away.
669  */
670 void
671 smb_user_inc_trees(smb_user_t *user)
672 {
673 	mutex_enter(&user->u_mutex);
674 	user->u_owned_tree_cnt++;
675 	mutex_exit(&user->u_mutex);
676 }
677 
678 void
679 smb_user_dec_trees(smb_user_t *user)
680 {
681 	mutex_enter(&user->u_mutex);
682 	user->u_owned_tree_cnt--;
683 	if (user->u_owned_tree_cnt == 0)
684 		cv_broadcast(&user->u_owned_tree_cv);
685 	mutex_exit(&user->u_mutex);
686 }
687 
688 int smb_user_wait_tree_tmo = 30;
689 
690 /*
691  * Wait (up to 30 sec.) for trees to go away.
692  * Should happen in less than a second.
693  */
694 void
695 smb_user_wait_trees(smb_user_t *user)
696 {
697 	clock_t	time;
698 
699 	time = SEC_TO_TICK(smb_user_wait_tree_tmo) + ddi_get_lbolt();
700 	mutex_enter(&user->u_mutex);
701 	while (user->u_owned_tree_cnt != 0) {
702 		if (cv_timedwait(&user->u_owned_tree_cv,
703 		    &user->u_mutex, time) < 0)
704 			break;
705 	}
706 	mutex_exit(&user->u_mutex);
707 #ifdef	DEBUG
708 	if (user->u_owned_tree_cnt != 0) {
709 		cmn_err(CE_NOTE, "smb_user_wait_trees failed");
710 		debug_enter("smb_user_wait_trees debug");
711 	}
712 #endif
713 }
714 
715 /* *************************** Static Functions ***************************** */
716 
717 /*
718  * Delete a user.  The tree list should be empty.
719  *
720  * Remove the user from the session's user list before freeing resources
721  * associated with the user.
722  */
723 static void
724 smb_user_delete(void *arg)
725 {
726 	smb_session_t	*session;
727 	smb_user_t	*user = (smb_user_t *)arg;
728 	uint32_t	ucount;
729 
730 	SMB_USER_VALID(user);
731 	ASSERT(user->u_refcnt == 0);
732 	ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
733 	ASSERT(user->u_authsock == NULL);
734 	ASSERT(user->u_auth_tmo == NULL);
735 
736 	session = user->u_session;
737 
738 	smb_server_dec_users(session->s_server);
739 	smb_llist_enter(&session->s_user_list, RW_WRITER);
740 	smb_llist_remove(&session->s_user_list, user);
741 	smb_idpool_free(&session->s_uid_pool, user->u_uid);
742 	ucount = smb_llist_get_count(&session->s_user_list);
743 	smb_llist_exit(&session->s_user_list);
744 
745 	/*
746 	 * When the last smb_user_t object goes away, schedule a timeout
747 	 * after which we'll terminate this session if the client hasn't
748 	 * authenticated another smb_user_t on this session by then.
749 	 */
750 	if (ucount == 0) {
751 		smb_rwx_rwenter(&session->s_lock, RW_WRITER);
752 		if (session->s_state == SMB_SESSION_STATE_NEGOTIATED &&
753 		    session->s_auth_tmo == NULL) {
754 			session->s_auth_tmo =
755 			    timeout((tmo_func_t)smb_session_disconnect,
756 			    session, SEC_TO_TICK(smb_session_auth_tmo));
757 		}
758 		smb_rwx_cvbcast(&session->s_lock);
759 		smb_rwx_rwexit(&session->s_lock);
760 	}
761 
762 	/*
763 	 * This user is no longer on s_user_list, however...
764 	 *
765 	 * This is called via smb_llist_post, which means it may run
766 	 * BEFORE smb_user_release drops u_mutex (if another thread
767 	 * flushes the delete queue before we do).  Synchronize.
768 	 */
769 	mutex_enter(&user->u_mutex);
770 	mutex_exit(&user->u_mutex);
771 
772 	user->u_magic = (uint32_t)~SMB_USER_MAGIC;
773 	mutex_destroy(&user->u_mutex);
774 	if (user->u_cred)
775 		crfree(user->u_cred);
776 	if (user->u_privcred)
777 		crfree(user->u_privcred);
778 	smb_mem_free(user->u_name);
779 	smb_mem_free(user->u_domain);
780 	kmem_cache_free(smb_cache_user, user);
781 }
782 
783 cred_t *
784 smb_user_getcred(smb_user_t *user)
785 {
786 	return (user->u_cred);
787 }
788 
789 cred_t *
790 smb_user_getprivcred(smb_user_t *user)
791 {
792 	return ((user->u_privcred)? user->u_privcred : user->u_cred);
793 }
794 
795 #ifdef	_KERNEL
796 /*
797  * Assign the user cred and privileges.
798  *
799  * If the user has backup and/or restore privleges, dup the cred
800  * and add those privileges to this new privileged cred.
801  */
802 void
803 smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
804 {
805 	cred_t *privcred = NULL;
806 
807 	ASSERT(cr);
808 	crhold(cr);
809 
810 	/*
811 	 * See smb.4 bypass_traverse_checking
812 	 *
813 	 * For historical reasons, the Windows privilege is named
814 	 * SeChangeNotifyPrivilege, though the description is
815 	 * "Bypass traverse checking".
816 	 */
817 	if ((privileges & SMB_USER_PRIV_CHANGE_NOTIFY) != 0) {
818 		(void) crsetpriv(cr, PRIV_FILE_DAC_SEARCH, NULL);
819 	}
820 
821 	/*
822 	 * Window's "take ownership privilege" is similar to our
823 	 * PRIV_FILE_CHOWN privilege. It's normally given to members of the
824 	 * "Administrators" group, which normally includes the the local
825 	 * Administrator (like root) and when joined to a domain,
826 	 * "Domain Admins".
827 	 */
828 	if ((privileges & SMB_USER_PRIV_TAKE_OWNERSHIP) != 0) {
829 		(void) crsetpriv(cr,
830 		    PRIV_FILE_CHOWN,
831 		    PRIV_FILE_CHOWN_SELF,
832 		    NULL);
833 	}
834 
835 	/*
836 	 * Bypass ACL for READ accesses.
837 	 */
838 	if ((privileges & SMB_USER_PRIV_READ_FILE) != 0) {
839 		(void) crsetpriv(cr, PRIV_FILE_DAC_READ, NULL);
840 	}
841 
842 	/*
843 	 * Bypass ACL for WRITE accesses.
844 	 * Include FILE_OWNER, as it covers WRITE_ACL and DELETE.
845 	 */
846 	if ((privileges & SMB_USER_PRIV_WRITE_FILE) != 0) {
847 		(void) crsetpriv(cr,
848 		    PRIV_FILE_DAC_WRITE,
849 		    PRIV_FILE_OWNER,
850 		    NULL);
851 	}
852 
853 	/*
854 	 * These privileges are used only when a file is opened with
855 	 * 'backup intent'. These allow users to bypass certain access
856 	 * controls. Administrators typically have these privileges,
857 	 * and they are used during recursive take-ownership operations.
858 	 * Some commonly used tools use 'backup intent' to administrate
859 	 * files that do not grant explicit permissions to Administrators.
860 	 */
861 	if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
862 		privcred = crdup(cr);
863 
864 	if (privcred != NULL) {
865 		if (privileges & SMB_USER_PRIV_BACKUP) {
866 			(void) crsetpriv(privcred, PRIV_FILE_DAC_READ,
867 			    PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
868 		}
869 
870 		if (privileges & SMB_USER_PRIV_RESTORE) {
871 			(void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE,
872 			    PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
873 			    PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
874 			    PRIV_FILE_OWNER, PRIV_FILE_SETID,
875 			    PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL);
876 		}
877 	}
878 
879 	user->u_cred = cr;
880 	user->u_privcred = privcred;
881 	user->u_privileges = privileges;
882 }
883 #endif	/* _KERNEL */
884 
885 /*
886  * Determines whether a user can be granted ACCESS_SYSTEM_SECURITY
887  */
888 boolean_t
889 smb_user_has_security_priv(smb_user_t *user, cred_t *cr)
890 {
891 	/* Need SeSecurityPrivilege to get/set SACL */
892 	if ((user->u_privileges & SMB_USER_PRIV_SECURITY) != 0)
893 		return (B_TRUE);
894 
895 #ifdef _KERNEL
896 	/*
897 	 * ACCESS_SYSTEM_SECURITY is also granted if the file is opened with
898 	 * BACKUP/RESTORE intent by a user with BACKUP/RESTORE privilege,
899 	 * which means we'll be using u_privcred.
900 	 *
901 	 * We translate BACKUP as DAC_READ and RESTORE as DAC_WRITE,
902 	 * to account for our various SMB_USER_* privileges.
903 	 */
904 	if (PRIV_POLICY_ONLY(cr,
905 	    priv_getbyname(PRIV_FILE_DAC_READ, 0), B_FALSE) ||
906 	    PRIV_POLICY_ONLY(cr,
907 	    priv_getbyname(PRIV_FILE_DAC_WRITE, 0), B_FALSE))
908 		return (B_TRUE);
909 #else
910 	/*
911 	 * No "real" privileges in fksmbsrv, so use the SMB privs instead.
912 	 */
913 	if ((user->u_privileges &
914 	    (SMB_USER_PRIV_BACKUP |
915 	    SMB_USER_PRIV_RESTORE |
916 	    SMB_USER_PRIV_READ_FILE |
917 	    SMB_USER_PRIV_WRITE_FILE)) != 0)
918 		return (B_TRUE);
919 #endif
920 
921 	return (B_FALSE);
922 }
923 
924 /*
925  * Private function to support smb_user_enum.
926  */
927 static int
928 smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum)
929 {
930 	uint8_t *pb;
931 	uint_t nbytes;
932 	int rc;
933 
934 	if (svcenum->se_nskip > 0) {
935 		svcenum->se_nskip--;
936 		return (0);
937 	}
938 
939 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
940 		svcenum->se_nitems = svcenum->se_nlimit;
941 		return (0);
942 	}
943 
944 	pb = &svcenum->se_buf[svcenum->se_bused];
945 	rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes);
946 	if (rc == 0) {
947 		svcenum->se_bavail -= nbytes;
948 		svcenum->se_bused += nbytes;
949 		svcenum->se_nitems++;
950 	}
951 
952 	return (rc);
953 }
954 
955 /*
956  * Encode the NetInfo for a user into a buffer.  NetInfo contains
957  * information that is often needed in user space to support RPC
958  * requests.
959  */
960 int
961 smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen,
962     uint32_t *nbytes)
963 {
964 	smb_netuserinfo_t	info;
965 	int			rc;
966 
967 	smb_user_netinfo_init(user, &info);
968 	rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes);
969 	smb_user_netinfo_fini(&info);
970 
971 	return (rc);
972 }
973 
974 void
975 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
976 {
977 	smb_session_t	*session;
978 	char		*buf;
979 
980 	ASSERT(user);
981 	ASSERT(user->u_domain);
982 	ASSERT(user->u_name);
983 
984 	session = user->u_session;
985 	ASSERT(session);
986 	ASSERT(session->workstation);
987 
988 	info->ui_session_id = session->s_kid;
989 	info->ui_native_os = session->native_os;
990 	info->ui_ipaddr = session->ipaddr;
991 	info->ui_numopens = session->s_file_cnt;
992 	info->ui_logon_time = user->u_logon_time;
993 	info->ui_flags = user->u_flags;
994 	info->ui_posix_uid = crgetuid(user->u_cred);
995 
996 	info->ui_domain_len = user->u_domain_len;
997 	info->ui_domain = smb_mem_strdup(user->u_domain);
998 
999 	info->ui_account_len = user->u_name_len;
1000 	info->ui_account = smb_mem_strdup(user->u_name);
1001 
1002 	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1003 	smb_session_getclient(session, buf, MAXNAMELEN);
1004 	info->ui_workstation_len = strlen(buf) + 1;
1005 	info->ui_workstation = smb_mem_strdup(buf);
1006 	kmem_free(buf, MAXNAMELEN);
1007 }
1008 
1009 void
1010 smb_user_netinfo_fini(smb_netuserinfo_t *info)
1011 {
1012 	if (info == NULL)
1013 		return;
1014 
1015 	if (info->ui_domain)
1016 		smb_mem_free(info->ui_domain);
1017 	if (info->ui_account)
1018 		smb_mem_free(info->ui_account);
1019 	if (info->ui_workstation)
1020 		smb_mem_free(info->ui_workstation);
1021 
1022 	bzero(info, sizeof (smb_netuserinfo_t));
1023 }
1024 
1025 /*
1026  * Tell smbd this user is going away so it can clean up their
1027  * audit session, autohome dir, etc.
1028  *
1029  * Note that when we're shutting down, smbd will already have set
1030  * smbd.s_shutting_down and therefore will ignore door calls.
1031  * Skip this during shutdown to reduce upcall noise.
1032  */
1033 static void
1034 smb_user_auth_logoff(smb_user_t *user)
1035 {
1036 	smb_server_t *sv = user->u_server;
1037 	uint32_t audit_sid;
1038 
1039 	if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
1040 		return;
1041 
1042 	audit_sid = user->u_audit_sid;
1043 	(void) smb_kdoor_upcall(sv, SMB_DR_USER_AUTH_LOGOFF,
1044 	    &audit_sid, xdr_uint32_t, NULL, NULL);
1045 }
1046 
1047 boolean_t
1048 smb_is_same_user(cred_t *cr1, cred_t *cr2)
1049 {
1050 	ksid_t *ks1 = crgetsid(cr1, KSID_USER);
1051 	ksid_t *ks2 = crgetsid(cr2, KSID_USER);
1052 
1053 	if (ks1 == NULL || ks2 == NULL) {
1054 		return (B_FALSE);
1055 	}
1056 	return (ks1->ks_rid == ks2->ks_rid &&
1057 	    strcmp(ks1->ks_domain->kd_name, ks2->ks_domain->kd_name) == 0);
1058 }
1059