xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_user.c (revision 5328fc53d11d7151861fa272e4fb0248b8f0e145)
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 2018 Nexenta Systems, 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 <smbsrv/smb_kproto.h>
209 #include <smbsrv/smb_door.h>
210 
211 #define	ADMINISTRATORS_SID	"S-1-5-32-544"
212 
213 /* Don't leak object addresses */
214 #define	SMB_USER_SSNID(u) \
215 	((uintptr_t)&smb_cache_user ^ (uintptr_t)(u))
216 
217 static void smb_user_delete(void *);
218 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
219 static void smb_user_auth_logoff(smb_user_t *);
220 static void smb_user_logoff_tq(void *);
221 
222 /*
223  * Create a new user.
224  *
225  * For SMB2 and later, session IDs (u_ssnid) need to be unique among all
226  * current and "recent" sessions.  The session ID is derived from the
227  * address of the smb_user object (obscured by XOR with a constant).
228  * This adds a 3-bit generation number in the low bits, incremented
229  * when we allocate an smb_user_t from its kmem cache, so it can't
230  * be confused with a (recent) previous incarnation of this object.
231  */
232 smb_user_t *
233 smb_user_new(smb_session_t *session)
234 {
235 	smb_user_t	*user;
236 	uint_t		gen;	// generation (low 3 bits of ssnid)
237 	uint32_t	ucount;
238 
239 	ASSERT(session);
240 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
241 
242 	user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
243 	gen = (user->u_ssnid + 1) & 7;
244 	bzero(user, sizeof (smb_user_t));
245 
246 	user->u_refcnt = 1;
247 	user->u_session = session;
248 	user->u_server = session->s_server;
249 	user->u_logon_time = gethrestime_sec();
250 
251 	if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
252 		goto errout;
253 	user->u_ssnid = SMB_USER_SSNID(user) + gen;
254 
255 	mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
256 	user->u_state = SMB_USER_STATE_LOGGING_ON;
257 	user->u_magic = SMB_USER_MAGIC;
258 
259 	smb_llist_enter(&session->s_user_list, RW_WRITER);
260 	ucount = smb_llist_get_count(&session->s_user_list);
261 	smb_llist_insert_tail(&session->s_user_list, user);
262 	smb_llist_exit(&session->s_user_list);
263 	smb_server_inc_users(session->s_server);
264 
265 	/*
266 	 * If we added the first user to the session, cancel the
267 	 * timeout that was started in smb_session_receiver().
268 	 */
269 	if (ucount == 0) {
270 		timeout_id_t tmo = NULL;
271 
272 		smb_rwx_rwenter(&session->s_lock, RW_WRITER);
273 		tmo = session->s_auth_tmo;
274 		session->s_auth_tmo = NULL;
275 		smb_rwx_rwexit(&session->s_lock);
276 
277 		if (tmo != NULL)
278 			(void) untimeout(tmo);
279 	}
280 
281 	return (user);
282 
283 errout:
284 	if (user->u_uid != 0)
285 		smb_idpool_free(&session->s_uid_pool, user->u_uid);
286 	kmem_cache_free(smb_cache_user, user);
287 	return (NULL);
288 }
289 
290 /*
291  * Fill in the details of a user, meaning a transition
292  * from state LOGGING_ON to state LOGGED_ON.
293  */
294 int
295 smb_user_logon(
296     smb_user_t		*user,
297     cred_t		*cr,
298     char		*domain_name,
299     char		*account_name,
300     uint32_t		flags,
301     uint32_t		privileges,
302     uint32_t		audit_sid)
303 {
304 	ksocket_t authsock = NULL;
305 	timeout_id_t tmo = NULL;
306 
307 	ASSERT(user->u_magic == SMB_USER_MAGIC);
308 	ASSERT(cr);
309 	ASSERT(account_name);
310 	ASSERT(domain_name);
311 
312 	mutex_enter(&user->u_mutex);
313 
314 	if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
315 		mutex_exit(&user->u_mutex);
316 		return (-1);
317 	}
318 
319 	/*
320 	 * In the transition from LOGGING_ON to LOGGED_ON,
321 	 * we always have an auth. socket to close.
322 	 */
323 	authsock = user->u_authsock;
324 	user->u_authsock = NULL;
325 	tmo = user->u_auth_tmo;
326 	user->u_auth_tmo = NULL;
327 
328 	user->u_state = SMB_USER_STATE_LOGGED_ON;
329 	user->u_flags = flags;
330 	user->u_name_len = strlen(account_name) + 1;
331 	user->u_domain_len = strlen(domain_name) + 1;
332 	user->u_name = smb_mem_strdup(account_name);
333 	user->u_domain = smb_mem_strdup(domain_name);
334 	user->u_audit_sid = audit_sid;
335 
336 	smb_user_setcred(user, cr, privileges);
337 
338 	mutex_exit(&user->u_mutex);
339 
340 	/* Timeout callback takes u_mutex. See untimeout(9f) */
341 	if (tmo != NULL)
342 		(void) untimeout(tmo);
343 
344 	/* This close can block, so not under the mutex. */
345 	if (authsock != NULL)
346 		smb_authsock_close(user, authsock);
347 
348 	return (0);
349 }
350 
351 /*
352  * smb_user_logoff
353  *
354  * Change the user state to "logging off" and disconnect trees.
355  * The user list must not be entered or modified here.
356  *
357  * We remain in state "logging off" until the last ref. is gone,
358  * then smb_user_release takes us to state "logged off".
359  */
360 void
361 smb_user_logoff(
362     smb_user_t		*user)
363 {
364 	ksocket_t authsock = NULL;
365 	timeout_id_t tmo = NULL;
366 
367 	ASSERT(user->u_magic == SMB_USER_MAGIC);
368 
369 	mutex_enter(&user->u_mutex);
370 	ASSERT(user->u_refcnt);
371 	switch (user->u_state) {
372 	case SMB_USER_STATE_LOGGING_ON:
373 		authsock = user->u_authsock;
374 		user->u_authsock = NULL;
375 		tmo = user->u_auth_tmo;
376 		user->u_auth_tmo = NULL;
377 		user->u_state = SMB_USER_STATE_LOGGING_OFF;
378 		mutex_exit(&user->u_mutex);
379 
380 		/* Timeout callback takes u_mutex. See untimeout(9f) */
381 		if (tmo != NULL)
382 			(void) untimeout(tmo);
383 		/* This close can block, so not under the mutex. */
384 		if (authsock != NULL)
385 			smb_authsock_close(user, authsock);
386 		break;
387 
388 	case SMB_USER_STATE_LOGGED_ON:
389 		/*
390 		 * The user is moved into a state indicating that the log off
391 		 * process has started.
392 		 */
393 		user->u_state = SMB_USER_STATE_LOGGING_OFF;
394 		mutex_exit(&user->u_mutex);
395 		smb_session_disconnect_owned_trees(user->u_session, user);
396 		smb_user_auth_logoff(user);
397 		break;
398 
399 	case SMB_USER_STATE_LOGGED_OFF:
400 	case SMB_USER_STATE_LOGGING_OFF:
401 		mutex_exit(&user->u_mutex);
402 		break;
403 
404 	default:
405 		ASSERT(0);
406 		mutex_exit(&user->u_mutex);
407 		break;
408 	}
409 }
410 
411 /*
412  * Take a reference on a user.  Do not return a reference unless the user is in
413  * the logged-in state.
414  */
415 boolean_t
416 smb_user_hold(smb_user_t *user)
417 {
418 	SMB_USER_VALID(user);
419 
420 	mutex_enter(&user->u_mutex);
421 
422 	if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
423 		user->u_refcnt++;
424 		mutex_exit(&user->u_mutex);
425 		return (B_TRUE);
426 	}
427 
428 	mutex_exit(&user->u_mutex);
429 	return (B_FALSE);
430 }
431 
432 /*
433  * Unconditionally take a reference on a user.
434  */
435 void
436 smb_user_hold_internal(smb_user_t *user)
437 {
438 	SMB_USER_VALID(user);
439 
440 	mutex_enter(&user->u_mutex);
441 	user->u_refcnt++;
442 	mutex_exit(&user->u_mutex);
443 }
444 
445 /*
446  * Release a reference on a user.  If the reference count falls to
447  * zero and the user has logged off, post the object for deletion.
448  * Object deletion is deferred to avoid modifying a list while an
449  * iteration may be in progress.
450  */
451 void
452 smb_user_release(
453     smb_user_t		*user)
454 {
455 	smb_session_t *ssn = user->u_session;
456 
457 	SMB_USER_VALID(user);
458 
459 	/* flush the tree list delete queue */
460 	smb_llist_flush(&ssn->s_tree_list);
461 
462 	mutex_enter(&user->u_mutex);
463 	ASSERT(user->u_refcnt);
464 	user->u_refcnt--;
465 
466 	switch (user->u_state) {
467 	case SMB_USER_STATE_LOGGING_OFF:
468 		if (user->u_refcnt == 0) {
469 			smb_session_t *ssn = user->u_session;
470 			user->u_state = SMB_USER_STATE_LOGGED_OFF;
471 			smb_llist_post(&ssn->s_user_list, user,
472 			    smb_user_delete);
473 		}
474 		break;
475 
476 	case SMB_USER_STATE_LOGGING_ON:
477 	case SMB_USER_STATE_LOGGED_ON:
478 		break;
479 
480 	case SMB_USER_STATE_LOGGED_OFF:
481 	default:
482 		ASSERT(0);
483 		break;
484 	}
485 	mutex_exit(&user->u_mutex);
486 }
487 
488 /*
489  * Timeout handler for user logons that stay too long in
490  * state SMB_USER_STATE_LOGGING_ON.  This is setup by a
491  * timeout call in smb_authsock_open, and called in a
492  * callout thread, so schedule a taskq job to do the
493  * real work of logging off this user.
494  */
495 void
496 smb_user_auth_tmo(void *arg)
497 {
498 	smb_user_t *user = arg;
499 	smb_request_t *sr;
500 
501 	SMB_USER_VALID(user);
502 
503 	/*
504 	 * If we can't allocate a request, it means the
505 	 * session is being torn down, so nothing to do.
506 	 */
507 	sr = smb_request_alloc(user->u_session, 0);
508 	if (sr == NULL)
509 		return;
510 
511 	/*
512 	 * Check user state, and take a hold if it's
513 	 * still logging on.  If not, we're done.
514 	 */
515 	mutex_enter(&user->u_mutex);
516 	if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
517 		mutex_exit(&user->u_mutex);
518 		smb_request_free(sr);
519 		return;
520 	}
521 	/* smb_user_hold_internal */
522 	user->u_refcnt++;
523 	mutex_exit(&user->u_mutex);
524 
525 	/*
526 	 * The user hold is given to the SR, and released in
527 	 * smb_user_logoff_tq / smb_request_free
528 	 */
529 	sr->uid_user = user;
530 	sr->user_cr = user->u_cred;
531 	sr->sr_state = SMB_REQ_STATE_SUBMITTED;
532 
533 	(void) taskq_dispatch(
534 	    user->u_server->sv_worker_pool,
535 	    smb_user_logoff_tq, sr, TQ_SLEEP);
536 }
537 
538 /*
539  * Helper for smb_user_auth_tmo()
540  */
541 static void
542 smb_user_logoff_tq(void *arg)
543 {
544 	smb_request_t	*sr = arg;
545 
546 	SMB_REQ_VALID(sr);
547 
548 	mutex_enter(&sr->sr_mutex);
549 	sr->sr_worker = curthread;
550 	sr->sr_state = SMB_REQ_STATE_ACTIVE;
551 	mutex_exit(&sr->sr_mutex);
552 
553 	smb_user_logoff(sr->uid_user);
554 
555 	sr->sr_state = SMB_REQ_STATE_COMPLETED;
556 	smb_request_free(sr);
557 }
558 
559 /*
560  * Determine whether or not the user is an administrator.
561  * Members of the administrators group have administrative rights.
562  */
563 boolean_t
564 smb_user_is_admin(smb_user_t *user)
565 {
566 #ifdef	_KERNEL
567 	char		sidstr[SMB_SID_STRSZ];
568 	ksidlist_t	*ksidlist;
569 	ksid_t		ksid1;
570 	ksid_t		*ksid2;
571 	int		i;
572 #endif	/* _KERNEL */
573 	boolean_t	rc = B_FALSE;
574 
575 	ASSERT(user);
576 	ASSERT(user->u_cred);
577 
578 	if (SMB_USER_IS_ADMIN(user))
579 		return (B_TRUE);
580 
581 #ifdef	_KERNEL
582 	bzero(&ksid1, sizeof (ksid_t));
583 	(void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ);
584 	ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0);
585 	ksid1.ks_domain = ksid_lookupdomain(sidstr);
586 
587 	ksidlist = crgetsidlist(user->u_cred);
588 	ASSERT(ksidlist);
589 	ASSERT(ksid1.ks_domain);
590 	ASSERT(ksid1.ks_domain->kd_name);
591 
592 	i = 0;
593 	ksid2 = crgetsid(user->u_cred, KSID_USER);
594 	do {
595 		ASSERT(ksid2->ks_domain);
596 		ASSERT(ksid2->ks_domain->kd_name);
597 
598 		if (strcmp(ksid1.ks_domain->kd_name,
599 		    ksid2->ks_domain->kd_name) == 0 &&
600 		    ksid1.ks_rid == ksid2->ks_rid) {
601 			user->u_flags |= SMB_USER_FLAG_ADMIN;
602 			rc = B_TRUE;
603 			break;
604 		}
605 
606 		ksid2 = &ksidlist->ksl_sids[i];
607 	} while (i++ < ksidlist->ksl_nsid);
608 
609 	ksid_rele(&ksid1);
610 #endif	/* _KERNEL */
611 	return (rc);
612 }
613 
614 /*
615  * This function should be called with a hold on the user.
616  */
617 boolean_t
618 smb_user_namecmp(smb_user_t *user, const char *name)
619 {
620 	char		*fq_name;
621 	boolean_t	match;
622 
623 	if (smb_strcasecmp(name, user->u_name, 0) == 0)
624 		return (B_TRUE);
625 
626 	fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
627 
628 	(void) snprintf(fq_name, MAXNAMELEN, "%s\\%s",
629 	    user->u_domain, user->u_name);
630 
631 	match = (smb_strcasecmp(name, fq_name, 0) == 0);
632 	if (!match) {
633 		(void) snprintf(fq_name, MAXNAMELEN, "%s@%s",
634 		    user->u_name, user->u_domain);
635 
636 		match = (smb_strcasecmp(name, fq_name, 0) == 0);
637 	}
638 
639 	kmem_free(fq_name, MAXNAMELEN);
640 	return (match);
641 }
642 
643 /*
644  * If the enumeration request is for user data, handle the request
645  * here.  Otherwise, pass it on to the trees.
646  *
647  * This function should be called with a hold on the user.
648  */
649 int
650 smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
651 {
652 	int		rc = 0;
653 
654 	ASSERT(user);
655 	ASSERT(user->u_magic == SMB_USER_MAGIC);
656 
657 	if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
658 		return (smb_user_enum_private(user, svcenum));
659 
660 	return (rc);
661 }
662 
663 /* *************************** Static Functions ***************************** */
664 
665 /*
666  * Delete a user.  The tree list should be empty.
667  *
668  * Remove the user from the session's user list before freeing resources
669  * associated with the user.
670  */
671 static void
672 smb_user_delete(void *arg)
673 {
674 	smb_session_t	*session;
675 	smb_user_t	*user = (smb_user_t *)arg;
676 	uint32_t	ucount;
677 
678 	SMB_USER_VALID(user);
679 	ASSERT(user->u_refcnt == 0);
680 	ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
681 	ASSERT(user->u_authsock == NULL);
682 	ASSERT(user->u_auth_tmo == NULL);
683 
684 	session = user->u_session;
685 
686 	smb_server_dec_users(session->s_server);
687 	smb_llist_enter(&session->s_user_list, RW_WRITER);
688 	smb_llist_remove(&session->s_user_list, user);
689 	smb_idpool_free(&session->s_uid_pool, user->u_uid);
690 	ucount = smb_llist_get_count(&session->s_user_list);
691 	smb_llist_exit(&session->s_user_list);
692 
693 	/*
694 	 * When the last smb_user_t object goes away, schedule a timeout
695 	 * after which we'll terminate this session if the client hasn't
696 	 * authenticated another smb_user_t on this session by then.
697 	 */
698 	if (ucount == 0) {
699 		smb_rwx_rwenter(&session->s_lock, RW_WRITER);
700 		if (session->s_state == SMB_SESSION_STATE_NEGOTIATED &&
701 		    session->s_auth_tmo == NULL) {
702 			session->s_auth_tmo =
703 			    timeout((tmo_func_t)smb_session_disconnect,
704 			    session, SEC_TO_TICK(smb_session_auth_tmo));
705 		}
706 		smb_rwx_cvbcast(&session->s_lock);
707 		smb_rwx_rwexit(&session->s_lock);
708 	}
709 
710 	/*
711 	 * This user is no longer on s_user_list, however...
712 	 *
713 	 * This is called via smb_llist_post, which means it may run
714 	 * BEFORE smb_user_release drops u_mutex (if another thread
715 	 * flushes the delete queue before we do).  Synchronize.
716 	 */
717 	mutex_enter(&user->u_mutex);
718 	mutex_exit(&user->u_mutex);
719 
720 	user->u_magic = (uint32_t)~SMB_USER_MAGIC;
721 	mutex_destroy(&user->u_mutex);
722 	if (user->u_cred)
723 		crfree(user->u_cred);
724 	if (user->u_privcred)
725 		crfree(user->u_privcred);
726 	smb_mem_free(user->u_name);
727 	smb_mem_free(user->u_domain);
728 	kmem_cache_free(smb_cache_user, user);
729 }
730 
731 cred_t *
732 smb_user_getcred(smb_user_t *user)
733 {
734 	return (user->u_cred);
735 }
736 
737 cred_t *
738 smb_user_getprivcred(smb_user_t *user)
739 {
740 	return ((user->u_privcred)? user->u_privcred : user->u_cred);
741 }
742 
743 #ifdef	_KERNEL
744 /*
745  * Assign the user cred and privileges.
746  *
747  * If the user has backup and/or restore privleges, dup the cred
748  * and add those privileges to this new privileged cred.
749  */
750 void
751 smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
752 {
753 	cred_t *privcred = NULL;
754 
755 	ASSERT(cr);
756 	crhold(cr);
757 
758 	if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
759 		privcred = crdup(cr);
760 
761 	if (privcred != NULL) {
762 		if (privileges & SMB_USER_PRIV_BACKUP) {
763 			(void) crsetpriv(privcred, PRIV_FILE_DAC_READ,
764 			    PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
765 		}
766 
767 		if (privileges & SMB_USER_PRIV_RESTORE) {
768 			(void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE,
769 			    PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
770 			    PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
771 			    PRIV_FILE_OWNER, PRIV_FILE_SETID,
772 			    PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL);
773 		}
774 	}
775 
776 	user->u_cred = cr;
777 	user->u_privcred = privcred;
778 	user->u_privileges = privileges;
779 }
780 #endif	/* _KERNEL */
781 
782 /*
783  * Private function to support smb_user_enum.
784  */
785 static int
786 smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum)
787 {
788 	uint8_t *pb;
789 	uint_t nbytes;
790 	int rc;
791 
792 	if (svcenum->se_nskip > 0) {
793 		svcenum->se_nskip--;
794 		return (0);
795 	}
796 
797 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
798 		svcenum->se_nitems = svcenum->se_nlimit;
799 		return (0);
800 	}
801 
802 	pb = &svcenum->se_buf[svcenum->se_bused];
803 	rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes);
804 	if (rc == 0) {
805 		svcenum->se_bavail -= nbytes;
806 		svcenum->se_bused += nbytes;
807 		svcenum->se_nitems++;
808 	}
809 
810 	return (rc);
811 }
812 
813 /*
814  * Encode the NetInfo for a user into a buffer.  NetInfo contains
815  * information that is often needed in user space to support RPC
816  * requests.
817  */
818 int
819 smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen,
820     uint32_t *nbytes)
821 {
822 	smb_netuserinfo_t	info;
823 	int			rc;
824 
825 	smb_user_netinfo_init(user, &info);
826 	rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes);
827 	smb_user_netinfo_fini(&info);
828 
829 	return (rc);
830 }
831 
832 void
833 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
834 {
835 	smb_session_t	*session;
836 	char		*buf;
837 
838 	ASSERT(user);
839 	ASSERT(user->u_domain);
840 	ASSERT(user->u_name);
841 
842 	session = user->u_session;
843 	ASSERT(session);
844 	ASSERT(session->workstation);
845 
846 	info->ui_session_id = session->s_kid;
847 	info->ui_native_os = session->native_os;
848 	info->ui_ipaddr = session->ipaddr;
849 	info->ui_numopens = session->s_file_cnt;
850 	info->ui_logon_time = user->u_logon_time;
851 	info->ui_flags = user->u_flags;
852 	info->ui_posix_uid = crgetuid(user->u_cred);
853 
854 	info->ui_domain_len = user->u_domain_len;
855 	info->ui_domain = smb_mem_strdup(user->u_domain);
856 
857 	info->ui_account_len = user->u_name_len;
858 	info->ui_account = smb_mem_strdup(user->u_name);
859 
860 	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
861 	smb_session_getclient(session, buf, MAXNAMELEN);
862 	info->ui_workstation_len = strlen(buf) + 1;
863 	info->ui_workstation = smb_mem_strdup(buf);
864 	kmem_free(buf, MAXNAMELEN);
865 }
866 
867 void
868 smb_user_netinfo_fini(smb_netuserinfo_t *info)
869 {
870 	if (info == NULL)
871 		return;
872 
873 	if (info->ui_domain)
874 		smb_mem_free(info->ui_domain);
875 	if (info->ui_account)
876 		smb_mem_free(info->ui_account);
877 	if (info->ui_workstation)
878 		smb_mem_free(info->ui_workstation);
879 
880 	bzero(info, sizeof (smb_netuserinfo_t));
881 }
882 
883 /*
884  * Tell smbd this user is going away so it can clean up their
885  * audit session, autohome dir, etc.
886  *
887  * Note that when we're shutting down, smbd will already have set
888  * smbd.s_shutting_down and therefore will ignore door calls.
889  * Skip this during shutdown to reduce upcall noise.
890  */
891 static void
892 smb_user_auth_logoff(smb_user_t *user)
893 {
894 	smb_server_t *sv = user->u_server;
895 	uint32_t audit_sid;
896 
897 	if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
898 		return;
899 
900 	audit_sid = user->u_audit_sid;
901 	(void) smb_kdoor_upcall(sv, SMB_DR_USER_AUTH_LOGOFF,
902 	    &audit_sid, xdr_uint32_t, NULL, NULL);
903 }
904 
905 boolean_t
906 smb_is_same_user(cred_t *cr1, cred_t *cr2)
907 {
908 	ksid_t *ks1 = crgetsid(cr1, KSID_USER);
909 	ksid_t *ks2 = crgetsid(cr2, KSID_USER);
910 
911 	return (ks1->ks_rid == ks2->ks_rid &&
912 	    strcmp(ks1->ks_domain->kd_name, ks2->ks_domain->kd_name) == 0);
913 }
914