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