xref: /titanic_41/usr/src/uts/common/fs/smbsrv/smb_user.c (revision 7206bf49b1fe641544165ee97f63856da95e0868)
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*7206bf49SGordon Ross  * Copyright 2013 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  * +-------------------+       +-------------------+      +-------------------+
42d040dae9SThomas Keiser  *   |          |
43d040dae9SThomas Keiser  *   |          |
44d040dae9SThomas Keiser  *   |          v
45d040dae9SThomas Keiser  *   |  +-------------------+     +-------------------+   +-------------------+
46d040dae9SThomas Keiser  *   |  |       USER        |<--->|       USER        |...|       USER        |
47d040dae9SThomas 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  *
71da6c28aaSamw  *    +-----------------------------+	 T0
72da6c28aaSamw  *    |  SMB_USER_STATE_LOGGED_IN   |<----------- Creation/Allocation
73da6c28aaSamw  *    +-----------------------------+
74da6c28aaSamw  *		    |
75da6c28aaSamw  *		    | T1
76da6c28aaSamw  *		    |
77da6c28aaSamw  *		    v
78da6c28aaSamw  *    +-----------------------------+
79da6c28aaSamw  *    |  SMB_USER_STATE_LOGGING_OFF |
80da6c28aaSamw  *    +-----------------------------+
81da6c28aaSamw  *		    |
82da6c28aaSamw  *		    | T2
83da6c28aaSamw  *		    |
84da6c28aaSamw  *		    v
85da6c28aaSamw  *    +-----------------------------+    T3
86da6c28aaSamw  *    |  SMB_USER_STATE_LOGGED_OFF  |----------> Deletion/Free
87da6c28aaSamw  *    +-----------------------------+
88da6c28aaSamw  *
89da6c28aaSamw  * SMB_USER_STATE_LOGGED_IN
90da6c28aaSamw  *
91da6c28aaSamw  *    While in this state:
92da6c28aaSamw  *      - The user is queued in the list of users of his session.
93da6c28aaSamw  *      - References will be given out if the user is looked up.
94da6c28aaSamw  *      - The user can access files and pipes.
95da6c28aaSamw  *
96da6c28aaSamw  * SMB_USER_STATE_LOGGING_OFF
97da6c28aaSamw  *
98da6c28aaSamw  *    While in this state:
99da6c28aaSamw  *      - The user is queued in the list of users of his session.
100da6c28aaSamw  *      - References will not be given out if the user is looked up.
101da6c28aaSamw  *      - The trees the user connected are being disconnected.
102da6c28aaSamw  *      - The resources associated with the user remain.
103da6c28aaSamw  *
104da6c28aaSamw  * SMB_USER_STATE_LOGGING_OFF
105da6c28aaSamw  *
106da6c28aaSamw  *    While in this state:
107da6c28aaSamw  *      - The user is queued in the list of users of his session.
108da6c28aaSamw  *      - References will not be given out if the user is looked up.
109da6c28aaSamw  *      - The user has no more trees connected.
110da6c28aaSamw  *      - The resources associated with the user remain.
111da6c28aaSamw  *
112da6c28aaSamw  * Transition T0
113da6c28aaSamw  *
114da6c28aaSamw  *    This transition occurs in smb_user_login(). A new user is created and
115da6c28aaSamw  *    added to the list of users of a session.
116da6c28aaSamw  *
117da6c28aaSamw  * Transition T1
118da6c28aaSamw  *
119da6c28aaSamw  *    This transition occurs in smb_user_logoff().
120da6c28aaSamw  *
121da6c28aaSamw  * Transition T2
122da6c28aaSamw  *
123da6c28aaSamw  *    This transition occurs in smb_user_release(). The resources associated
124da6c28aaSamw  *    with the user are deleted as well as the user. For the transition to
125da6c28aaSamw  *    occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the
126da6c28aaSamw  *    reference count be zero.
127da6c28aaSamw  *
128da6c28aaSamw  * Comments
129da6c28aaSamw  * --------
130da6c28aaSamw  *
131da6c28aaSamw  *    The state machine of the user structures is controlled by 3 elements:
132da6c28aaSamw  *      - The list of users of the session he belongs to.
133da6c28aaSamw  *      - The mutex embedded in the structure itself.
134da6c28aaSamw  *      - The reference count.
135da6c28aaSamw  *
136da6c28aaSamw  *    There's a mutex embedded in the user structure used to protect its fields
137da6c28aaSamw  *    and there's a lock embedded in the list of users of a session. To
138da6c28aaSamw  *    increment or to decrement the reference count the mutex must be entered.
139da6c28aaSamw  *    To insert the user into the list of users of the session and to remove
140da6c28aaSamw  *    the user from it, the lock must be entered in RW_WRITER mode.
141da6c28aaSamw  *
142da6c28aaSamw  *    Rules of access to a user structure:
143da6c28aaSamw  *
144da6c28aaSamw  *    1) In order to avoid deadlocks, when both (mutex and lock of the session
145da6c28aaSamw  *       list) have to be entered, the lock must be entered first.
146da6c28aaSamw  *
147da6c28aaSamw  *    2) All actions applied to a user require a reference count.
148da6c28aaSamw  *
149da6c28aaSamw  *    3) There are 2 ways of getting a reference count. One is when the user
1509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *       logs in. The other when the user is looked up.
151da6c28aaSamw  *
152da6c28aaSamw  *    It should be noted that the reference count of a user registers the
153da6c28aaSamw  *    number of references to the user in other structures (such as an smb
154da6c28aaSamw  *    request). The reference count is not incremented in these 2 instances:
155da6c28aaSamw  *
156da6c28aaSamw  *    1) The user is logged in. An user is anchored by his state. If there's
157da6c28aaSamw  *       no activity involving a user currently logged in, the reference
158da6c28aaSamw  *       count of that user is zero.
159da6c28aaSamw  *
160da6c28aaSamw  *    2) The user is queued in the list of users of the session. The fact of
161da6c28aaSamw  *       being queued in that list is NOT registered by incrementing the
162da6c28aaSamw  *       reference count.
163da6c28aaSamw  */
164148c5f43SAlan Wright #include <sys/types.h>
165148c5f43SAlan Wright #include <sys/sid.h>
166148c5f43SAlan Wright #include <sys/priv_names.h>
167bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
1689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <smbsrv/smb_door.h>
169da6c28aaSamw 
170c8ec8eeaSjose borrego #define	ADMINISTRATORS_SID	"S-1-5-32-544"
171c8ec8eeaSjose borrego 
1721fcced4cSJordan Brown static boolean_t smb_user_is_logged_in(smb_user_t *);
1731fcced4cSJordan Brown static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
174ae240eb8SGordon Ross static void smb_user_nonauth_logon(smb_user_t *);
175ae240eb8SGordon Ross static void smb_user_auth_logoff(smb_user_t *);
176c8ec8eeaSjose borrego 
177*7206bf49SGordon Ross 
178da6c28aaSamw /*
179148c5f43SAlan Wright  * Create a new user.
180da6c28aaSamw  */
181da6c28aaSamw smb_user_t *
smb_user_login(smb_session_t * session,cred_t * cr,char * domain_name,char * account_name,uint32_t flags,uint32_t privileges,uint32_t audit_sid)182da6c28aaSamw smb_user_login(
183da6c28aaSamw     smb_session_t	*session,
184da6c28aaSamw     cred_t		*cr,
185da6c28aaSamw     char		*domain_name,
186da6c28aaSamw     char		*account_name,
187da6c28aaSamw     uint32_t		flags,
188da6c28aaSamw     uint32_t		privileges,
189da6c28aaSamw     uint32_t		audit_sid)
190da6c28aaSamw {
191da6c28aaSamw 	smb_user_t	*user;
192da6c28aaSamw 
193da6c28aaSamw 	ASSERT(session);
194da6c28aaSamw 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
195da6c28aaSamw 	ASSERT(cr);
196da6c28aaSamw 	ASSERT(account_name);
197da6c28aaSamw 	ASSERT(domain_name);
198da6c28aaSamw 
199ae240eb8SGordon Ross 	user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
200da6c28aaSamw 	bzero(user, sizeof (smb_user_t));
201da6c28aaSamw 	user->u_refcnt = 1;
202da6c28aaSamw 	user->u_session = session;
203faa1795aSjb150015 	user->u_server = session->s_server;
204da6c28aaSamw 	user->u_logon_time = gethrestime_sec();
205da6c28aaSamw 	user->u_flags = flags;
206da6c28aaSamw 	user->u_name_len = strlen(account_name) + 1;
207da6c28aaSamw 	user->u_domain_len = strlen(domain_name) + 1;
2089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	user->u_name = smb_mem_strdup(account_name);
2099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	user->u_domain = smb_mem_strdup(domain_name);
210da6c28aaSamw 	user->u_audit_sid = audit_sid;
211da6c28aaSamw 
212da6c28aaSamw 	if (!smb_idpool_alloc(&session->s_uid_pool, &user->u_uid)) {
213da6c28aaSamw 		mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
214148c5f43SAlan Wright 		smb_user_setcred(user, cr, privileges);
215da6c28aaSamw 		user->u_state = SMB_USER_STATE_LOGGED_IN;
216da6c28aaSamw 		user->u_magic = SMB_USER_MAGIC;
217da6c28aaSamw 		smb_llist_enter(&session->s_user_list, RW_WRITER);
218da6c28aaSamw 		smb_llist_insert_tail(&session->s_user_list, user);
219da6c28aaSamw 		smb_llist_exit(&session->s_user_list);
220148c5f43SAlan Wright 		smb_server_inc_users(session->s_server);
221da6c28aaSamw 		return (user);
222da6c28aaSamw 	}
2239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_mem_free(user->u_name);
2249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_mem_free(user->u_domain);
225ae240eb8SGordon Ross 	kmem_cache_free(smb_cache_user, user);
226da6c28aaSamw 	return (NULL);
227da6c28aaSamw }
228da6c28aaSamw 
229da6c28aaSamw /*
230da6c28aaSamw  * Create a new user based on an existing user, used to support
231da6c28aaSamw  * additional SessionSetupX requests for a user on a session.
232da6c28aaSamw  *
233da6c28aaSamw  * Assumes the caller has a reference on the original user from
234da6c28aaSamw  * a user_lookup_by_x call.
235da6c28aaSamw  */
236da6c28aaSamw smb_user_t *
smb_user_dup(smb_user_t * orig_user)237da6c28aaSamw smb_user_dup(
238da6c28aaSamw     smb_user_t		*orig_user)
239da6c28aaSamw {
240da6c28aaSamw 	smb_user_t	*user;
241da6c28aaSamw 
242da6c28aaSamw 	ASSERT(orig_user->u_magic == SMB_USER_MAGIC);
243da6c28aaSamw 	ASSERT(orig_user->u_refcnt);
244da6c28aaSamw 
245da6c28aaSamw 	user = smb_user_login(orig_user->u_session, orig_user->u_cred,
246da6c28aaSamw 	    orig_user->u_domain, orig_user->u_name, orig_user->u_flags,
247da6c28aaSamw 	    orig_user->u_privileges, orig_user->u_audit_sid);
248da6c28aaSamw 
249da6c28aaSamw 	if (user)
250ae240eb8SGordon Ross 		smb_user_nonauth_logon(orig_user);
251da6c28aaSamw 
252da6c28aaSamw 	return (user);
253da6c28aaSamw }
254da6c28aaSamw 
255da6c28aaSamw /*
256da6c28aaSamw  * smb_user_logoff
257da6c28aaSamw  *
2581fcced4cSJordan Brown  * Change the user state and disconnect trees.
2591fcced4cSJordan Brown  * The user list must not be entered or modified here.
260da6c28aaSamw  */
261da6c28aaSamw void
smb_user_logoff(smb_user_t * user)262da6c28aaSamw smb_user_logoff(
263da6c28aaSamw     smb_user_t		*user)
264da6c28aaSamw {
265da6c28aaSamw 	ASSERT(user->u_magic == SMB_USER_MAGIC);
266da6c28aaSamw 
267da6c28aaSamw 	mutex_enter(&user->u_mutex);
268da6c28aaSamw 	ASSERT(user->u_refcnt);
269da6c28aaSamw 	switch (user->u_state) {
270da6c28aaSamw 	case SMB_USER_STATE_LOGGED_IN: {
271da6c28aaSamw 		/*
272da6c28aaSamw 		 * The user is moved into a state indicating that the log off
273da6c28aaSamw 		 * process has started.
274da6c28aaSamw 		 */
275da6c28aaSamw 		user->u_state = SMB_USER_STATE_LOGGING_OFF;
276da6c28aaSamw 		mutex_exit(&user->u_mutex);
277d040dae9SThomas Keiser 		smb_session_disconnect_owned_trees(user->u_session, user);
278ae240eb8SGordon Ross 		smb_user_auth_logoff(user);
279da6c28aaSamw 		mutex_enter(&user->u_mutex);
280da6c28aaSamw 		user->u_state = SMB_USER_STATE_LOGGED_OFF;
281148c5f43SAlan Wright 		smb_server_dec_users(user->u_server);
282da6c28aaSamw 		break;
283da6c28aaSamw 	}
284da6c28aaSamw 	case SMB_USER_STATE_LOGGED_OFF:
285da6c28aaSamw 	case SMB_USER_STATE_LOGGING_OFF:
286da6c28aaSamw 		break;
287da6c28aaSamw 
288da6c28aaSamw 	default:
289da6c28aaSamw 		ASSERT(0);
290da6c28aaSamw 		break;
291da6c28aaSamw 	}
292da6c28aaSamw 	mutex_exit(&user->u_mutex);
293da6c28aaSamw }
294da6c28aaSamw 
295da6c28aaSamw /*
296d040dae9SThomas Keiser  * Take a reference on a user.  Do not return a reference unless the user is in
297d040dae9SThomas Keiser  * the logged-in state.
2981fcced4cSJordan Brown  */
2991fcced4cSJordan Brown boolean_t
smb_user_hold(smb_user_t * user)3001fcced4cSJordan Brown smb_user_hold(smb_user_t *user)
3011fcced4cSJordan Brown {
302d040dae9SThomas Keiser 	SMB_USER_VALID(user);
3031fcced4cSJordan Brown 
3041fcced4cSJordan Brown 	mutex_enter(&user->u_mutex);
3051fcced4cSJordan Brown 
3061fcced4cSJordan Brown 	if (smb_user_is_logged_in(user)) {
3071fcced4cSJordan Brown 		user->u_refcnt++;
3081fcced4cSJordan Brown 		mutex_exit(&user->u_mutex);
3091fcced4cSJordan Brown 		return (B_TRUE);
3101fcced4cSJordan Brown 	}
3111fcced4cSJordan Brown 
3121fcced4cSJordan Brown 	mutex_exit(&user->u_mutex);
3131fcced4cSJordan Brown 	return (B_FALSE);
3141fcced4cSJordan Brown }
3151fcced4cSJordan Brown 
3161fcced4cSJordan Brown /*
317d040dae9SThomas Keiser  * Unconditionally take a reference on a user.
318d040dae9SThomas Keiser  */
319d040dae9SThomas Keiser void
smb_user_hold_internal(smb_user_t * user)320d040dae9SThomas Keiser smb_user_hold_internal(smb_user_t *user)
321d040dae9SThomas Keiser {
322d040dae9SThomas Keiser 	SMB_USER_VALID(user);
323d040dae9SThomas Keiser 
324d040dae9SThomas Keiser 	mutex_enter(&user->u_mutex);
325d040dae9SThomas Keiser 	user->u_refcnt++;
326d040dae9SThomas Keiser 	mutex_exit(&user->u_mutex);
327d040dae9SThomas Keiser }
328d040dae9SThomas Keiser 
329d040dae9SThomas Keiser /*
3309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Release a reference on a user.  If the reference count falls to
3319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * zero and the user has logged off, post the object for deletion.
3329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Object deletion is deferred to avoid modifying a list while an
3339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * iteration may be in progress.
334da6c28aaSamw  */
335da6c28aaSamw void
smb_user_release(smb_user_t * user)336da6c28aaSamw smb_user_release(
337da6c28aaSamw     smb_user_t		*user)
338da6c28aaSamw {
339da6c28aaSamw 	ASSERT(user->u_magic == SMB_USER_MAGIC);
340da6c28aaSamw 
341da6c28aaSamw 	mutex_enter(&user->u_mutex);
342da6c28aaSamw 	ASSERT(user->u_refcnt);
343da6c28aaSamw 	user->u_refcnt--;
344c5866007SKeyur Desai 
345da6c28aaSamw 	switch (user->u_state) {
346da6c28aaSamw 	case SMB_USER_STATE_LOGGED_OFF:
3479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (user->u_refcnt == 0)
3489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_session_post_user(user->u_session, user);
349da6c28aaSamw 		break;
350da6c28aaSamw 
351da6c28aaSamw 	case SMB_USER_STATE_LOGGED_IN:
352da6c28aaSamw 	case SMB_USER_STATE_LOGGING_OFF:
353da6c28aaSamw 		break;
354da6c28aaSamw 
355da6c28aaSamw 	default:
356da6c28aaSamw 		ASSERT(0);
357da6c28aaSamw 		break;
358da6c28aaSamw 	}
359da6c28aaSamw 	mutex_exit(&user->u_mutex);
360da6c28aaSamw }
361da6c28aaSamw 
3621fcced4cSJordan Brown /*
363c8ec8eeaSjose borrego  * Determine whether or not the user is an administrator.
364c8ec8eeaSjose borrego  * Members of the administrators group have administrative rights.
365c8ec8eeaSjose borrego  */
366c8ec8eeaSjose borrego boolean_t
smb_user_is_admin(smb_user_t * user)367148c5f43SAlan Wright smb_user_is_admin(smb_user_t *user)
368c8ec8eeaSjose borrego {
369*7206bf49SGordon Ross #ifdef	_KERNEL
370148c5f43SAlan Wright 	char		sidstr[SMB_SID_STRSZ];
371148c5f43SAlan Wright 	ksidlist_t	*ksidlist;
372148c5f43SAlan Wright 	ksid_t		ksid1;
373148c5f43SAlan Wright 	ksid_t		*ksid2;
374148c5f43SAlan Wright 	int		i;
375*7206bf49SGordon Ross #endif	/* _KERNEL */
376*7206bf49SGordon Ross 	boolean_t	rc = B_FALSE;
377c8ec8eeaSjose borrego 
378c8ec8eeaSjose borrego 	ASSERT(user);
379148c5f43SAlan Wright 	ASSERT(user->u_cred);
380c8ec8eeaSjose borrego 
381148c5f43SAlan Wright 	if (SMB_USER_IS_ADMIN(user))
382c8ec8eeaSjose borrego 		return (B_TRUE);
383c8ec8eeaSjose borrego 
384*7206bf49SGordon Ross #ifdef	_KERNEL
385148c5f43SAlan Wright 	bzero(&ksid1, sizeof (ksid_t));
386148c5f43SAlan Wright 	(void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ);
387148c5f43SAlan Wright 	ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0);
388148c5f43SAlan Wright 	ksid1.ks_domain = ksid_lookupdomain(sidstr);
389148c5f43SAlan Wright 
390148c5f43SAlan Wright 	ksidlist = crgetsidlist(user->u_cred);
391148c5f43SAlan Wright 	ASSERT(ksidlist);
392148c5f43SAlan Wright 	ASSERT(ksid1.ks_domain);
393148c5f43SAlan Wright 	ASSERT(ksid1.ks_domain->kd_name);
394148c5f43SAlan Wright 
395148c5f43SAlan Wright 	i = 0;
396148c5f43SAlan Wright 	ksid2 = crgetsid(user->u_cred, KSID_USER);
397148c5f43SAlan Wright 	do {
398148c5f43SAlan Wright 		ASSERT(ksid2->ks_domain);
399148c5f43SAlan Wright 		ASSERT(ksid2->ks_domain->kd_name);
400148c5f43SAlan Wright 
401148c5f43SAlan Wright 		if (strcmp(ksid1.ks_domain->kd_name,
402148c5f43SAlan Wright 		    ksid2->ks_domain->kd_name) == 0 &&
403148c5f43SAlan Wright 		    ksid1.ks_rid == ksid2->ks_rid) {
404148c5f43SAlan Wright 			user->u_flags |= SMB_USER_FLAG_ADMIN;
405148c5f43SAlan Wright 			rc = B_TRUE;
406148c5f43SAlan Wright 			break;
407148c5f43SAlan Wright 		}
408148c5f43SAlan Wright 
409148c5f43SAlan Wright 		ksid2 = &ksidlist->ksl_sids[i];
410148c5f43SAlan Wright 	} while (i++ < ksidlist->ksl_nsid);
411148c5f43SAlan Wright 
412148c5f43SAlan Wright 	ksid_rele(&ksid1);
413*7206bf49SGordon Ross #endif	/* _KERNEL */
414148c5f43SAlan Wright 	return (rc);
415c8ec8eeaSjose borrego }
416c8ec8eeaSjose borrego 
4171fcced4cSJordan Brown /*
4181fcced4cSJordan Brown  * This function should be called with a hold on the user.
4191fcced4cSJordan Brown  */
4201fcced4cSJordan Brown boolean_t
smb_user_namecmp(smb_user_t * user,const char * name)4211fcced4cSJordan Brown smb_user_namecmp(smb_user_t *user, const char *name)
4221fcced4cSJordan Brown {
4231fcced4cSJordan Brown 	char		*fq_name;
4241fcced4cSJordan Brown 	boolean_t	match;
4251fcced4cSJordan Brown 
426bbf6f00cSJordan Brown 	if (smb_strcasecmp(name, user->u_name, 0) == 0)
4271fcced4cSJordan Brown 		return (B_TRUE);
4281fcced4cSJordan Brown 
4291fcced4cSJordan Brown 	fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
4301fcced4cSJordan Brown 
4311fcced4cSJordan Brown 	(void) snprintf(fq_name, MAXNAMELEN, "%s\\%s",
4321fcced4cSJordan Brown 	    user->u_domain, user->u_name);
4331fcced4cSJordan Brown 
434bbf6f00cSJordan Brown 	match = (smb_strcasecmp(name, fq_name, 0) == 0);
4351fcced4cSJordan Brown 	if (!match) {
4361fcced4cSJordan Brown 		(void) snprintf(fq_name, MAXNAMELEN, "%s@%s",
4371fcced4cSJordan Brown 		    user->u_name, user->u_domain);
4381fcced4cSJordan Brown 
439bbf6f00cSJordan Brown 		match = (smb_strcasecmp(name, fq_name, 0) == 0);
4401fcced4cSJordan Brown 	}
4411fcced4cSJordan Brown 
4421fcced4cSJordan Brown 	kmem_free(fq_name, MAXNAMELEN);
4431fcced4cSJordan Brown 	return (match);
4441fcced4cSJordan Brown }
4451fcced4cSJordan Brown 
4461fcced4cSJordan Brown /*
4471fcced4cSJordan Brown  * If the enumeration request is for user data, handle the request
4481fcced4cSJordan Brown  * here.  Otherwise, pass it on to the trees.
4491fcced4cSJordan Brown  *
4501fcced4cSJordan Brown  * This function should be called with a hold on the user.
4511fcced4cSJordan Brown  */
4521fcced4cSJordan Brown int
smb_user_enum(smb_user_t * user,smb_svcenum_t * svcenum)4531fcced4cSJordan Brown smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
4541fcced4cSJordan Brown {
455d040dae9SThomas Keiser 	int		rc = 0;
4561fcced4cSJordan Brown 
4571fcced4cSJordan Brown 	ASSERT(user);
4581fcced4cSJordan Brown 	ASSERT(user->u_magic == SMB_USER_MAGIC);
4591fcced4cSJordan Brown 
4601fcced4cSJordan Brown 	if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
4611fcced4cSJordan Brown 		return (smb_user_enum_private(user, svcenum));
4621fcced4cSJordan Brown 
4631fcced4cSJordan Brown 	return (rc);
4641fcced4cSJordan Brown }
4651fcced4cSJordan Brown 
466da6c28aaSamw /* *************************** Static Functions ***************************** */
467da6c28aaSamw 
468da6c28aaSamw /*
4691fcced4cSJordan Brown  * Determine whether or not a user is logged in.
4701fcced4cSJordan Brown  * Typically, a reference can only be taken on a logged-in user.
4711fcced4cSJordan Brown  *
4721fcced4cSJordan Brown  * This is a private function and must be called with the user
4731fcced4cSJordan Brown  * mutex held.
4741fcced4cSJordan Brown  */
4751fcced4cSJordan Brown static boolean_t
smb_user_is_logged_in(smb_user_t * user)4761fcced4cSJordan Brown smb_user_is_logged_in(smb_user_t *user)
4771fcced4cSJordan Brown {
4781fcced4cSJordan Brown 	switch (user->u_state) {
4791fcced4cSJordan Brown 	case SMB_USER_STATE_LOGGED_IN:
4801fcced4cSJordan Brown 		return (B_TRUE);
4811fcced4cSJordan Brown 
4821fcced4cSJordan Brown 	case SMB_USER_STATE_LOGGING_OFF:
4831fcced4cSJordan Brown 	case SMB_USER_STATE_LOGGED_OFF:
4841fcced4cSJordan Brown 		return (B_FALSE);
4851fcced4cSJordan Brown 
4861fcced4cSJordan Brown 	default:
4871fcced4cSJordan Brown 		ASSERT(0);
4881fcced4cSJordan Brown 		return (B_FALSE);
4891fcced4cSJordan Brown 	}
4901fcced4cSJordan Brown }
4911fcced4cSJordan Brown 
4921fcced4cSJordan Brown /*
4939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Delete a user.  The tree list should be empty.
4949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  *
4959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * Remove the user from the session's user list before freeing resources
4969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States  * associated with the user.
497da6c28aaSamw  */
4989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_user_delete(void * arg)4999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_user_delete(void *arg)
500da6c28aaSamw {
501da6c28aaSamw 	smb_session_t	*session;
5029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_user_t	*user = (smb_user_t *)arg;
503da6c28aaSamw 
5049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	SMB_USER_VALID(user);
505da6c28aaSamw 	ASSERT(user->u_refcnt == 0);
506da6c28aaSamw 	ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
507da6c28aaSamw 
508da6c28aaSamw 	session = user->u_session;
509da6c28aaSamw 	smb_llist_enter(&session->s_user_list, RW_WRITER);
510da6c28aaSamw 	smb_llist_remove(&session->s_user_list, user);
5119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_idpool_free(&session->s_uid_pool, user->u_uid);
512da6c28aaSamw 	smb_llist_exit(&session->s_user_list);
513da6c28aaSamw 
5149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_enter(&user->u_mutex);
5159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	mutex_exit(&user->u_mutex);
5169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
517da6c28aaSamw 	user->u_magic = (uint32_t)~SMB_USER_MAGIC;
518da6c28aaSamw 	mutex_destroy(&user->u_mutex);
519148c5f43SAlan Wright 	if (user->u_cred)
520da6c28aaSamw 		crfree(user->u_cred);
521b89a8333Snatalie li - Sun Microsystems - Irvine United States 	if (user->u_privcred)
522b89a8333Snatalie li - Sun Microsystems - Irvine United States 		crfree(user->u_privcred);
5239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_mem_free(user->u_name);
5249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_mem_free(user->u_domain);
525ae240eb8SGordon Ross 	kmem_cache_free(smb_cache_user, user);
526da6c28aaSamw }
527c8ec8eeaSjose borrego 
528b89a8333Snatalie li - Sun Microsystems - Irvine United States cred_t *
smb_user_getcred(smb_user_t * user)529b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_getcred(smb_user_t *user)
530b89a8333Snatalie li - Sun Microsystems - Irvine United States {
531b89a8333Snatalie li - Sun Microsystems - Irvine United States 	return (user->u_cred);
532b89a8333Snatalie li - Sun Microsystems - Irvine United States }
533b89a8333Snatalie li - Sun Microsystems - Irvine United States 
534b89a8333Snatalie li - Sun Microsystems - Irvine United States cred_t *
smb_user_getprivcred(smb_user_t * user)535b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_getprivcred(smb_user_t *user)
536b89a8333Snatalie li - Sun Microsystems - Irvine United States {
537b89a8333Snatalie li - Sun Microsystems - Irvine United States 	return ((user->u_privcred)? user->u_privcred : user->u_cred);
538b89a8333Snatalie li - Sun Microsystems - Irvine United States }
5391fcced4cSJordan Brown 
540*7206bf49SGordon Ross #ifdef	_KERNEL
5411fcced4cSJordan Brown /*
542148c5f43SAlan Wright  * Assign the user cred and privileges.
543148c5f43SAlan Wright  *
544148c5f43SAlan Wright  * If the user has backup and/or restore privleges, dup the cred
545148c5f43SAlan Wright  * and add those privileges to this new privileged cred.
546148c5f43SAlan Wright  */
547*7206bf49SGordon Ross void
smb_user_setcred(smb_user_t * user,cred_t * cr,uint32_t privileges)548148c5f43SAlan Wright smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
549148c5f43SAlan Wright {
550148c5f43SAlan Wright 	cred_t *privcred = NULL;
551148c5f43SAlan Wright 
552148c5f43SAlan Wright 	ASSERT(cr);
553148c5f43SAlan Wright 	crhold(cr);
554148c5f43SAlan Wright 
555148c5f43SAlan Wright 	if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
556148c5f43SAlan Wright 		privcred = crdup(cr);
557148c5f43SAlan Wright 
558148c5f43SAlan Wright 	if (privcred != NULL) {
559148c5f43SAlan Wright 		if (privileges & SMB_USER_PRIV_BACKUP) {
560148c5f43SAlan Wright 			(void) crsetpriv(privcred, PRIV_FILE_DAC_READ,
561148c5f43SAlan Wright 			    PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
562148c5f43SAlan Wright 		}
563148c5f43SAlan Wright 
564148c5f43SAlan Wright 		if (privileges & SMB_USER_PRIV_RESTORE) {
565148c5f43SAlan Wright 			(void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE,
566148c5f43SAlan Wright 			    PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
567148c5f43SAlan Wright 			    PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
568148c5f43SAlan Wright 			    PRIV_FILE_OWNER, PRIV_FILE_SETID,
569148c5f43SAlan Wright 			    PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL);
570148c5f43SAlan Wright 		}
571148c5f43SAlan Wright 	}
572148c5f43SAlan Wright 
573148c5f43SAlan Wright 	user->u_cred = cr;
574148c5f43SAlan Wright 	user->u_privcred = privcred;
575148c5f43SAlan Wright 	user->u_privileges = privileges;
576148c5f43SAlan Wright }
577*7206bf49SGordon Ross #endif	/* _KERNEL */
578148c5f43SAlan Wright 
579148c5f43SAlan Wright /*
5801fcced4cSJordan Brown  * Private function to support smb_user_enum.
5811fcced4cSJordan Brown  */
5821fcced4cSJordan Brown static int
smb_user_enum_private(smb_user_t * user,smb_svcenum_t * svcenum)5831fcced4cSJordan Brown smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum)
5841fcced4cSJordan Brown {
5851fcced4cSJordan Brown 	uint8_t *pb;
5861fcced4cSJordan Brown 	uint_t nbytes;
5871fcced4cSJordan Brown 	int rc;
5881fcced4cSJordan Brown 
5891fcced4cSJordan Brown 	if (svcenum->se_nskip > 0) {
5901fcced4cSJordan Brown 		svcenum->se_nskip--;
5911fcced4cSJordan Brown 		return (0);
5921fcced4cSJordan Brown 	}
5931fcced4cSJordan Brown 
5941fcced4cSJordan Brown 	if (svcenum->se_nitems >= svcenum->se_nlimit) {
5951fcced4cSJordan Brown 		svcenum->se_nitems = svcenum->se_nlimit;
5961fcced4cSJordan Brown 		return (0);
5971fcced4cSJordan Brown 	}
5981fcced4cSJordan Brown 
5991fcced4cSJordan Brown 	pb = &svcenum->se_buf[svcenum->se_bused];
6001fcced4cSJordan Brown 	rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes);
6011fcced4cSJordan Brown 	if (rc == 0) {
6021fcced4cSJordan Brown 		svcenum->se_bavail -= nbytes;
6031fcced4cSJordan Brown 		svcenum->se_bused += nbytes;
6041fcced4cSJordan Brown 		svcenum->se_nitems++;
6051fcced4cSJordan Brown 	}
6061fcced4cSJordan Brown 
6071fcced4cSJordan Brown 	return (rc);
6081fcced4cSJordan Brown }
6091fcced4cSJordan Brown 
6101fcced4cSJordan Brown /*
6111fcced4cSJordan Brown  * Encode the NetInfo for a user into a buffer.  NetInfo contains
6121fcced4cSJordan Brown  * information that is often needed in user space to support RPC
6131fcced4cSJordan Brown  * requests.
6141fcced4cSJordan Brown  */
6151fcced4cSJordan Brown int
smb_user_netinfo_encode(smb_user_t * user,uint8_t * buf,size_t buflen,uint32_t * nbytes)6161fcced4cSJordan Brown smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen,
6171fcced4cSJordan Brown     uint32_t *nbytes)
6181fcced4cSJordan Brown {
6191fcced4cSJordan Brown 	smb_netuserinfo_t	info;
6201fcced4cSJordan Brown 	int			rc;
6211fcced4cSJordan Brown 
6221fcced4cSJordan Brown 	smb_user_netinfo_init(user, &info);
6231fcced4cSJordan Brown 	rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes);
6241fcced4cSJordan Brown 	smb_user_netinfo_fini(&info);
6251fcced4cSJordan Brown 
6261fcced4cSJordan Brown 	return (rc);
6271fcced4cSJordan Brown }
6281fcced4cSJordan Brown 
6291fcced4cSJordan Brown void
smb_user_netinfo_init(smb_user_t * user,smb_netuserinfo_t * info)6301fcced4cSJordan Brown smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
6311fcced4cSJordan Brown {
6321fcced4cSJordan Brown 	smb_session_t	*session;
6331fcced4cSJordan Brown 	char		*buf;
6341fcced4cSJordan Brown 
6351fcced4cSJordan Brown 	ASSERT(user);
6361fcced4cSJordan Brown 	ASSERT(user->u_domain);
6371fcced4cSJordan Brown 	ASSERT(user->u_name);
6381fcced4cSJordan Brown 
6391fcced4cSJordan Brown 	session = user->u_session;
6401fcced4cSJordan Brown 	ASSERT(session);
6411fcced4cSJordan Brown 	ASSERT(session->workstation);
6421fcced4cSJordan Brown 
6431fcced4cSJordan Brown 	info->ui_session_id = session->s_kid;
6441fcced4cSJordan Brown 	info->ui_native_os = session->native_os;
6451fcced4cSJordan Brown 	info->ui_ipaddr = session->ipaddr;
6461fcced4cSJordan Brown 	info->ui_numopens = session->s_file_cnt;
647c5866007SKeyur Desai 	info->ui_smb_uid = user->u_uid;
6481fcced4cSJordan Brown 	info->ui_logon_time = user->u_logon_time;
6491fcced4cSJordan Brown 	info->ui_flags = user->u_flags;
650c5866007SKeyur Desai 	info->ui_posix_uid = crgetuid(user->u_cred);
6511fcced4cSJordan Brown 
6521fcced4cSJordan Brown 	info->ui_domain_len = user->u_domain_len;
6539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	info->ui_domain = smb_mem_strdup(user->u_domain);
6541fcced4cSJordan Brown 
6551fcced4cSJordan Brown 	info->ui_account_len = user->u_name_len;
6569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	info->ui_account = smb_mem_strdup(user->u_name);
6571fcced4cSJordan Brown 
6581fcced4cSJordan Brown 	buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
6591fcced4cSJordan Brown 	smb_session_getclient(session, buf, MAXNAMELEN);
6601fcced4cSJordan Brown 	info->ui_workstation_len = strlen(buf) + 1;
6619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	info->ui_workstation = smb_mem_strdup(buf);
6621fcced4cSJordan Brown 	kmem_free(buf, MAXNAMELEN);
6631fcced4cSJordan Brown }
6641fcced4cSJordan Brown 
6651fcced4cSJordan Brown void
smb_user_netinfo_fini(smb_netuserinfo_t * info)6661fcced4cSJordan Brown smb_user_netinfo_fini(smb_netuserinfo_t *info)
6671fcced4cSJordan Brown {
6681fcced4cSJordan Brown 	if (info == NULL)
6691fcced4cSJordan Brown 		return;
6701fcced4cSJordan Brown 
6711fcced4cSJordan Brown 	if (info->ui_domain)
6729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_mem_free(info->ui_domain);
6731fcced4cSJordan Brown 	if (info->ui_account)
6749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_mem_free(info->ui_account);
6751fcced4cSJordan Brown 	if (info->ui_workstation)
6769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_mem_free(info->ui_workstation);
6771fcced4cSJordan Brown 
6781fcced4cSJordan Brown 	bzero(info, sizeof (smb_netuserinfo_t));
6791fcced4cSJordan Brown }
6809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
6819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_user_nonauth_logon(smb_user_t * user)682ae240eb8SGordon Ross smb_user_nonauth_logon(smb_user_t *user)
6839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
684ae240eb8SGordon Ross 	uint32_t audit_sid = user->u_audit_sid;
685ae240eb8SGordon Ross 
686ae240eb8SGordon Ross 	(void) smb_kdoor_upcall(user->u_server, SMB_DR_USER_NONAUTH_LOGON,
6879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    &audit_sid, xdr_uint32_t, NULL, NULL);
6889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
6899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
6909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_user_auth_logoff(smb_user_t * user)691ae240eb8SGordon Ross smb_user_auth_logoff(smb_user_t *user)
6929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
693ae240eb8SGordon Ross 	uint32_t audit_sid = user->u_audit_sid;
694ae240eb8SGordon Ross 
695ae240eb8SGordon Ross 	(void) smb_kdoor_upcall(user->u_server, SMB_DR_USER_AUTH_LOGOFF,
6969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    &audit_sid, xdr_uint32_t, NULL, NULL);
6979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
6989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
6999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_token_t *
smb_get_token(smb_session_t * session,smb_logon_t * user_info)700ae240eb8SGordon Ross smb_get_token(smb_session_t *session, smb_logon_t *user_info)
7019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
7029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_token_t	*token;
7039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	int		rc;
7049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
7069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
707ae240eb8SGordon Ross 	rc = smb_kdoor_upcall(session->s_server, SMB_DR_USER_AUTH_LOGON,
7089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    user_info, smb_logon_xdr, token, smb_token_xdr);
7099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (rc != 0) {
7119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		kmem_free(token, sizeof (smb_token_t));
7129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (NULL);
7139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (!smb_token_valid(token)) {
7169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_token_free(token);
7179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		return (NULL);
7189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	}
7199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
7209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (token);
7219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
722