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 <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
217static void smb_user_delete(void *);
218static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
219static void smb_user_auth_logoff(smb_user_t *);
220static 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 */
232smb_user_t *
233smb_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
283errout:
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 */
294int
295smb_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 */
360void
361smb_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 */
415boolean_t
416smb_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 */
435void
436smb_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 */
451void
452smb_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 */
495void
496smb_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 */
541static void
542smb_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 */
563boolean_t
564smb_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 */
617boolean_t
618smb_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 */
649int
650smb_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 */
671static void
672smb_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
731cred_t *
732smb_user_getcred(smb_user_t *user)
733{
734	return (user->u_cred);
735}
736
737cred_t *
738smb_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 */
750void
751smb_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	/*
759	 * See smb.4 bypass_traverse_checking
760	 *
761	 * For historical reasons, the Windows privilege is named
762	 * SeChangeNotifyPrivilege, though the description is
763	 * "Bypass traverse checking".
764	 */
765	if ((privileges & SMB_USER_PRIV_CHANGE_NOTIFY) != 0) {
766		(void) crsetpriv(cr, PRIV_FILE_DAC_SEARCH, NULL);
767	}
768
769	/*
770	 * Window's "take ownership privilege" is similar to our
771	 * PRIV_FILE_CHOWN privilege. It's normally given to members of the
772	 * "Administrators" group, which normally includes the the local
773	 * Administrator (like root) and when joined to a domain,
774	 * "Domain Admins".
775	 */
776	if ((privileges & SMB_USER_PRIV_TAKE_OWNERSHIP) != 0) {
777		(void) crsetpriv(cr,
778		    PRIV_FILE_CHOWN,
779		    PRIV_FILE_CHOWN_SELF,
780		    NULL);
781	}
782
783	/*
784	 * Bypass ACL for READ accesses.
785	 */
786	if ((privileges & SMB_USER_PRIV_READ_FILE) != 0) {
787		(void) crsetpriv(cr, PRIV_FILE_DAC_READ, NULL);
788	}
789
790	/*
791	 * Bypass ACL for WRITE accesses.
792	 * Include FILE_OWNER, as it covers WRITE_ACL and DELETE.
793	 */
794	if ((privileges & SMB_USER_PRIV_WRITE_FILE) != 0) {
795		(void) crsetpriv(cr,
796		    PRIV_FILE_DAC_WRITE,
797		    PRIV_FILE_OWNER,
798		    NULL);
799	}
800
801	/*
802	 * These privileges are used only when a file is opened with
803	 * 'backup intent'. These allow users to bypass certain access
804	 * controls. Administrators typically have these privileges,
805	 * and they are used during recursive take-ownership operations.
806	 * Some commonly used tools use 'backup intent' to administrate
807	 * files that do not grant explicit permissions to Administrators.
808	 */
809	if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
810		privcred = crdup(cr);
811
812	if (privcred != NULL) {
813		if (privileges & SMB_USER_PRIV_BACKUP) {
814			(void) crsetpriv(privcred, PRIV_FILE_DAC_READ,
815			    PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
816		}
817
818		if (privileges & SMB_USER_PRIV_RESTORE) {
819			(void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE,
820			    PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
821			    PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
822			    PRIV_FILE_OWNER, PRIV_FILE_SETID,
823			    PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL);
824		}
825	}
826
827	user->u_cred = cr;
828	user->u_privcred = privcred;
829	user->u_privileges = privileges;
830}
831#endif	/* _KERNEL */
832
833/*
834 * Private function to support smb_user_enum.
835 */
836static int
837smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum)
838{
839	uint8_t *pb;
840	uint_t nbytes;
841	int rc;
842
843	if (svcenum->se_nskip > 0) {
844		svcenum->se_nskip--;
845		return (0);
846	}
847
848	if (svcenum->se_nitems >= svcenum->se_nlimit) {
849		svcenum->se_nitems = svcenum->se_nlimit;
850		return (0);
851	}
852
853	pb = &svcenum->se_buf[svcenum->se_bused];
854	rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes);
855	if (rc == 0) {
856		svcenum->se_bavail -= nbytes;
857		svcenum->se_bused += nbytes;
858		svcenum->se_nitems++;
859	}
860
861	return (rc);
862}
863
864/*
865 * Encode the NetInfo for a user into a buffer.  NetInfo contains
866 * information that is often needed in user space to support RPC
867 * requests.
868 */
869int
870smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen,
871    uint32_t *nbytes)
872{
873	smb_netuserinfo_t	info;
874	int			rc;
875
876	smb_user_netinfo_init(user, &info);
877	rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes);
878	smb_user_netinfo_fini(&info);
879
880	return (rc);
881}
882
883void
884smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
885{
886	smb_session_t	*session;
887	char		*buf;
888
889	ASSERT(user);
890	ASSERT(user->u_domain);
891	ASSERT(user->u_name);
892
893	session = user->u_session;
894	ASSERT(session);
895	ASSERT(session->workstation);
896
897	info->ui_session_id = session->s_kid;
898	info->ui_native_os = session->native_os;
899	info->ui_ipaddr = session->ipaddr;
900	info->ui_numopens = session->s_file_cnt;
901	info->ui_logon_time = user->u_logon_time;
902	info->ui_flags = user->u_flags;
903	info->ui_posix_uid = crgetuid(user->u_cred);
904
905	info->ui_domain_len = user->u_domain_len;
906	info->ui_domain = smb_mem_strdup(user->u_domain);
907
908	info->ui_account_len = user->u_name_len;
909	info->ui_account = smb_mem_strdup(user->u_name);
910
911	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
912	smb_session_getclient(session, buf, MAXNAMELEN);
913	info->ui_workstation_len = strlen(buf) + 1;
914	info->ui_workstation = smb_mem_strdup(buf);
915	kmem_free(buf, MAXNAMELEN);
916}
917
918void
919smb_user_netinfo_fini(smb_netuserinfo_t *info)
920{
921	if (info == NULL)
922		return;
923
924	if (info->ui_domain)
925		smb_mem_free(info->ui_domain);
926	if (info->ui_account)
927		smb_mem_free(info->ui_account);
928	if (info->ui_workstation)
929		smb_mem_free(info->ui_workstation);
930
931	bzero(info, sizeof (smb_netuserinfo_t));
932}
933
934/*
935 * Tell smbd this user is going away so it can clean up their
936 * audit session, autohome dir, etc.
937 *
938 * Note that when we're shutting down, smbd will already have set
939 * smbd.s_shutting_down and therefore will ignore door calls.
940 * Skip this during shutdown to reduce upcall noise.
941 */
942static void
943smb_user_auth_logoff(smb_user_t *user)
944{
945	smb_server_t *sv = user->u_server;
946	uint32_t audit_sid;
947
948	if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
949		return;
950
951	audit_sid = user->u_audit_sid;
952	(void) smb_kdoor_upcall(sv, SMB_DR_USER_AUTH_LOGOFF,
953	    &audit_sid, xdr_uint32_t, NULL, NULL);
954}
955
956boolean_t
957smb_is_same_user(cred_t *cr1, cred_t *cr2)
958{
959	ksid_t *ks1 = crgetsid(cr1, KSID_USER);
960	ksid_t *ks2 = crgetsid(cr2, KSID_USER);
961
962	return (ks1->ks_rid == ks2->ks_rid &&
963	    strcmp(ks1->ks_domain->kd_name, ks2->ks_domain->kd_name) == 0);
964}
965