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 /* 22faa1795aSjb150015 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 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 * +-------------------+ +-------------------+ +-------------------+ 42da6c28aaSamw * | 43da6c28aaSamw * | 44da6c28aaSamw * v 45da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 46da6c28aaSamw * | USER |<----->| USER |......| USER | 47da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 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 150da6c28aaSamw * logs in. The other when the user is looked up. This translates into 151da6c28aaSamw * 3 functions: smb_user_login(), smb_user_lookup_by_uid() and 152da6c28aaSamw * smb_user_lookup_by_credentials. 153da6c28aaSamw * 154da6c28aaSamw * It should be noted that the reference count of a user registers the 155da6c28aaSamw * number of references to the user in other structures (such as an smb 156da6c28aaSamw * request). The reference count is not incremented in these 2 instances: 157da6c28aaSamw * 158da6c28aaSamw * 1) The user is logged in. An user is anchored by his state. If there's 159da6c28aaSamw * no activity involving a user currently logged in, the reference 160da6c28aaSamw * count of that user is zero. 161da6c28aaSamw * 162da6c28aaSamw * 2) The user is queued in the list of users of the session. The fact of 163da6c28aaSamw * being queued in that list is NOT registered by incrementing the 164da6c28aaSamw * reference count. 165da6c28aaSamw */ 166da6c28aaSamw #include <smbsrv/smb_incl.h> 167da6c28aaSamw #include <smbsrv/smb_door_svc.h> 168da6c28aaSamw 169c8ec8eeaSjose borrego 170c8ec8eeaSjose borrego #define ADMINISTRATORS_SID "S-1-5-32-544" 171c8ec8eeaSjose borrego 172c8ec8eeaSjose borrego static smb_sid_t *smb_admins_sid = NULL; 173c8ec8eeaSjose borrego 174da6c28aaSamw static void smb_user_delete(smb_user_t *user); 175c8ec8eeaSjose borrego static smb_tree_t *smb_user_get_tree(smb_llist_t *, smb_tree_t *); 176c8ec8eeaSjose borrego 177c8ec8eeaSjose borrego int 178c8ec8eeaSjose borrego smb_user_init(void) 179c8ec8eeaSjose borrego { 180c8ec8eeaSjose borrego if (smb_admins_sid != NULL) 181c8ec8eeaSjose borrego return (0); 182c8ec8eeaSjose borrego 183c8ec8eeaSjose borrego if ((smb_admins_sid = smb_sid_fromstr(ADMINISTRATORS_SID)) == NULL) 184c8ec8eeaSjose borrego return (-1); 185c8ec8eeaSjose borrego 186c8ec8eeaSjose borrego return (0); 187c8ec8eeaSjose borrego } 188c8ec8eeaSjose borrego 189c8ec8eeaSjose borrego void 190c8ec8eeaSjose borrego smb_user_fini(void) 191c8ec8eeaSjose borrego { 192c8ec8eeaSjose borrego if (smb_admins_sid != NULL) { 193c8ec8eeaSjose borrego smb_sid_free(smb_admins_sid); 194c8ec8eeaSjose borrego smb_admins_sid = NULL; 195c8ec8eeaSjose borrego } 196c8ec8eeaSjose borrego } 197da6c28aaSamw 198da6c28aaSamw /* 199da6c28aaSamw * smb_user_login 200da6c28aaSamw * 201da6c28aaSamw * 202da6c28aaSamw */ 203da6c28aaSamw smb_user_t * 204da6c28aaSamw smb_user_login( 205da6c28aaSamw smb_session_t *session, 206da6c28aaSamw cred_t *cr, 207da6c28aaSamw char *domain_name, 208da6c28aaSamw char *account_name, 209da6c28aaSamw uint32_t flags, 210da6c28aaSamw uint32_t privileges, 211da6c28aaSamw uint32_t audit_sid) 212da6c28aaSamw { 213da6c28aaSamw smb_user_t *user; 214da6c28aaSamw 215da6c28aaSamw ASSERT(session); 216da6c28aaSamw ASSERT(session->s_magic == SMB_SESSION_MAGIC); 217da6c28aaSamw ASSERT(cr); 218da6c28aaSamw ASSERT(account_name); 219da6c28aaSamw ASSERT(domain_name); 220da6c28aaSamw 221faa1795aSjb150015 user = kmem_cache_alloc(session->s_server->si_cache_user, KM_SLEEP); 222da6c28aaSamw bzero(user, sizeof (smb_user_t)); 223da6c28aaSamw user->u_refcnt = 1; 224da6c28aaSamw user->u_session = session; 225faa1795aSjb150015 user->u_server = session->s_server; 226da6c28aaSamw user->u_logon_time = gethrestime_sec(); 227da6c28aaSamw user->u_flags = flags; 228da6c28aaSamw user->u_privileges = privileges; 229da6c28aaSamw user->u_name_len = strlen(account_name) + 1; 230da6c28aaSamw user->u_domain_len = strlen(domain_name) + 1; 231da6c28aaSamw user->u_name = smb_kstrdup(account_name, user->u_name_len); 232da6c28aaSamw user->u_domain = smb_kstrdup(domain_name, user->u_domain_len); 233da6c28aaSamw user->u_cred = cr; 234*b89a8333Snatalie li - Sun Microsystems - Irvine United States user->u_privcred = smb_cred_create_privs(cr, privileges); 235da6c28aaSamw user->u_audit_sid = audit_sid; 236da6c28aaSamw 237da6c28aaSamw if (!smb_idpool_alloc(&session->s_uid_pool, &user->u_uid)) { 238da6c28aaSamw if (!smb_idpool_constructor(&user->u_tid_pool)) { 239da6c28aaSamw smb_llist_constructor(&user->u_tree_list, 240da6c28aaSamw sizeof (smb_tree_t), offsetof(smb_tree_t, t_lnd)); 241da6c28aaSamw mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL); 242*b89a8333Snatalie li - Sun Microsystems - Irvine United States crhold(user->u_cred); 243*b89a8333Snatalie li - Sun Microsystems - Irvine United States if (user->u_privcred) 244*b89a8333Snatalie li - Sun Microsystems - Irvine United States crhold(user->u_privcred); 245da6c28aaSamw user->u_state = SMB_USER_STATE_LOGGED_IN; 246da6c28aaSamw user->u_magic = SMB_USER_MAGIC; 247da6c28aaSamw smb_llist_enter(&session->s_user_list, RW_WRITER); 248da6c28aaSamw smb_llist_insert_tail(&session->s_user_list, user); 249da6c28aaSamw smb_llist_exit(&session->s_user_list); 250faa1795aSjb150015 atomic_inc_32(&session->s_server->sv_open_users); 251da6c28aaSamw return (user); 252da6c28aaSamw } 253da6c28aaSamw smb_idpool_free(&session->s_uid_pool, user->u_uid); 254da6c28aaSamw } 255da6c28aaSamw kmem_free(user->u_name, (size_t)user->u_name_len); 256da6c28aaSamw kmem_free(user->u_domain, (size_t)user->u_domain_len); 257faa1795aSjb150015 kmem_cache_free(session->s_server->si_cache_user, user); 258da6c28aaSamw return (NULL); 259da6c28aaSamw } 260da6c28aaSamw 261da6c28aaSamw /* 262da6c28aaSamw * Create a new user based on an existing user, used to support 263da6c28aaSamw * additional SessionSetupX requests for a user on a session. 264da6c28aaSamw * 265da6c28aaSamw * Assumes the caller has a reference on the original user from 266da6c28aaSamw * a user_lookup_by_x call. 267da6c28aaSamw */ 268da6c28aaSamw smb_user_t * 269da6c28aaSamw smb_user_dup( 270da6c28aaSamw smb_user_t *orig_user) 271da6c28aaSamw { 272da6c28aaSamw smb_user_t *user; 273da6c28aaSamw 274da6c28aaSamw ASSERT(orig_user->u_magic == SMB_USER_MAGIC); 275da6c28aaSamw ASSERT(orig_user->u_refcnt); 276da6c28aaSamw 277da6c28aaSamw user = smb_user_login(orig_user->u_session, orig_user->u_cred, 278da6c28aaSamw orig_user->u_domain, orig_user->u_name, orig_user->u_flags, 279da6c28aaSamw orig_user->u_privileges, orig_user->u_audit_sid); 280da6c28aaSamw 281da6c28aaSamw if (user) 282da6c28aaSamw smb_user_nonauth_logon(orig_user->u_audit_sid); 283da6c28aaSamw 284da6c28aaSamw return (user); 285da6c28aaSamw } 286da6c28aaSamw 287da6c28aaSamw /* 288da6c28aaSamw * smb_user_logoff 289da6c28aaSamw * 290da6c28aaSamw * 291da6c28aaSamw */ 292da6c28aaSamw void 293da6c28aaSamw smb_user_logoff( 294da6c28aaSamw smb_user_t *user) 295da6c28aaSamw { 296da6c28aaSamw ASSERT(user->u_magic == SMB_USER_MAGIC); 297da6c28aaSamw 298da6c28aaSamw mutex_enter(&user->u_mutex); 299da6c28aaSamw ASSERT(user->u_refcnt); 300da6c28aaSamw switch (user->u_state) { 301da6c28aaSamw case SMB_USER_STATE_LOGGED_IN: { 302da6c28aaSamw /* 303da6c28aaSamw * The user is moved into a state indicating that the log off 304da6c28aaSamw * process has started. 305da6c28aaSamw */ 306da6c28aaSamw user->u_state = SMB_USER_STATE_LOGGING_OFF; 307da6c28aaSamw mutex_exit(&user->u_mutex); 308faa1795aSjb150015 atomic_dec_32(&user->u_server->sv_open_users); 309da6c28aaSamw /* 310da6c28aaSamw * All the trees hanging off of this user are disconnected. 311da6c28aaSamw */ 312c8ec8eeaSjose borrego smb_user_disconnect_trees(user); 313da6c28aaSamw smb_user_auth_logoff(user->u_audit_sid); 314da6c28aaSamw mutex_enter(&user->u_mutex); 315da6c28aaSamw user->u_state = SMB_USER_STATE_LOGGED_OFF; 316da6c28aaSamw break; 317da6c28aaSamw } 318da6c28aaSamw case SMB_USER_STATE_LOGGED_OFF: 319da6c28aaSamw case SMB_USER_STATE_LOGGING_OFF: 320da6c28aaSamw break; 321da6c28aaSamw 322da6c28aaSamw default: 323da6c28aaSamw ASSERT(0); 324da6c28aaSamw break; 325da6c28aaSamw } 326da6c28aaSamw mutex_exit(&user->u_mutex); 327da6c28aaSamw } 328da6c28aaSamw 329da6c28aaSamw /* 330da6c28aaSamw * smb_user_logoff_all 331da6c28aaSamw * 332da6c28aaSamw * 333da6c28aaSamw */ 334da6c28aaSamw void 335da6c28aaSamw smb_user_logoff_all( 336da6c28aaSamw smb_session_t *session) 337da6c28aaSamw { 338da6c28aaSamw smb_user_t *user; 339da6c28aaSamw 340da6c28aaSamw ASSERT(session); 341da6c28aaSamw ASSERT(session->s_magic == SMB_SESSION_MAGIC); 342da6c28aaSamw 343da6c28aaSamw smb_llist_enter(&session->s_user_list, RW_READER); 344da6c28aaSamw user = smb_llist_head(&session->s_user_list); 345da6c28aaSamw while (user) { 346da6c28aaSamw ASSERT(user->u_magic == SMB_USER_MAGIC); 347da6c28aaSamw ASSERT(user->u_session == session); 348da6c28aaSamw mutex_enter(&user->u_mutex); 349da6c28aaSamw switch (user->u_state) { 350da6c28aaSamw case SMB_USER_STATE_LOGGED_IN: 351da6c28aaSamw /* The user is still logged in. */ 352da6c28aaSamw user->u_refcnt++; 353da6c28aaSamw mutex_exit(&user->u_mutex); 354da6c28aaSamw smb_llist_exit(&session->s_user_list); 355da6c28aaSamw smb_user_logoff(user); 356da6c28aaSamw smb_user_release(user); 357da6c28aaSamw smb_llist_enter(&session->s_user_list, RW_READER); 358da6c28aaSamw user = smb_llist_head(&session->s_user_list); 359da6c28aaSamw break; 360da6c28aaSamw case SMB_USER_STATE_LOGGING_OFF: 361da6c28aaSamw case SMB_USER_STATE_LOGGED_OFF: 362da6c28aaSamw /* 363da6c28aaSamw * The user is logged off or logging off. 364da6c28aaSamw */ 365da6c28aaSamw mutex_exit(&user->u_mutex); 366da6c28aaSamw user = smb_llist_next(&session->s_user_list, user); 367da6c28aaSamw break; 368da6c28aaSamw default: 369da6c28aaSamw ASSERT(0); 370da6c28aaSamw mutex_exit(&user->u_mutex); 371da6c28aaSamw user = smb_llist_next(&session->s_user_list, user); 372da6c28aaSamw break; 373da6c28aaSamw } 374da6c28aaSamw } 375da6c28aaSamw smb_llist_exit(&session->s_user_list); 376da6c28aaSamw } 377da6c28aaSamw 378da6c28aaSamw /* 379da6c28aaSamw * smb_user_release 380da6c28aaSamw * 381da6c28aaSamw * 382da6c28aaSamw */ 383da6c28aaSamw void 384da6c28aaSamw smb_user_release( 385da6c28aaSamw smb_user_t *user) 386da6c28aaSamw { 387da6c28aaSamw ASSERT(user->u_magic == SMB_USER_MAGIC); 388da6c28aaSamw 389da6c28aaSamw mutex_enter(&user->u_mutex); 390da6c28aaSamw ASSERT(user->u_refcnt); 391da6c28aaSamw user->u_refcnt--; 392da6c28aaSamw switch (user->u_state) { 393da6c28aaSamw case SMB_USER_STATE_LOGGED_OFF: 394da6c28aaSamw if (user->u_refcnt == 0) { 395da6c28aaSamw mutex_exit(&user->u_mutex); 396da6c28aaSamw smb_user_delete(user); 397da6c28aaSamw return; 398da6c28aaSamw } 399da6c28aaSamw break; 400da6c28aaSamw 401da6c28aaSamw case SMB_USER_STATE_LOGGED_IN: 402da6c28aaSamw case SMB_USER_STATE_LOGGING_OFF: 403da6c28aaSamw break; 404da6c28aaSamw 405da6c28aaSamw default: 406da6c28aaSamw ASSERT(0); 407da6c28aaSamw break; 408da6c28aaSamw } 409da6c28aaSamw mutex_exit(&user->u_mutex); 410da6c28aaSamw } 411da6c28aaSamw 412da6c28aaSamw /* 413da6c28aaSamw * smb_user_lookup_by_uid 414da6c28aaSamw * 415da6c28aaSamw * Find the appropriate user for this request. The request credentials 416da6c28aaSamw * set here may be overridden by the tree credentials. In domain mode, 417da6c28aaSamw * the user and tree credentials should be the same. In share mode, the 418da6c28aaSamw * tree credentials (defined in the share definition) should override 419da6c28aaSamw * the user credentials. 420da6c28aaSamw */ 421da6c28aaSamw smb_user_t * 422da6c28aaSamw smb_user_lookup_by_uid( 423da6c28aaSamw smb_session_t *session, 424da6c28aaSamw uint16_t uid) 425da6c28aaSamw { 426da6c28aaSamw smb_user_t *user; 427da6c28aaSamw 428da6c28aaSamw ASSERT(session); 429da6c28aaSamw ASSERT(session->s_magic == SMB_SESSION_MAGIC); 430da6c28aaSamw 431da6c28aaSamw smb_llist_enter(&session->s_user_list, RW_READER); 432da6c28aaSamw user = smb_llist_head(&session->s_user_list); 433da6c28aaSamw while (user) { 434da6c28aaSamw ASSERT(user->u_magic == SMB_USER_MAGIC); 435da6c28aaSamw ASSERT(user->u_session == session); 436da6c28aaSamw if (user->u_uid == uid) { 437da6c28aaSamw mutex_enter(&user->u_mutex); 438da6c28aaSamw switch (user->u_state) { 439da6c28aaSamw 440da6c28aaSamw case SMB_USER_STATE_LOGGED_IN: 441da6c28aaSamw /* The user exists and is still logged in. */ 442da6c28aaSamw user->u_refcnt++; 443da6c28aaSamw mutex_exit(&user->u_mutex); 444da6c28aaSamw smb_llist_exit(&session->s_user_list); 445da6c28aaSamw return (user); 446da6c28aaSamw 447da6c28aaSamw case SMB_USER_STATE_LOGGING_OFF: 448da6c28aaSamw case SMB_USER_STATE_LOGGED_OFF: 449da6c28aaSamw /* 450da6c28aaSamw * The user exists but has logged off or is in 451da6c28aaSamw * the process of logging off. 452da6c28aaSamw */ 453da6c28aaSamw mutex_exit(&user->u_mutex); 454da6c28aaSamw smb_llist_exit(&session->s_user_list); 455da6c28aaSamw return (NULL); 456da6c28aaSamw 457da6c28aaSamw default: 458da6c28aaSamw ASSERT(0); 459da6c28aaSamw mutex_exit(&user->u_mutex); 460da6c28aaSamw smb_llist_exit(&session->s_user_list); 461da6c28aaSamw return (NULL); 462da6c28aaSamw } 463da6c28aaSamw } 464da6c28aaSamw user = smb_llist_next(&session->s_user_list, user); 465da6c28aaSamw } 466da6c28aaSamw smb_llist_exit(&session->s_user_list); 467da6c28aaSamw return (NULL); 468da6c28aaSamw } 469da6c28aaSamw 470da6c28aaSamw /* 471da6c28aaSamw * smb_user_lookup_by_state 472da6c28aaSamw * 473da6c28aaSamw * This function returns the first user in the logged in state. If the user 474da6c28aaSamw * provided is NULL the search starts from the beginning of the list passed 475da6c28aaSamw * in. It a user is provided the search starts just after that user. 476da6c28aaSamw */ 477da6c28aaSamw smb_user_t * 478da6c28aaSamw smb_user_lookup_by_state( 479da6c28aaSamw smb_session_t *session, 480da6c28aaSamw smb_user_t *user) 481da6c28aaSamw { 482da6c28aaSamw smb_llist_t *lst; 483da6c28aaSamw smb_user_t *next; 484da6c28aaSamw 485da6c28aaSamw ASSERT(session); 486da6c28aaSamw ASSERT(session->s_magic == SMB_SESSION_MAGIC); 487da6c28aaSamw 488da6c28aaSamw lst = &session->s_user_list; 489da6c28aaSamw 490da6c28aaSamw smb_llist_enter(lst, RW_READER); 491da6c28aaSamw if (user) { 492da6c28aaSamw ASSERT(user); 493da6c28aaSamw ASSERT(user->u_magic == SMB_USER_MAGIC); 494da6c28aaSamw ASSERT(user->u_refcnt); 495da6c28aaSamw next = smb_llist_next(lst, user); 496da6c28aaSamw } else { 497da6c28aaSamw next = smb_llist_head(lst); 498da6c28aaSamw } 499da6c28aaSamw while (next) { 500da6c28aaSamw ASSERT(next->u_magic == SMB_USER_MAGIC); 501da6c28aaSamw ASSERT(next->u_session == session); 502da6c28aaSamw mutex_enter(&next->u_mutex); 503da6c28aaSamw if (next->u_state == SMB_USER_STATE_LOGGED_IN) { 504da6c28aaSamw next->u_refcnt++; 505da6c28aaSamw mutex_exit(&next->u_mutex); 506da6c28aaSamw break; 507da6c28aaSamw } else { 508da6c28aaSamw ASSERT((next->u_state == SMB_USER_STATE_LOGGING_OFF) || 509da6c28aaSamw (next->u_state == SMB_USER_STATE_LOGGED_OFF)); 510da6c28aaSamw mutex_exit(&next->u_mutex); 511da6c28aaSamw next = smb_llist_next(lst, next); 512da6c28aaSamw } 513da6c28aaSamw } 514da6c28aaSamw smb_llist_exit(lst); 515da6c28aaSamw 516da6c28aaSamw return (next); 517da6c28aaSamw } 518da6c28aaSamw 519da6c28aaSamw /* 520c8ec8eeaSjose borrego * Find a tree by tree-id. 521da6c28aaSamw */ 522c8ec8eeaSjose borrego smb_tree_t * 523c8ec8eeaSjose borrego smb_user_lookup_tree( 524da6c28aaSamw smb_user_t *user, 525c8ec8eeaSjose borrego uint16_t tid) 526c8ec8eeaSjose borrego 527da6c28aaSamw { 528da6c28aaSamw smb_tree_t *tree; 529da6c28aaSamw 530da6c28aaSamw ASSERT(user); 531da6c28aaSamw ASSERT(user->u_magic == SMB_USER_MAGIC); 532da6c28aaSamw 533c8ec8eeaSjose borrego smb_llist_enter(&user->u_tree_list, RW_READER); 534c8ec8eeaSjose borrego tree = smb_llist_head(&user->u_tree_list); 535c8ec8eeaSjose borrego 536da6c28aaSamw while (tree) { 537da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 538c8ec8eeaSjose borrego ASSERT(tree->t_user == user); 539c8ec8eeaSjose borrego 540c8ec8eeaSjose borrego if (tree->t_tid == tid) { 541c8ec8eeaSjose borrego if (smb_tree_hold(tree)) { 542c8ec8eeaSjose borrego smb_llist_exit(&user->u_tree_list); 543c8ec8eeaSjose borrego return (tree); 544c8ec8eeaSjose borrego } else { 545c8ec8eeaSjose borrego smb_llist_exit(&user->u_tree_list); 546c8ec8eeaSjose borrego return (NULL); 547c8ec8eeaSjose borrego } 548c8ec8eeaSjose borrego } 549c8ec8eeaSjose borrego 550c8ec8eeaSjose borrego tree = smb_llist_next(&user->u_tree_list, tree); 551c8ec8eeaSjose borrego } 552c8ec8eeaSjose borrego 553c8ec8eeaSjose borrego smb_llist_exit(&user->u_tree_list); 554c8ec8eeaSjose borrego return (NULL); 555c8ec8eeaSjose borrego } 556c8ec8eeaSjose borrego 557c8ec8eeaSjose borrego /* 558c8ec8eeaSjose borrego * Find the first connected tree that matches the specified sharename. 559c8ec8eeaSjose borrego * If the specified tree is NULL the search starts from the beginning of 560c8ec8eeaSjose borrego * the user's tree list. If a tree is provided the search starts just 561c8ec8eeaSjose borrego * after that tree. 562c8ec8eeaSjose borrego */ 563c8ec8eeaSjose borrego smb_tree_t * 564c8ec8eeaSjose borrego smb_user_lookup_share( 565c8ec8eeaSjose borrego smb_user_t *user, 566c8ec8eeaSjose borrego const char *sharename, 567c8ec8eeaSjose borrego smb_tree_t *tree) 568c8ec8eeaSjose borrego { 569c8ec8eeaSjose borrego ASSERT(user); 570c8ec8eeaSjose borrego ASSERT(user->u_magic == SMB_USER_MAGIC); 571c8ec8eeaSjose borrego ASSERT(sharename); 572c8ec8eeaSjose borrego 573c8ec8eeaSjose borrego smb_llist_enter(&user->u_tree_list, RW_READER); 574c8ec8eeaSjose borrego 575c8ec8eeaSjose borrego if (tree) { 576c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 577c8ec8eeaSjose borrego ASSERT(tree->t_user == user); 578c8ec8eeaSjose borrego tree = smb_llist_next(&user->u_tree_list, tree); 579c8ec8eeaSjose borrego } else { 580c8ec8eeaSjose borrego tree = smb_llist_head(&user->u_tree_list); 581c8ec8eeaSjose borrego } 582c8ec8eeaSjose borrego 583c8ec8eeaSjose borrego while (tree) { 584c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 585c8ec8eeaSjose borrego ASSERT(tree->t_user == user); 586c8ec8eeaSjose borrego if (utf8_strcasecmp(tree->t_sharename, sharename) == 0) { 587c8ec8eeaSjose borrego if (smb_tree_hold(tree)) { 588c8ec8eeaSjose borrego smb_llist_exit(&user->u_tree_list); 589c8ec8eeaSjose borrego return (tree); 590c8ec8eeaSjose borrego } 591c8ec8eeaSjose borrego } 592c8ec8eeaSjose borrego tree = smb_llist_next(&user->u_tree_list, tree); 593c8ec8eeaSjose borrego } 594c8ec8eeaSjose borrego 595c8ec8eeaSjose borrego smb_llist_exit(&user->u_tree_list); 596c8ec8eeaSjose borrego return (NULL); 597c8ec8eeaSjose borrego } 598c8ec8eeaSjose borrego 599c8ec8eeaSjose borrego /* 600c8ec8eeaSjose borrego * Find the first connected tree that matches the specified volume name. 601c8ec8eeaSjose borrego * If the specified tree is NULL the search starts from the beginning of 602c8ec8eeaSjose borrego * the user's tree list. If a tree is provided the search starts just 603c8ec8eeaSjose borrego * after that tree. 604c8ec8eeaSjose borrego */ 605c8ec8eeaSjose borrego smb_tree_t * 606c8ec8eeaSjose borrego smb_user_lookup_volume( 607c8ec8eeaSjose borrego smb_user_t *user, 608c8ec8eeaSjose borrego const char *name, 609c8ec8eeaSjose borrego smb_tree_t *tree) 610c8ec8eeaSjose borrego { 611c8ec8eeaSjose borrego ASSERT(user); 612c8ec8eeaSjose borrego ASSERT(user->u_magic == SMB_USER_MAGIC); 613c8ec8eeaSjose borrego ASSERT(name); 614c8ec8eeaSjose borrego 615c8ec8eeaSjose borrego smb_llist_enter(&user->u_tree_list, RW_READER); 616c8ec8eeaSjose borrego 617c8ec8eeaSjose borrego if (tree) { 618c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 619c8ec8eeaSjose borrego ASSERT(tree->t_user == user); 620c8ec8eeaSjose borrego tree = smb_llist_next(&user->u_tree_list, tree); 621c8ec8eeaSjose borrego } else { 622c8ec8eeaSjose borrego tree = smb_llist_head(&user->u_tree_list); 623c8ec8eeaSjose borrego } 624c8ec8eeaSjose borrego 625c8ec8eeaSjose borrego while (tree) { 626c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 627c8ec8eeaSjose borrego ASSERT(tree->t_user == user); 628c8ec8eeaSjose borrego 629c8ec8eeaSjose borrego if (utf8_strcasecmp(tree->t_volume, name) == 0) { 630c8ec8eeaSjose borrego if (smb_tree_hold(tree)) { 631c8ec8eeaSjose borrego smb_llist_exit(&user->u_tree_list); 632c8ec8eeaSjose borrego return (tree); 633c8ec8eeaSjose borrego } 634c8ec8eeaSjose borrego } 635c8ec8eeaSjose borrego 636c8ec8eeaSjose borrego tree = smb_llist_next(&user->u_tree_list, tree); 637c8ec8eeaSjose borrego } 638c8ec8eeaSjose borrego 639c8ec8eeaSjose borrego smb_llist_exit(&user->u_tree_list); 640c8ec8eeaSjose borrego return (NULL); 641c8ec8eeaSjose borrego } 642c8ec8eeaSjose borrego 643c8ec8eeaSjose borrego /* 644c8ec8eeaSjose borrego * Disconnect all trees that match the specified client process-id. 645c8ec8eeaSjose borrego */ 646c8ec8eeaSjose borrego void 647c8ec8eeaSjose borrego smb_user_close_pid( 648c8ec8eeaSjose borrego smb_user_t *user, 649c8ec8eeaSjose borrego uint16_t pid) 650c8ec8eeaSjose borrego { 651c8ec8eeaSjose borrego smb_tree_t *tree; 652c8ec8eeaSjose borrego 653c8ec8eeaSjose borrego ASSERT(user); 654c8ec8eeaSjose borrego ASSERT(user->u_magic == SMB_USER_MAGIC); 655c8ec8eeaSjose borrego 656c8ec8eeaSjose borrego tree = smb_user_get_tree(&user->u_tree_list, NULL); 657c8ec8eeaSjose borrego while (tree) { 658c8ec8eeaSjose borrego smb_tree_t *next; 659c8ec8eeaSjose borrego ASSERT(tree->t_user == user); 660c8ec8eeaSjose borrego smb_tree_close_pid(tree, pid); 661c8ec8eeaSjose borrego next = smb_user_get_tree(&user->u_tree_list, tree); 662da6c28aaSamw smb_tree_release(tree); 663da6c28aaSamw tree = next; 664da6c28aaSamw } 665da6c28aaSamw } 666da6c28aaSamw 667da6c28aaSamw /* 668c8ec8eeaSjose borrego * Disconnect all trees that this user has connected. 669da6c28aaSamw */ 670da6c28aaSamw void 671c8ec8eeaSjose borrego smb_user_disconnect_trees( 672c8ec8eeaSjose borrego smb_user_t *user) 673c8ec8eeaSjose borrego { 674c8ec8eeaSjose borrego smb_tree_t *tree; 675c8ec8eeaSjose borrego 676c8ec8eeaSjose borrego ASSERT(user); 677c8ec8eeaSjose borrego ASSERT(user->u_magic == SMB_USER_MAGIC); 678c8ec8eeaSjose borrego 679c8ec8eeaSjose borrego tree = smb_user_get_tree(&user->u_tree_list, NULL); 680c8ec8eeaSjose borrego while (tree) { 681c8ec8eeaSjose borrego ASSERT(tree->t_user == user); 682c8ec8eeaSjose borrego smb_tree_disconnect(tree); 683c8ec8eeaSjose borrego smb_tree_release(tree); 684c8ec8eeaSjose borrego tree = smb_user_get_tree(&user->u_tree_list, NULL); 685c8ec8eeaSjose borrego } 686c8ec8eeaSjose borrego } 687c8ec8eeaSjose borrego 688c8ec8eeaSjose borrego /* 689c8ec8eeaSjose borrego * Disconnect all trees that match the specified share name. 690c8ec8eeaSjose borrego */ 691c8ec8eeaSjose borrego void 692c8ec8eeaSjose borrego smb_user_disconnect_share( 693da6c28aaSamw smb_user_t *user, 694c8ec8eeaSjose borrego const char *sharename) 695da6c28aaSamw { 696da6c28aaSamw smb_tree_t *tree; 697da6c28aaSamw smb_tree_t *next; 698da6c28aaSamw 699da6c28aaSamw ASSERT(user); 700da6c28aaSamw ASSERT(user->u_magic == SMB_USER_MAGIC); 701da6c28aaSamw ASSERT(user->u_refcnt); 702da6c28aaSamw 703c8ec8eeaSjose borrego tree = smb_user_lookup_share(user, sharename, NULL); 704da6c28aaSamw while (tree) { 705da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 706c8ec8eeaSjose borrego smb_session_cancel_requests(user->u_session, tree, NULL); 707da6c28aaSamw smb_tree_disconnect(tree); 708c8ec8eeaSjose borrego next = smb_user_lookup_share(user, sharename, tree); 709da6c28aaSamw smb_tree_release(tree); 710da6c28aaSamw tree = next; 711da6c28aaSamw } 712da6c28aaSamw } 713da6c28aaSamw 714c8ec8eeaSjose borrego /* 715c8ec8eeaSjose borrego * Determine whether or not the user is an administrator. 716c8ec8eeaSjose borrego * Members of the administrators group have administrative rights. 717c8ec8eeaSjose borrego */ 718c8ec8eeaSjose borrego boolean_t 719c8ec8eeaSjose borrego smb_user_is_admin( 720c8ec8eeaSjose borrego smb_user_t *user) 721c8ec8eeaSjose borrego { 722c8ec8eeaSjose borrego cred_t *u_cred; 723c8ec8eeaSjose borrego 724c8ec8eeaSjose borrego ASSERT(user); 725c8ec8eeaSjose borrego u_cred = user->u_cred; 726c8ec8eeaSjose borrego ASSERT(u_cred); 727c8ec8eeaSjose borrego 728c8ec8eeaSjose borrego if (smb_admins_sid == NULL) 729c8ec8eeaSjose borrego return (B_FALSE); 730c8ec8eeaSjose borrego 731c8ec8eeaSjose borrego if (smb_cred_is_member(u_cred, smb_admins_sid)) 732c8ec8eeaSjose borrego return (B_TRUE); 733c8ec8eeaSjose borrego 734c8ec8eeaSjose borrego return (B_FALSE); 735c8ec8eeaSjose borrego } 736c8ec8eeaSjose borrego 737da6c28aaSamw /* *************************** Static Functions ***************************** */ 738da6c28aaSamw 739da6c28aaSamw /* 740da6c28aaSamw * smb_user_delete 741da6c28aaSamw */ 742da6c28aaSamw static void 743da6c28aaSamw smb_user_delete( 744da6c28aaSamw smb_user_t *user) 745da6c28aaSamw { 746da6c28aaSamw smb_session_t *session; 747da6c28aaSamw 748da6c28aaSamw ASSERT(user); 749da6c28aaSamw ASSERT(user->u_magic == SMB_USER_MAGIC); 750da6c28aaSamw ASSERT(user->u_refcnt == 0); 751da6c28aaSamw ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF); 752da6c28aaSamw 753da6c28aaSamw session = user->u_session; 754da6c28aaSamw /* 755da6c28aaSamw * Let's remove the user from the list of users of the session. This 756da6c28aaSamw * has to be done before any resources associated with the user are 757da6c28aaSamw * deleted. 758da6c28aaSamw */ 759da6c28aaSamw smb_llist_enter(&session->s_user_list, RW_WRITER); 760da6c28aaSamw smb_llist_remove(&session->s_user_list, user); 761da6c28aaSamw smb_llist_exit(&session->s_user_list); 762da6c28aaSamw 763da6c28aaSamw user->u_magic = (uint32_t)~SMB_USER_MAGIC; 764da6c28aaSamw mutex_destroy(&user->u_mutex); 765da6c28aaSamw smb_llist_destructor(&user->u_tree_list); 766da6c28aaSamw smb_idpool_destructor(&user->u_tid_pool); 767da6c28aaSamw smb_idpool_free(&session->s_uid_pool, user->u_uid); 768da6c28aaSamw crfree(user->u_cred); 769*b89a8333Snatalie li - Sun Microsystems - Irvine United States if (user->u_privcred) 770*b89a8333Snatalie li - Sun Microsystems - Irvine United States crfree(user->u_privcred); 771da6c28aaSamw kmem_free(user->u_name, (size_t)user->u_name_len); 772da6c28aaSamw kmem_free(user->u_domain, (size_t)user->u_domain_len); 773faa1795aSjb150015 kmem_cache_free(user->u_server->si_cache_user, user); 774da6c28aaSamw } 775c8ec8eeaSjose borrego 776c8ec8eeaSjose borrego /* 777c8ec8eeaSjose borrego * Get the next connected tree in the list. A reference is taken on 778c8ec8eeaSjose borrego * the tree, which can be released later with smb_tree_release(). 779c8ec8eeaSjose borrego * 780c8ec8eeaSjose borrego * If the specified tree is NULL the search starts from the beginning of 781c8ec8eeaSjose borrego * the tree list. If a tree is provided the search starts just after 782c8ec8eeaSjose borrego * that tree. 783c8ec8eeaSjose borrego * 784c8ec8eeaSjose borrego * Returns NULL if there are no connected trees in the list. 785c8ec8eeaSjose borrego */ 786c8ec8eeaSjose borrego static smb_tree_t * 787c8ec8eeaSjose borrego smb_user_get_tree( 788c8ec8eeaSjose borrego smb_llist_t *tree_list, 789c8ec8eeaSjose borrego smb_tree_t *tree) 790c8ec8eeaSjose borrego { 791c8ec8eeaSjose borrego ASSERT(tree_list); 792c8ec8eeaSjose borrego 793c8ec8eeaSjose borrego smb_llist_enter(tree_list, RW_READER); 794c8ec8eeaSjose borrego 795c8ec8eeaSjose borrego if (tree) { 796c8ec8eeaSjose borrego ASSERT(tree->t_magic == SMB_TREE_MAGIC); 797c8ec8eeaSjose borrego tree = smb_llist_next(tree_list, tree); 798c8ec8eeaSjose borrego } else { 799c8ec8eeaSjose borrego tree = smb_llist_head(tree_list); 800c8ec8eeaSjose borrego } 801c8ec8eeaSjose borrego 802c8ec8eeaSjose borrego while (tree) { 803c8ec8eeaSjose borrego if (smb_tree_hold(tree)) 804c8ec8eeaSjose borrego break; 805c8ec8eeaSjose borrego 806c8ec8eeaSjose borrego tree = smb_llist_next(tree_list, tree); 807c8ec8eeaSjose borrego } 808c8ec8eeaSjose borrego 809c8ec8eeaSjose borrego smb_llist_exit(tree_list); 810c8ec8eeaSjose borrego return (tree); 811c8ec8eeaSjose borrego } 812*b89a8333Snatalie li - Sun Microsystems - Irvine United States 813*b89a8333Snatalie li - Sun Microsystems - Irvine United States cred_t * 814*b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_getcred(smb_user_t *user) 815*b89a8333Snatalie li - Sun Microsystems - Irvine United States { 816*b89a8333Snatalie li - Sun Microsystems - Irvine United States return (user->u_cred); 817*b89a8333Snatalie li - Sun Microsystems - Irvine United States } 818*b89a8333Snatalie li - Sun Microsystems - Irvine United States 819*b89a8333Snatalie li - Sun Microsystems - Irvine United States cred_t * 820*b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_getprivcred(smb_user_t *user) 821*b89a8333Snatalie li - Sun Microsystems - Irvine United States { 822*b89a8333Snatalie li - Sun Microsystems - Irvine United States return ((user->u_privcred)? user->u_privcred : user->u_cred); 823*b89a8333Snatalie li - Sun Microsystems - Irvine United States } 824