xref: /titanic_51/usr/src/uts/common/fs/smbsrv/smb_user.c (revision 12b65585e720714b31036daaa2b30eb76014048e)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*12b65585SGordon Ross  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw /*
27da6c28aaSamw  * General Structures Layout
28da6c28aaSamw  * -------------------------
29da6c28aaSamw  *
30da6c28aaSamw  * This is a simplified diagram showing the relationship between most of the
31da6c28aaSamw  * main structures.
32da6c28aaSamw  *
33da6c28aaSamw  * +-------------------+
34da6c28aaSamw  * |     SMB_INFO      |
35da6c28aaSamw  * +-------------------+
36da6c28aaSamw  *          |
37da6c28aaSamw  *          |
38da6c28aaSamw  *          v
39da6c28aaSamw  * +-------------------+       +-------------------+      +-------------------+
40da6c28aaSamw  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
41da6c28aaSamw  * +-------------------+       +-------------------+      +-------------------+
423b13a1efSThomas Keiser  *   |          |
433b13a1efSThomas Keiser  *   |          |
443b13a1efSThomas Keiser  *   |          v
453b13a1efSThomas Keiser  *   |  +-------------------+     +-------------------+   +-------------------+
463b13a1efSThomas Keiser  *   |  |       USER        |<--->|       USER        |...|       USER        |
473b13a1efSThomas Keiser  *   |  +-------------------+     +-------------------+   +-------------------+
48da6c28aaSamw  *   |
49da6c28aaSamw  *   |
50da6c28aaSamw  *   v
51da6c28aaSamw  * +-------------------+       +-------------------+      +-------------------+
52da6c28aaSamw  * |       TREE        |<----->|       TREE        |......|       TREE        |
53da6c28aaSamw  * +-------------------+       +-------------------+      +-------------------+
54da6c28aaSamw  *      |         |
55da6c28aaSamw  *      |         |
56da6c28aaSamw  *      |         v
57da6c28aaSamw  *      |     +-------+       +-------+      +-------+
58da6c28aaSamw  *      |     | OFILE |<----->| OFILE |......| OFILE |
59da6c28aaSamw  *      |     +-------+       +-------+      +-------+
60da6c28aaSamw  *      |
61da6c28aaSamw  *      |
62da6c28aaSamw  *      v
63da6c28aaSamw  *  +-------+       +------+      +------+
64da6c28aaSamw  *  | ODIR  |<----->| ODIR |......| ODIR |
65da6c28aaSamw  *  +-------+       +------+      +------+
66da6c28aaSamw  *
67da6c28aaSamw  *
68da6c28aaSamw  * User State Machine
69da6c28aaSamw  * ------------------
70da6c28aaSamw  *
71*12b65585SGordon Ross  *
72*12b65585SGordon Ross  *		    | T0:  Creation/Allocation
73*12b65585SGordon Ross  *		    |	   (1st session setup)
74*12b65585SGordon Ross  *		    v
75*12b65585SGordon Ross  *    +-----------------------------+
76*12b65585SGordon Ross  *    |  SMB_USER_STATE_LOGGING_ON  |<----------+
77*12b65585SGordon Ross  *    +-----------------------------+	 addl. session setup
78*12b65585SGordon Ross  *		    |		|	(more proc. required)
79*12b65585SGordon Ross  *		    | T2	|		^
80*12b65585SGordon Ross  *		    |		|		| T1: (cont.)
81*12b65585SGordon Ross  *		    |		+------->-------?
82*12b65585SGordon Ross  *		    v				| T3: (fail)
83*12b65585SGordon Ross  *    +-----------------------------+		v
84*12b65585SGordon Ross  *    |  SMB_USER_STATE_LOGGED_ON   |	    (logged off)
85da6c28aaSamw  *    +-----------------------------+
86da6c28aaSamw  *		    |
87*12b65585SGordon Ross  *		    | T4
88da6c28aaSamw  *		    |
89da6c28aaSamw  *		    v
90da6c28aaSamw  *    +-----------------------------+
91da6c28aaSamw  *    |  SMB_USER_STATE_LOGGING_OFF |
92da6c28aaSamw  *    +-----------------------------+
93da6c28aaSamw  *		    |
94*12b65585SGordon Ross  *		    | T5
95da6c28aaSamw  *		    |
96da6c28aaSamw  *		    v
97*12b65585SGordon Ross  *    +-----------------------------+    T6
98da6c28aaSamw  *    |  SMB_USER_STATE_LOGGED_OFF  |----------> Deletion/Free
99da6c28aaSamw  *    +-----------------------------+
100da6c28aaSamw  *
101*12b65585SGordon Ross  * SMB_USER_STATE_LOGGING_ON
102da6c28aaSamw  *
103da6c28aaSamw  *    While in this state:
104*12b65585SGordon Ross  *      - The user is in the list of users for his session.
105*12b65585SGordon Ross  *      - References will be given out ONLY for session setup.
106*12b65585SGordon Ross  *      - This user can not access anything yet.
107*12b65585SGordon Ross  *
108*12b65585SGordon Ross  * SMB_USER_STATE_LOGGED_ON
109*12b65585SGordon Ross  *
110*12b65585SGordon Ross  *    While in this state:
111*12b65585SGordon Ross  *      - The user is in the list of users for his session.
112da6c28aaSamw  *      - References will be given out if the user is looked up.
113da6c28aaSamw  *      - The user can access files and pipes.
114da6c28aaSamw  *
115da6c28aaSamw  * SMB_USER_STATE_LOGGING_OFF
116da6c28aaSamw  *
117da6c28aaSamw  *    While in this state:
118*12b65585SGordon Ross  *      - The user is in the list of users for his session.
119da6c28aaSamw  *      - References will not be given out if the user is looked up.
120da6c28aaSamw  *      - The trees the user connected are being disconnected.
121da6c28aaSamw  *      - The resources associated with the user remain.
122da6c28aaSamw  *
123*12b65585SGordon Ross  * SMB_USER_STATE_LOGGED_OFF
124da6c28aaSamw  *
125da6c28aaSamw  *    While in this state:
126da6c28aaSamw  *      - The user is queued in the list of users of his session.
127da6c28aaSamw  *      - References will not be given out if the user is looked up.
128da6c28aaSamw  *      - The user has no more trees connected.
129da6c28aaSamw  *      - The resources associated with the user remain.
130da6c28aaSamw  *
131da6c28aaSamw  * Transition T0
132da6c28aaSamw  *
133*12b65585SGordon Ross  *    First request in an SMB Session Setup sequence creates a
134*12b65585SGordon Ross  *    new user object and adds it to the list of users for
135*12b65585SGordon Ross  *    this session.  User UID is assigned and returned.
136da6c28aaSamw  *
137da6c28aaSamw  * Transition T1
138da6c28aaSamw  *
139*12b65585SGordon Ross  *    Subsequent SMB Session Setup requests (on the same UID
140*12b65585SGordon Ross  *    assigned in T0) update the state of this user object,
141*12b65585SGordon Ross  *    communicating with smbd for the crypto work.
142da6c28aaSamw  *
143da6c28aaSamw  * Transition T2
144da6c28aaSamw  *
145*12b65585SGordon Ross  *    If the SMB Session Setup sequence is successful, T2
146*12b65585SGordon Ross  *    makes the new user object available for requests.
147*12b65585SGordon Ross  *
148*12b65585SGordon Ross  * Transition T3
149*12b65585SGordon Ross  *
150*12b65585SGordon Ross  *    If an Session Setup request gets an error other than
151*12b65585SGordon Ross  *    the expected "more processing required", then T3
152*12b65585SGordon Ross  *    leads to state "LOGGED_OFF" and then tear-down of the
153*12b65585SGordon Ross  *    partially constructed user.
154*12b65585SGordon Ross  *
155*12b65585SGordon Ross  * Transition T4
156*12b65585SGordon Ross  *
157*12b65585SGordon Ross  *    Normal SMB User Logoff request, or session tear-down.
158*12b65585SGordon Ross  *
159*12b65585SGordon Ross  * Transition T5
160*12b65585SGordon Ross  *
161da6c28aaSamw  *    This transition occurs in smb_user_release(). The resources associated
162da6c28aaSamw  *    with the user are deleted as well as the user. For the transition to
163da6c28aaSamw  *    occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the
164da6c28aaSamw  *    reference count be zero.
165da6c28aaSamw  *
166da6c28aaSamw  * Comments
167da6c28aaSamw  * --------
168da6c28aaSamw  *
169da6c28aaSamw  *    The state machine of the user structures is controlled by 3 elements:
170da6c28aaSamw  *      - The list of users of the session he belongs to.
171da6c28aaSamw  *      - The mutex embedded in the structure itself.
172da6c28aaSamw  *      - The reference count.
173da6c28aaSamw  *
174da6c28aaSamw  *    There's a mutex embedded in the user structure used to protect its fields
175da6c28aaSamw  *    and there's a lock embedded in the list of users of a session. To
176da6c28aaSamw  *    increment or to decrement the reference count the mutex must be entered.
177da6c28aaSamw  *    To insert the user into the list of users of the session and to remove
178da6c28aaSamw  *    the user from it, the lock must be entered in RW_WRITER mode.
179da6c28aaSamw  *
180da6c28aaSamw  *    Rules of access to a user structure:
181da6c28aaSamw  *
182da6c28aaSamw  *    1) In order to avoid deadlocks, when both (mutex and lock of the session
183da6c28aaSamw  *       list) have to be entered, the lock must be entered first.
184da6c28aaSamw  *
185da6c28aaSamw  *    2) All actions applied to a user require a reference count.
186da6c28aaSamw  *
187da6c28aaSamw  *    3) There are 2 ways of getting a reference count. One is when the user
1889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *       logs in. The other when the user is looked up.
189da6c28aaSamw  *
190da6c28aaSamw  *    It should be noted that the reference count of a user registers the
191da6c28aaSamw  *    number of references to the user in other structures (such as an smb
192da6c28aaSamw  *    request). The reference count is not incremented in these 2 instances:
193da6c28aaSamw  *
194da6c28aaSamw  *    1) The user is logged in. An user is anchored by his state. If there's
195da6c28aaSamw  *       no activity involving a user currently logged in, the reference
196da6c28aaSamw  *       count of that user is zero.
197da6c28aaSamw  *
198da6c28aaSamw  *    2) The user is queued in the list of users of the session. The fact of
199da6c28aaSamw  *       being queued in that list is NOT registered by incrementing the
200da6c28aaSamw  *       reference count.
201da6c28aaSamw  */
202148c5f43SAlan Wright #include <sys/types.h>
203148c5f43SAlan Wright #include <sys/sid.h>
204148c5f43SAlan Wright #include <sys/priv_names.h>
205bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
2069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h>
207da6c28aaSamw 
208c8ec8eeaSjose borrego #define	ADMINISTRATORS_SID	"S-1-5-32-544"
209c8ec8eeaSjose borrego 
2101fcced4cSJordan Brown static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
2118622ec45SGordon Ross static void smb_user_auth_logoff(smb_user_t *);
212c8ec8eeaSjose borrego 
213b819cea2SGordon Ross 
214da6c28aaSamw /*
215148c5f43SAlan Wright  * Create a new user.
216da6c28aaSamw  */
217da6c28aaSamw smb_user_t *
218*12b65585SGordon Ross smb_user_new(smb_session_t *session)
219*12b65585SGordon Ross {
220*12b65585SGordon Ross 	smb_user_t	*user;
221*12b65585SGordon Ross 
222*12b65585SGordon Ross 	ASSERT(session);
223*12b65585SGordon Ross 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
224*12b65585SGordon Ross 
225*12b65585SGordon Ross 	user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
226*12b65585SGordon Ross 	bzero(user, sizeof (smb_user_t));
227*12b65585SGordon Ross 
228*12b65585SGordon Ross 	user->u_refcnt = 1;
229*12b65585SGordon Ross 	user->u_session = session;
230*12b65585SGordon Ross 	user->u_server = session->s_server;
231*12b65585SGordon Ross 	user->u_logon_time = gethrestime_sec();
232*12b65585SGordon Ross 
233*12b65585SGordon Ross 	if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
234*12b65585SGordon Ross 		goto errout;
235*12b65585SGordon Ross 
236*12b65585SGordon Ross 	mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
237*12b65585SGordon Ross 	user->u_state = SMB_USER_STATE_LOGGING_ON;
238*12b65585SGordon Ross 	user->u_magic = SMB_USER_MAGIC;
239*12b65585SGordon Ross 
240*12b65585SGordon Ross 	smb_llist_enter(&session->s_user_list, RW_WRITER);
241*12b65585SGordon Ross 	smb_llist_insert_tail(&session->s_user_list, user);
242*12b65585SGordon Ross 	smb_llist_exit(&session->s_user_list);
243*12b65585SGordon Ross 	smb_server_inc_users(session->s_server);
244*12b65585SGordon Ross 
245*12b65585SGordon Ross 	return (user);
246*12b65585SGordon Ross 
247*12b65585SGordon Ross errout:
248*12b65585SGordon Ross 	if (user->u_uid != 0)
249*12b65585SGordon Ross 		smb_idpool_free(&session->s_uid_pool, user->u_uid);
250*12b65585SGordon Ross 	kmem_cache_free(smb_cache_user, user);
251*12b65585SGordon Ross 	return (NULL);
252*12b65585SGordon Ross }
253*12b65585SGordon Ross 
254*12b65585SGordon Ross /*
255*12b65585SGordon Ross  * Fill in the details of a user, meaning a transition
256*12b65585SGordon Ross  * from state LOGGING_ON to state LOGGED_ON.
257*12b65585SGordon Ross  */
258*12b65585SGordon Ross int
259*12b65585SGordon Ross smb_user_logon(
260*12b65585SGordon Ross     smb_user_t		*user,
261da6c28aaSamw     cred_t		*cr,
262da6c28aaSamw     char		*domain_name,
263da6c28aaSamw     char		*account_name,
264da6c28aaSamw     uint32_t		flags,
265da6c28aaSamw     uint32_t		privileges,
266da6c28aaSamw     uint32_t		audit_sid)
267da6c28aaSamw {
268da6c28aaSamw 
269*12b65585SGordon Ross 	ASSERT(user->u_magic == SMB_USER_MAGIC);
270da6c28aaSamw 	ASSERT(cr);
271da6c28aaSamw 	ASSERT(account_name);
272da6c28aaSamw 	ASSERT(domain_name);
273da6c28aaSamw 
274*12b65585SGordon Ross 	mutex_enter(&user->u_mutex);
275*12b65585SGordon Ross 
276*12b65585SGordon Ross 	if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
277*12b65585SGordon Ross 		mutex_exit(&user->u_mutex);
278*12b65585SGordon Ross 		return (-1);
279*12b65585SGordon Ross 	}
280*12b65585SGordon Ross 
281*12b65585SGordon Ross 	smb_authsock_close(user);
282*12b65585SGordon Ross 
283*12b65585SGordon Ross 	user->u_state = SMB_USER_STATE_LOGGED_ON;
284da6c28aaSamw 	user->u_flags = flags;
285da6c28aaSamw 	user->u_name_len = strlen(account_name) + 1;
286da6c28aaSamw 	user->u_domain_len = strlen(domain_name) + 1;
2879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	user->u_name = smb_mem_strdup(account_name);
2889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	user->u_domain = smb_mem_strdup(domain_name);
289da6c28aaSamw 	user->u_audit_sid = audit_sid;
290da6c28aaSamw 
291148c5f43SAlan Wright 	smb_user_setcred(user, cr, privileges);
292da6c28aaSamw 
293*12b65585SGordon Ross 	mutex_exit(&user->u_mutex);
294da6c28aaSamw 
295*12b65585SGordon Ross 	return (0);
296da6c28aaSamw }
297da6c28aaSamw 
298da6c28aaSamw /*
299da6c28aaSamw  * smb_user_logoff
300da6c28aaSamw  *
3011fcced4cSJordan Brown  * Change the user state and disconnect trees.
3021fcced4cSJordan Brown  * The user list must not be entered or modified here.
303da6c28aaSamw  */
304da6c28aaSamw void
305da6c28aaSamw smb_user_logoff(
306da6c28aaSamw     smb_user_t		*user)
307da6c28aaSamw {
308da6c28aaSamw 	ASSERT(user->u_magic == SMB_USER_MAGIC);
309da6c28aaSamw 
310da6c28aaSamw 	mutex_enter(&user->u_mutex);
311da6c28aaSamw 	ASSERT(user->u_refcnt);
312da6c28aaSamw 	switch (user->u_state) {
313*12b65585SGordon Ross 	case SMB_USER_STATE_LOGGING_ON: {
314*12b65585SGordon Ross 		smb_authsock_close(user);
315*12b65585SGordon Ross 		user->u_state = SMB_USER_STATE_LOGGED_OFF;
316*12b65585SGordon Ross 		smb_server_dec_users(user->u_server);
317*12b65585SGordon Ross 		break;
318*12b65585SGordon Ross 	}
319*12b65585SGordon Ross 
320*12b65585SGordon Ross 	case SMB_USER_STATE_LOGGED_ON: {
321da6c28aaSamw 		/*
322da6c28aaSamw 		 * The user is moved into a state indicating that the log off
323da6c28aaSamw 		 * process has started.
324da6c28aaSamw 		 */
325da6c28aaSamw 		user->u_state = SMB_USER_STATE_LOGGING_OFF;
326da6c28aaSamw 		mutex_exit(&user->u_mutex);
3273b13a1efSThomas Keiser 		smb_session_disconnect_owned_trees(user->u_session, user);
3288622ec45SGordon Ross 		smb_user_auth_logoff(user);
329da6c28aaSamw 		mutex_enter(&user->u_mutex);
330da6c28aaSamw 		user->u_state = SMB_USER_STATE_LOGGED_OFF;
331148c5f43SAlan Wright 		smb_server_dec_users(user->u_server);
332da6c28aaSamw 		break;
333da6c28aaSamw 	}
334da6c28aaSamw 	case SMB_USER_STATE_LOGGED_OFF:
335da6c28aaSamw 	case SMB_USER_STATE_LOGGING_OFF:
336da6c28aaSamw 		break;
337da6c28aaSamw 
338da6c28aaSamw 	default:
339da6c28aaSamw 		ASSERT(0);
340da6c28aaSamw 		break;
341da6c28aaSamw 	}
342da6c28aaSamw 	mutex_exit(&user->u_mutex);
343da6c28aaSamw }
344da6c28aaSamw 
345da6c28aaSamw /*
3463b13a1efSThomas Keiser  * Take a reference on a user.  Do not return a reference unless the user is in
3473b13a1efSThomas Keiser  * the logged-in state.
3481fcced4cSJordan Brown  */
3491fcced4cSJordan Brown boolean_t
3501fcced4cSJordan Brown smb_user_hold(smb_user_t *user)
3511fcced4cSJordan Brown {
3523b13a1efSThomas Keiser 	SMB_USER_VALID(user);
3531fcced4cSJordan Brown 
3541fcced4cSJordan Brown 	mutex_enter(&user->u_mutex);
3551fcced4cSJordan Brown 
356*12b65585SGordon Ross 	if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
3571fcced4cSJordan Brown 		user->u_refcnt++;
3581fcced4cSJordan Brown 		mutex_exit(&user->u_mutex);
3591fcced4cSJordan Brown 		return (B_TRUE);
3601fcced4cSJordan Brown 	}
3611fcced4cSJordan Brown 
3621fcced4cSJordan Brown 	mutex_exit(&user->u_mutex);
3631fcced4cSJordan Brown 	return (B_FALSE);
3641fcced4cSJordan Brown }
3651fcced4cSJordan Brown 
3661fcced4cSJordan Brown /*
3673b13a1efSThomas Keiser  * Unconditionally take a reference on a user.
3683b13a1efSThomas Keiser  */
3693b13a1efSThomas Keiser void
3703b13a1efSThomas Keiser smb_user_hold_internal(smb_user_t *user)
3713b13a1efSThomas Keiser {
3723b13a1efSThomas Keiser 	SMB_USER_VALID(user);
3733b13a1efSThomas Keiser 
3743b13a1efSThomas Keiser 	mutex_enter(&user->u_mutex);
3753b13a1efSThomas Keiser 	user->u_refcnt++;
3763b13a1efSThomas Keiser 	mutex_exit(&user->u_mutex);
3773b13a1efSThomas Keiser }
3783b13a1efSThomas Keiser 
3793b13a1efSThomas Keiser /*
3809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Release a reference on a user.  If the reference count falls to
3819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * zero and the user has logged off, post the object for deletion.
3829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Object deletion is deferred to avoid modifying a list while an
3839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * iteration may be in progress.
384da6c28aaSamw  */
385da6c28aaSamw void
386da6c28aaSamw smb_user_release(
387da6c28aaSamw     smb_user_t		*user)
388da6c28aaSamw {
389da6c28aaSamw 	ASSERT(user->u_magic == SMB_USER_MAGIC);
390da6c28aaSamw 
391da6c28aaSamw 	mutex_enter(&user->u_mutex);
392da6c28aaSamw 	ASSERT(user->u_refcnt);
393da6c28aaSamw 	user->u_refcnt--;
394c5866007SKeyur Desai 
395da6c28aaSamw 	switch (user->u_state) {
396da6c28aaSamw 	case SMB_USER_STATE_LOGGED_OFF:
3979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (user->u_refcnt == 0)
3989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_session_post_user(user->u_session, user);
399da6c28aaSamw 		break;
400da6c28aaSamw 
401*12b65585SGordon Ross 	case SMB_USER_STATE_LOGGING_ON:
402*12b65585SGordon Ross 	case SMB_USER_STATE_LOGGED_ON:
403da6c28aaSamw 	case SMB_USER_STATE_LOGGING_OFF:
404da6c28aaSamw 		break;
405da6c28aaSamw 
406da6c28aaSamw 	default:
407da6c28aaSamw 		ASSERT(0);
408da6c28aaSamw 		break;
409da6c28aaSamw 	}
410da6c28aaSamw 	mutex_exit(&user->u_mutex);
411da6c28aaSamw }
412da6c28aaSamw 
4131fcced4cSJordan Brown /*
414c8ec8eeaSjose borrego  * Determine whether or not the user is an administrator.
415c8ec8eeaSjose borrego  * Members of the administrators group have administrative rights.
416c8ec8eeaSjose borrego  */
417c8ec8eeaSjose borrego boolean_t
418148c5f43SAlan Wright smb_user_is_admin(smb_user_t *user)
419c8ec8eeaSjose borrego {
420b819cea2SGordon Ross #ifdef	_KERNEL
421148c5f43SAlan Wright 	char		sidstr[SMB_SID_STRSZ];
422148c5f43SAlan Wright 	ksidlist_t	*ksidlist;
423148c5f43SAlan Wright 	ksid_t		ksid1;
424148c5f43SAlan Wright 	ksid_t		*ksid2;
425148c5f43SAlan Wright 	int		i;
426b819cea2SGordon Ross #endif	/* _KERNEL */
427b819cea2SGordon Ross 	boolean_t	rc = B_FALSE;
428c8ec8eeaSjose borrego 
429c8ec8eeaSjose borrego 	ASSERT(user);
430148c5f43SAlan Wright 	ASSERT(user->u_cred);
431c8ec8eeaSjose borrego 
432148c5f43SAlan Wright 	if (SMB_USER_IS_ADMIN(user))
433c8ec8eeaSjose borrego 		return (B_TRUE);
434c8ec8eeaSjose borrego 
435b819cea2SGordon Ross #ifdef	_KERNEL
436148c5f43SAlan Wright 	bzero(&ksid1, sizeof (ksid_t));
437148c5f43SAlan Wright 	(void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ);
438148c5f43SAlan Wright 	ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0);
439148c5f43SAlan Wright 	ksid1.ks_domain = ksid_lookupdomain(sidstr);
440148c5f43SAlan Wright 
441148c5f43SAlan Wright 	ksidlist = crgetsidlist(user->u_cred);
442148c5f43SAlan Wright 	ASSERT(ksidlist);
443148c5f43SAlan Wright 	ASSERT(ksid1.ks_domain);
444148c5f43SAlan Wright 	ASSERT(ksid1.ks_domain->kd_name);
445148c5f43SAlan Wright 
446148c5f43SAlan Wright 	i = 0;
447148c5f43SAlan Wright 	ksid2 = crgetsid(user->u_cred, KSID_USER);
448148c5f43SAlan Wright 	do {
449148c5f43SAlan Wright 		ASSERT(ksid2->ks_domain);
450148c5f43SAlan Wright 		ASSERT(ksid2->ks_domain->kd_name);
451148c5f43SAlan Wright 
452148c5f43SAlan Wright 		if (strcmp(ksid1.ks_domain->kd_name,
453148c5f43SAlan Wright 		    ksid2->ks_domain->kd_name) == 0 &&
454148c5f43SAlan Wright 		    ksid1.ks_rid == ksid2->ks_rid) {
455148c5f43SAlan Wright 			user->u_flags |= SMB_USER_FLAG_ADMIN;
456148c5f43SAlan Wright 			rc = B_TRUE;
457148c5f43SAlan Wright 			break;
458148c5f43SAlan Wright 		}
459148c5f43SAlan Wright 
460148c5f43SAlan Wright 		ksid2 = &ksidlist->ksl_sids[i];
461148c5f43SAlan Wright 	} while (i++ < ksidlist->ksl_nsid);
462148c5f43SAlan Wright 
463148c5f43SAlan Wright 	ksid_rele(&ksid1);
464b819cea2SGordon Ross #endif	/* _KERNEL */
465148c5f43SAlan Wright 	return (rc);
466c8ec8eeaSjose borrego }
467c8ec8eeaSjose borrego 
4681fcced4cSJordan Brown /*
4691fcced4cSJordan Brown  * This function should be called with a hold on the user.
4701fcced4cSJordan Brown  */
4711fcced4cSJordan Brown boolean_t
4721fcced4cSJordan Brown smb_user_namecmp(smb_user_t *user, const char *name)
4731fcced4cSJordan Brown {
4741fcced4cSJordan Brown 	char		*fq_name;
4751fcced4cSJordan Brown 	boolean_t	match;
4761fcced4cSJordan Brown 
477bbf6f00cSJordan Brown 	if (smb_strcasecmp(name, user->u_name, 0) == 0)
4781fcced4cSJordan Brown 		return (B_TRUE);
4791fcced4cSJordan Brown 
4801fcced4cSJordan Brown 	fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
4811fcced4cSJordan Brown 
4821fcced4cSJordan Brown 	(void) snprintf(fq_name, MAXNAMELEN, "%s\\%s",
4831fcced4cSJordan Brown 	    user->u_domain, user->u_name);
4841fcced4cSJordan Brown 
485bbf6f00cSJordan Brown 	match = (smb_strcasecmp(name, fq_name, 0) == 0);
4861fcced4cSJordan Brown 	if (!match) {
4871fcced4cSJordan Brown 		(void) snprintf(fq_name, MAXNAMELEN, "%s@%s",
4881fcced4cSJordan Brown 		    user->u_name, user->u_domain);
4891fcced4cSJordan Brown 
490bbf6f00cSJordan Brown 		match = (smb_strcasecmp(name, fq_name, 0) == 0);
4911fcced4cSJordan Brown 	}
4921fcced4cSJordan Brown 
4931fcced4cSJordan Brown 	kmem_free(fq_name, MAXNAMELEN);
4941fcced4cSJordan Brown 	return (match);
4951fcced4cSJordan Brown }
4961fcced4cSJordan Brown 
4971fcced4cSJordan Brown /*
4981fcced4cSJordan Brown  * If the enumeration request is for user data, handle the request
4991fcced4cSJordan Brown  * here.  Otherwise, pass it on to the trees.
5001fcced4cSJordan Brown  *
5011fcced4cSJordan Brown  * This function should be called with a hold on the user.
5021fcced4cSJordan Brown  */
5031fcced4cSJordan Brown int
5041fcced4cSJordan Brown smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
5051fcced4cSJordan Brown {
5063b13a1efSThomas Keiser 	int		rc = 0;
5071fcced4cSJordan Brown 
5081fcced4cSJordan Brown 	ASSERT(user);
5091fcced4cSJordan Brown 	ASSERT(user->u_magic == SMB_USER_MAGIC);
5101fcced4cSJordan Brown 
5111fcced4cSJordan Brown 	if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
5121fcced4cSJordan Brown 		return (smb_user_enum_private(user, svcenum));
5131fcced4cSJordan Brown 
5141fcced4cSJordan Brown 	return (rc);
5151fcced4cSJordan Brown }
5161fcced4cSJordan Brown 
517da6c28aaSamw /* *************************** Static Functions ***************************** */
518da6c28aaSamw 
519da6c28aaSamw /*
5209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Delete a user.  The tree list should be empty.
5219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
5229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Remove the user from the session's user list before freeing resources
5239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * associated with the user.
524da6c28aaSamw  */
5259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
5269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_delete(void *arg)
527da6c28aaSamw {
528da6c28aaSamw 	smb_session_t	*session;
5299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_user_t	*user = (smb_user_t *)arg;
530da6c28aaSamw 
5319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_USER_VALID(user);
532da6c28aaSamw 	ASSERT(user->u_refcnt == 0);
533da6c28aaSamw 	ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
534*12b65585SGordon Ross 	ASSERT(user->u_authsock == NULL);
535da6c28aaSamw 
536da6c28aaSamw 	session = user->u_session;
537da6c28aaSamw 	smb_llist_enter(&session->s_user_list, RW_WRITER);
538da6c28aaSamw 	smb_llist_remove(&session->s_user_list, user);
5399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_idpool_free(&session->s_uid_pool, user->u_uid);
540da6c28aaSamw 	smb_llist_exit(&session->s_user_list);
541da6c28aaSamw 
5429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&user->u_mutex);
5439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&user->u_mutex);
5449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
545da6c28aaSamw 	user->u_magic = (uint32_t)~SMB_USER_MAGIC;
546da6c28aaSamw 	mutex_destroy(&user->u_mutex);
547148c5f43SAlan Wright 	if (user->u_cred)
548da6c28aaSamw 		crfree(user->u_cred);
549b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (user->u_privcred)
550b89a8333Snatalie li - Sun Microsystems - Irvine United States 		crfree(user->u_privcred);
5519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_mem_free(user->u_name);
5529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_mem_free(user->u_domain);
5538622ec45SGordon Ross 	kmem_cache_free(smb_cache_user, user);
554da6c28aaSamw }
555c8ec8eeaSjose borrego 
556b89a8333Snatalie li - Sun Microsystems - Irvine United States cred_t *
557b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_getcred(smb_user_t *user)
558b89a8333Snatalie li - Sun Microsystems - Irvine United States {
559b89a8333Snatalie li - Sun Microsystems - Irvine United States 	return (user->u_cred);
560b89a8333Snatalie li - Sun Microsystems - Irvine United States }
561b89a8333Snatalie li - Sun Microsystems - Irvine United States 
562b89a8333Snatalie li - Sun Microsystems - Irvine United States cred_t *
563b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_getprivcred(smb_user_t *user)
564b89a8333Snatalie li - Sun Microsystems - Irvine United States {
565b89a8333Snatalie li - Sun Microsystems - Irvine United States 	return ((user->u_privcred)? user->u_privcred : user->u_cred);
566b89a8333Snatalie li - Sun Microsystems - Irvine United States }
5671fcced4cSJordan Brown 
568b819cea2SGordon Ross #ifdef	_KERNEL
5691fcced4cSJordan Brown /*
570148c5f43SAlan Wright  * Assign the user cred and privileges.
571148c5f43SAlan Wright  *
572148c5f43SAlan Wright  * If the user has backup and/or restore privleges, dup the cred
573148c5f43SAlan Wright  * and add those privileges to this new privileged cred.
574148c5f43SAlan Wright  */
575b819cea2SGordon Ross void
576148c5f43SAlan Wright smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
577148c5f43SAlan Wright {
578148c5f43SAlan Wright 	cred_t *privcred = NULL;
579148c5f43SAlan Wright 
580148c5f43SAlan Wright 	ASSERT(cr);
581148c5f43SAlan Wright 	crhold(cr);
582148c5f43SAlan Wright 
583148c5f43SAlan Wright 	if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
584148c5f43SAlan Wright 		privcred = crdup(cr);
585148c5f43SAlan Wright 
586148c5f43SAlan Wright 	if (privcred != NULL) {
587148c5f43SAlan Wright 		if (privileges & SMB_USER_PRIV_BACKUP) {
588148c5f43SAlan Wright 			(void) crsetpriv(privcred, PRIV_FILE_DAC_READ,
589148c5f43SAlan Wright 			    PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
590148c5f43SAlan Wright 		}
591148c5f43SAlan Wright 
592148c5f43SAlan Wright 		if (privileges & SMB_USER_PRIV_RESTORE) {
593148c5f43SAlan Wright 			(void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE,
594148c5f43SAlan Wright 			    PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
595148c5f43SAlan Wright 			    PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
596148c5f43SAlan Wright 			    PRIV_FILE_OWNER, PRIV_FILE_SETID,
597148c5f43SAlan Wright 			    PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL);
598148c5f43SAlan Wright 		}
599148c5f43SAlan Wright 	}
600148c5f43SAlan Wright 
601148c5f43SAlan Wright 	user->u_cred = cr;
602148c5f43SAlan Wright 	user->u_privcred = privcred;
603148c5f43SAlan Wright 	user->u_privileges = privileges;
604148c5f43SAlan Wright }
605b819cea2SGordon Ross #endif	/* _KERNEL */
606148c5f43SAlan Wright 
607148c5f43SAlan Wright /*
6081fcced4cSJordan Brown  * Private function to support smb_user_enum.
6091fcced4cSJordan Brown  */
6101fcced4cSJordan Brown static int
6111fcced4cSJordan Brown smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum)
6121fcced4cSJordan Brown {
6131fcced4cSJordan Brown 	uint8_t *pb;
6141fcced4cSJordan Brown 	uint_t nbytes;
6151fcced4cSJordan Brown 	int rc;
6161fcced4cSJordan Brown 
6171fcced4cSJordan Brown 	if (svcenum->se_nskip > 0) {
6181fcced4cSJordan Brown 		svcenum->se_nskip--;
6191fcced4cSJordan Brown 		return (0);
6201fcced4cSJordan Brown 	}
6211fcced4cSJordan Brown 
6221fcced4cSJordan Brown 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
6231fcced4cSJordan Brown 		svcenum->se_nitems = svcenum->se_nlimit;
6241fcced4cSJordan Brown 		return (0);
6251fcced4cSJordan Brown 	}
6261fcced4cSJordan Brown 
6271fcced4cSJordan Brown 	pb = &svcenum->se_buf[svcenum->se_bused];
6281fcced4cSJordan Brown 	rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes);
6291fcced4cSJordan Brown 	if (rc == 0) {
6301fcced4cSJordan Brown 		svcenum->se_bavail -= nbytes;
6311fcced4cSJordan Brown 		svcenum->se_bused += nbytes;
6321fcced4cSJordan Brown 		svcenum->se_nitems++;
6331fcced4cSJordan Brown 	}
6341fcced4cSJordan Brown 
6351fcced4cSJordan Brown 	return (rc);
6361fcced4cSJordan Brown }
6371fcced4cSJordan Brown 
6381fcced4cSJordan Brown /*
6391fcced4cSJordan Brown  * Encode the NetInfo for a user into a buffer.  NetInfo contains
6401fcced4cSJordan Brown  * information that is often needed in user space to support RPC
6411fcced4cSJordan Brown  * requests.
6421fcced4cSJordan Brown  */
6431fcced4cSJordan Brown int
6441fcced4cSJordan Brown smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen,
6451fcced4cSJordan Brown     uint32_t *nbytes)
6461fcced4cSJordan Brown {
6471fcced4cSJordan Brown 	smb_netuserinfo_t	info;
6481fcced4cSJordan Brown 	int			rc;
6491fcced4cSJordan Brown 
6501fcced4cSJordan Brown 	smb_user_netinfo_init(user, &info);
6511fcced4cSJordan Brown 	rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes);
6521fcced4cSJordan Brown 	smb_user_netinfo_fini(&info);
6531fcced4cSJordan Brown 
6541fcced4cSJordan Brown 	return (rc);
6551fcced4cSJordan Brown }
6561fcced4cSJordan Brown 
6571fcced4cSJordan Brown void
6581fcced4cSJordan Brown smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
6591fcced4cSJordan Brown {
6601fcced4cSJordan Brown 	smb_session_t	*session;
6611fcced4cSJordan Brown 	char		*buf;
6621fcced4cSJordan Brown 
6631fcced4cSJordan Brown 	ASSERT(user);
6641fcced4cSJordan Brown 	ASSERT(user->u_domain);
6651fcced4cSJordan Brown 	ASSERT(user->u_name);
6661fcced4cSJordan Brown 
6671fcced4cSJordan Brown 	session = user->u_session;
6681fcced4cSJordan Brown 	ASSERT(session);
6691fcced4cSJordan Brown 	ASSERT(session->workstation);
6701fcced4cSJordan Brown 
6711fcced4cSJordan Brown 	info->ui_session_id = session->s_kid;
6721fcced4cSJordan Brown 	info->ui_native_os = session->native_os;
6731fcced4cSJordan Brown 	info->ui_ipaddr = session->ipaddr;
6741fcced4cSJordan Brown 	info->ui_numopens = session->s_file_cnt;
675c5866007SKeyur Desai 	info->ui_smb_uid = user->u_uid;
6761fcced4cSJordan Brown 	info->ui_logon_time = user->u_logon_time;
6771fcced4cSJordan Brown 	info->ui_flags = user->u_flags;
678c5866007SKeyur Desai 	info->ui_posix_uid = crgetuid(user->u_cred);
6791fcced4cSJordan Brown 
6801fcced4cSJordan Brown 	info->ui_domain_len = user->u_domain_len;
6819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	info->ui_domain = smb_mem_strdup(user->u_domain);
6821fcced4cSJordan Brown 
6831fcced4cSJordan Brown 	info->ui_account_len = user->u_name_len;
6849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	info->ui_account = smb_mem_strdup(user->u_name);
6851fcced4cSJordan Brown 
6861fcced4cSJordan Brown 	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
6871fcced4cSJordan Brown 	smb_session_getclient(session, buf, MAXNAMELEN);
6881fcced4cSJordan Brown 	info->ui_workstation_len = strlen(buf) + 1;
6899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	info->ui_workstation = smb_mem_strdup(buf);
6901fcced4cSJordan Brown 	kmem_free(buf, MAXNAMELEN);
6911fcced4cSJordan Brown }
6921fcced4cSJordan Brown 
6931fcced4cSJordan Brown void
6941fcced4cSJordan Brown smb_user_netinfo_fini(smb_netuserinfo_t *info)
6951fcced4cSJordan Brown {
6961fcced4cSJordan Brown 	if (info == NULL)
6971fcced4cSJordan Brown 		return;
6981fcced4cSJordan Brown 
6991fcced4cSJordan Brown 	if (info->ui_domain)
7009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_mem_free(info->ui_domain);
7011fcced4cSJordan Brown 	if (info->ui_account)
7029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_mem_free(info->ui_account);
7031fcced4cSJordan Brown 	if (info->ui_workstation)
7049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_mem_free(info->ui_workstation);
7051fcced4cSJordan Brown 
7061fcced4cSJordan Brown 	bzero(info, sizeof (smb_netuserinfo_t));
7071fcced4cSJordan Brown }
7089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
7108622ec45SGordon Ross smb_user_auth_logoff(smb_user_t *user)
7119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7128622ec45SGordon Ross 	uint32_t audit_sid = user->u_audit_sid;
7138622ec45SGordon Ross 
7148622ec45SGordon Ross 	(void) smb_kdoor_upcall(user->u_server, SMB_DR_USER_AUTH_LOGOFF,
7159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    &audit_sid, xdr_uint32_t, NULL, NULL);
7169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
717