3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  24  * Copyright (c) 2016 by Delphix. All rights reserved.
  25  */
  26 
  27 /*
  28  * General Structures Layout
  29  * -------------------------
  30  *
  31  * This is a simplified diagram showing the relationship between most of the
  32  * main structures.
  33  *
  34  * +-------------------+
  35  * |     SMB_INFO      |
  36  * +-------------------+
  37  *          |
  38  *          |
  39  *          v
  40  * +-------------------+       +-------------------+      +-------------------+
  41  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
  42  * +-------------------+       +-------------------+      +-------------------+
  43  *   |          |
 
 
 164  *    occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the
 165  *    reference count be zero.
 166  *
 167  * Comments
 168  * --------
 169  *
 170  *    The state machine of the user structures is controlled by 3 elements:
 171  *      - The list of users of the session they belong to.
 172  *      - The mutex embedded in the structure itself.
 173  *      - The reference count.
 174  *
 175  *    There's a mutex embedded in the user structure used to protect its fields
 176  *    and there's a lock embedded in the list of users of a session. To
 177  *    increment or to decrement the reference count the mutex must be entered.
 178  *    To insert the user into the list of users of the session and to remove
 179  *    the user from it, the lock must be entered in RW_WRITER mode.
 180  *
 181  *    Rules of access to a user structure:
 182  *
 183  *    1) In order to avoid deadlocks, when both (mutex and lock of the session
 184  *       list) have to be entered, the lock must be entered first.
 185  *
 186  *    2) All actions applied to a user require a reference count.
 187  *
 188  *    3) There are 2 ways of getting a reference count. One is when the user
 189  *       logs in. The other when the user is looked up.
 190  *
 191  *    It should be noted that the reference count of a user registers the
 192  *    number of references to the user in other structures (such as an smb
 193  *    request). The reference count is not incremented in these 2 instances:
 194  *
 195  *    1) The user is logged in. An user is anchored by their state. If there's
 196  *       no activity involving a user currently logged in, the reference
 197  *       count of that user is zero.
 198  *
 199  *    2) The user is queued in the list of users of the session. The fact of
 200  *       being queued in that list is NOT registered by incrementing the
 201  *       reference count.
 202  */
 203 #include <sys/types.h>
 204 #include <sys/sid.h>
 205 #include <sys/priv_names.h>
 206 #include <smbsrv/smb_kproto.h>
 207 #include <smbsrv/smb_door.h>
 208 
 209 #define ADMINISTRATORS_SID      "S-1-5-32-544"
 210 
 211 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
 212 static void smb_user_auth_logoff(smb_user_t *);
 213 
 214 
 215 /*
 216  * Create a new user.
 217  */
 218 smb_user_t *
 219 smb_user_new(smb_session_t *session)
 220 {
 221         smb_user_t      *user;
 222 
 223         ASSERT(session);
 224         ASSERT(session->s_magic == SMB_SESSION_MAGIC);
 225 
 226         user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
 227         bzero(user, sizeof (smb_user_t));
 228 
 229         user->u_refcnt = 1;
 230         user->u_session = session;
 231         user->u_server = session->s_server;
 232         user->u_logon_time = gethrestime_sec();
 233 
 234         if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
 235                 goto errout;
 236 
 237         mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
 238         user->u_state = SMB_USER_STATE_LOGGING_ON;
 239         user->u_magic = SMB_USER_MAGIC;
 240 
 241         smb_llist_enter(&session->s_user_list, RW_WRITER);
 242         smb_llist_insert_tail(&session->s_user_list, user);
 243         smb_llist_exit(&session->s_user_list);
 244         smb_server_inc_users(session->s_server);
 245 
 246         return (user);
 247 
 248 errout:
 249         if (user->u_uid != 0)
 250                 smb_idpool_free(&session->s_uid_pool, user->u_uid);
 251         kmem_cache_free(smb_cache_user, user);
 252         return (NULL);
 253 }
 254 
 255 /*
 256  * Fill in the details of a user, meaning a transition
 257  * from state LOGGING_ON to state LOGGED_ON.
 258  */
 259 int
 260 smb_user_logon(
 261     smb_user_t          *user,
 262     cred_t              *cr,
 263     char                *domain_name,
 264     char                *account_name,
 265     uint32_t            flags,
 266     uint32_t            privileges,
 267     uint32_t            audit_sid)
 268 {
 269 
 270         ASSERT(user->u_magic == SMB_USER_MAGIC);
 271         ASSERT(cr);
 272         ASSERT(account_name);
 273         ASSERT(domain_name);
 274 
 275         mutex_enter(&user->u_mutex);
 276 
 277         if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
 278                 mutex_exit(&user->u_mutex);
 279                 return (-1);
 280         }
 281 
 282         smb_authsock_close(user);
 283 
 284         user->u_state = SMB_USER_STATE_LOGGED_ON;
 285         user->u_flags = flags;
 286         user->u_name_len = strlen(account_name) + 1;
 287         user->u_domain_len = strlen(domain_name) + 1;
 288         user->u_name = smb_mem_strdup(account_name);
 289         user->u_domain = smb_mem_strdup(domain_name);
 290         user->u_audit_sid = audit_sid;
 291 
 292         smb_user_setcred(user, cr, privileges);
 293 
 294         mutex_exit(&user->u_mutex);
 295 
 296         return (0);
 297 }
 298 
 299 /*
 300  * smb_user_logoff
 301  *
 302  * Change the user state and disconnect trees.
 303  * The user list must not be entered or modified here.
 304  */
 305 void
 306 smb_user_logoff(
 307     smb_user_t          *user)
 308 {
 309         ASSERT(user->u_magic == SMB_USER_MAGIC);
 310 
 311         mutex_enter(&user->u_mutex);
 312         ASSERT(user->u_refcnt);
 313         switch (user->u_state) {
 314         case SMB_USER_STATE_LOGGING_ON: {
 315                 smb_authsock_close(user);
 316                 user->u_state = SMB_USER_STATE_LOGGED_OFF;
 317                 smb_server_dec_users(user->u_server);
 318                 break;
 319         }
 320 
 321         case SMB_USER_STATE_LOGGED_ON: {
 322                 /*
 323                  * The user is moved into a state indicating that the log off
 324                  * process has started.
 325                  */
 326                 user->u_state = SMB_USER_STATE_LOGGING_OFF;
 327                 mutex_exit(&user->u_mutex);
 328                 smb_session_disconnect_owned_trees(user->u_session, user);
 329                 smb_user_auth_logoff(user);
 330                 mutex_enter(&user->u_mutex);
 331                 user->u_state = SMB_USER_STATE_LOGGED_OFF;
 332                 smb_server_dec_users(user->u_server);
 333                 break;
 334         }
 335         case SMB_USER_STATE_LOGGED_OFF:
 336         case SMB_USER_STATE_LOGGING_OFF:
 337                 break;
 338 
 339         default:
 340                 ASSERT(0);
 341                 break;
 342         }
 343         mutex_exit(&user->u_mutex);
 344 }
 345 
 346 /*
 347  * Take a reference on a user.  Do not return a reference unless the user is in
 348  * the logged-in state.
 349  */
 350 boolean_t
 351 smb_user_hold(smb_user_t *user)
 352 {
 353         SMB_USER_VALID(user);
 354 
 355         mutex_enter(&user->u_mutex);
 356 
 357         if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
 358                 user->u_refcnt++;
 359                 mutex_exit(&user->u_mutex);
 360                 return (B_TRUE);
 361         }
 362 
 363         mutex_exit(&user->u_mutex);
 
 370 void
 371 smb_user_hold_internal(smb_user_t *user)
 372 {
 373         SMB_USER_VALID(user);
 374 
 375         mutex_enter(&user->u_mutex);
 376         user->u_refcnt++;
 377         mutex_exit(&user->u_mutex);
 378 }
 379 
 380 /*
 381  * Release a reference on a user.  If the reference count falls to
 382  * zero and the user has logged off, post the object for deletion.
 383  * Object deletion is deferred to avoid modifying a list while an
 384  * iteration may be in progress.
 385  */
 386 void
 387 smb_user_release(
 388     smb_user_t          *user)
 389 {
 390         ASSERT(user->u_magic == SMB_USER_MAGIC);
 391 
 392         mutex_enter(&user->u_mutex);
 393         ASSERT(user->u_refcnt);
 394         user->u_refcnt--;
 395 
 396         switch (user->u_state) {
 397         case SMB_USER_STATE_LOGGED_OFF:
 398                 if (user->u_refcnt == 0)
 399                         smb_session_post_user(user->u_session, user);
 400                 break;
 401 
 402         case SMB_USER_STATE_LOGGING_ON:
 403         case SMB_USER_STATE_LOGGED_ON:
 404         case SMB_USER_STATE_LOGGING_OFF:
 405                 break;
 406 
 407         default:
 408                 ASSERT(0);
 409                 break;
 410         }
 411         mutex_exit(&user->u_mutex);
 412 }
 413 
 414 /*
 415  * Determine whether or not the user is an administrator.
 416  * Members of the administrators group have administrative rights.
 417  */
 418 boolean_t
 419 smb_user_is_admin(smb_user_t *user)
 420 {
 421 #ifdef  _KERNEL
 422         char            sidstr[SMB_SID_STRSZ];
 423         ksidlist_t      *ksidlist;
 424         ksid_t          ksid1;
 425         ksid_t          *ksid2;
 426         int             i;
 427 #endif  /* _KERNEL */
 428         boolean_t       rc = B_FALSE;
 429 
 430         ASSERT(user);
 431         ASSERT(user->u_cred);
 432 
 433         if (SMB_USER_IS_ADMIN(user))
 434                 return (B_TRUE);
 
 506 {
 507         int             rc = 0;
 508 
 509         ASSERT(user);
 510         ASSERT(user->u_magic == SMB_USER_MAGIC);
 511 
 512         if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
 513                 return (smb_user_enum_private(user, svcenum));
 514 
 515         return (rc);
 516 }
 517 
 518 /* *************************** Static Functions ***************************** */
 519 
 520 /*
 521  * Delete a user.  The tree list should be empty.
 522  *
 523  * Remove the user from the session's user list before freeing resources
 524  * associated with the user.
 525  */
 526 void
 527 smb_user_delete(void *arg)
 528 {
 529         smb_session_t   *session;
 530         smb_user_t      *user = (smb_user_t *)arg;
 531 
 532         SMB_USER_VALID(user);
 533         ASSERT(user->u_refcnt == 0);
 534         ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
 535         ASSERT(user->u_authsock == NULL);
 536 
 537         session = user->u_session;
 538         smb_llist_enter(&session->s_user_list, RW_WRITER);
 539         smb_llist_remove(&session->s_user_list, user);
 540         smb_idpool_free(&session->s_uid_pool, user->u_uid);
 541         smb_llist_exit(&session->s_user_list);
 542 
 543         mutex_enter(&user->u_mutex);
 544         mutex_exit(&user->u_mutex);
 545 
 546         user->u_magic = (uint32_t)~SMB_USER_MAGIC;
 547         mutex_destroy(&user->u_mutex);
 548         if (user->u_cred)
 549                 crfree(user->u_cred);
 550         if (user->u_privcred)
 551                 crfree(user->u_privcred);
 552         smb_mem_free(user->u_name);
 553         smb_mem_free(user->u_domain);
 554         kmem_cache_free(smb_cache_user, user);
 555 }
 556 
 557 cred_t *
 558 smb_user_getcred(smb_user_t *user)
 559 {
 560         return (user->u_cred);
 561 }
 562 
 
 656 }
 657 
 658 void
 659 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
 660 {
 661         smb_session_t   *session;
 662         char            *buf;
 663 
 664         ASSERT(user);
 665         ASSERT(user->u_domain);
 666         ASSERT(user->u_name);
 667 
 668         session = user->u_session;
 669         ASSERT(session);
 670         ASSERT(session->workstation);
 671 
 672         info->ui_session_id = session->s_kid;
 673         info->ui_native_os = session->native_os;
 674         info->ui_ipaddr = session->ipaddr;
 675         info->ui_numopens = session->s_file_cnt;
 676         info->ui_smb_uid = user->u_uid;
 677         info->ui_logon_time = user->u_logon_time;
 678         info->ui_flags = user->u_flags;
 679         info->ui_posix_uid = crgetuid(user->u_cred);
 680 
 681         info->ui_domain_len = user->u_domain_len;
 682         info->ui_domain = smb_mem_strdup(user->u_domain);
 683 
 684         info->ui_account_len = user->u_name_len;
 685         info->ui_account = smb_mem_strdup(user->u_name);
 686 
 687         buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 688         smb_session_getclient(session, buf, MAXNAMELEN);
 689         info->ui_workstation_len = strlen(buf) + 1;
 690         info->ui_workstation = smb_mem_strdup(buf);
 691         kmem_free(buf, MAXNAMELEN);
 692 }
 693 
 694 void
 695 smb_user_netinfo_fini(smb_netuserinfo_t *info)
 696 {
 697         if (info == NULL)
 698                 return;
 699 
 700         if (info->ui_domain)
 701                 smb_mem_free(info->ui_domain);
 702         if (info->ui_account)
 703                 smb_mem_free(info->ui_account);
 704         if (info->ui_workstation)
 705                 smb_mem_free(info->ui_workstation);
 706 
 707         bzero(info, sizeof (smb_netuserinfo_t));
 708 }
 709 
 710 static void
 711 smb_user_auth_logoff(smb_user_t *user)
 712 {
 713         uint32_t audit_sid = user->u_audit_sid;
 714 
 715         (void) smb_kdoor_upcall(user->u_server, SMB_DR_USER_AUTH_LOGOFF,
 716             &audit_sid, xdr_uint32_t, NULL, NULL);
 717 }
 | 
 
 
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
  24  * Copyright (c) 2016 by Delphix. All rights reserved.
  25  */
  26 
  27 /*
  28  * General Structures Layout
  29  * -------------------------
  30  *
  31  * This is a simplified diagram showing the relationship between most of the
  32  * main structures.
  33  *
  34  * +-------------------+
  35  * |     SMB_INFO      |
  36  * +-------------------+
  37  *          |
  38  *          |
  39  *          v
  40  * +-------------------+       +-------------------+      +-------------------+
  41  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
  42  * +-------------------+       +-------------------+      +-------------------+
  43  *   |          |
 
 
 164  *    occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the
 165  *    reference count be zero.
 166  *
 167  * Comments
 168  * --------
 169  *
 170  *    The state machine of the user structures is controlled by 3 elements:
 171  *      - The list of users of the session they belong to.
 172  *      - The mutex embedded in the structure itself.
 173  *      - The reference count.
 174  *
 175  *    There's a mutex embedded in the user structure used to protect its fields
 176  *    and there's a lock embedded in the list of users of a session. To
 177  *    increment or to decrement the reference count the mutex must be entered.
 178  *    To insert the user into the list of users of the session and to remove
 179  *    the user from it, the lock must be entered in RW_WRITER mode.
 180  *
 181  *    Rules of access to a user structure:
 182  *
 183  *    1) In order to avoid deadlocks, when both (mutex and lock of the session
 184  *       list) have to be entered, the lock must be entered first. Additionally,
 185  *       one may NOT flush the deleteq of either the tree list or the ofile list
 186  *       while the user mutex is held.
 187  *
 188  *    2) All actions applied to a user require a reference count.
 189  *
 190  *    3) There are 2 ways of getting a reference count. One is when the user
 191  *       logs in. The other when the user is looked up.
 192  *
 193  *    It should be noted that the reference count of a user registers the
 194  *    number of references to the user in other structures (such as an smb
 195  *    request). The reference count is not incremented in these 2 instances:
 196  *
 197  *    1) The user is logged in. An user is anchored by their state. If there's
 198  *       no activity involving a user currently logged in, the reference
 199  *       count of that user is zero.
 200  *
 201  *    2) The user is queued in the list of users of the session. The fact of
 202  *       being queued in that list is NOT registered by incrementing the
 203  *       reference count.
 204  */
 205 #include <sys/types.h>
 206 #include <sys/sid.h>
 207 #include <sys/priv_names.h>
 208 #include <smbsrv/smb_kproto.h>
 209 #include <smbsrv/smb_door.h>
 210 
 211 #define ADMINISTRATORS_SID      "S-1-5-32-544"
 212 
 213 /* Don't leak object addresses */
 214 #define SMB_USER_SSNID(u) \
 215         ((uintptr_t)&smb_cache_user ^ (uintptr_t)(u))
 216 
 217 static void smb_user_delete(void *);
 218 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
 219 static void smb_user_auth_logoff(smb_user_t *);
 220 static void smb_user_logoff_tq(void *);
 221 
 222 /*
 223  * Create a new user.
 224  *
 225  * For SMB2 and later, session IDs (u_ssnid) need to be unique among all
 226  * current and "recent" sessions.  The session ID is derived from the
 227  * address of the smb_user object (obscured by XOR with a constant).
 228  * This adds a 3-bit generation number in the low bits, incremented
 229  * when we allocate an smb_user_t from its kmem cache, so it can't
 230  * be confused with a (recent) previous incarnation of this object.
 231  */
 232 smb_user_t *
 233 smb_user_new(smb_session_t *session)
 234 {
 235         smb_user_t      *user;
 236         uint_t          gen;    // generation (low 3 bits of ssnid)
 237 
 238         ASSERT(session);
 239         ASSERT(session->s_magic == SMB_SESSION_MAGIC);
 240 
 241         user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
 242         gen = (user->u_ssnid + 1) & 7;
 243         bzero(user, sizeof (smb_user_t));
 244 
 245         user->u_refcnt = 1;
 246         user->u_session = session;
 247         user->u_server = session->s_server;
 248         user->u_logon_time = gethrestime_sec();
 249 
 250         if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
 251                 goto errout;
 252         user->u_ssnid = SMB_USER_SSNID(user) + gen;
 253 
 254         mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
 255         user->u_state = SMB_USER_STATE_LOGGING_ON;
 256         user->u_magic = SMB_USER_MAGIC;
 257 
 258         smb_llist_enter(&session->s_user_list, RW_WRITER);
 259         smb_llist_insert_tail(&session->s_user_list, user);
 260         smb_llist_exit(&session->s_user_list);
 261         smb_server_inc_users(session->s_server);
 262 
 263         return (user);
 264 
 265 errout:
 266         if (user->u_uid != 0)
 267                 smb_idpool_free(&session->s_uid_pool, user->u_uid);
 268         kmem_cache_free(smb_cache_user, user);
 269         return (NULL);
 270 }
 271 
 272 /*
 273  * Fill in the details of a user, meaning a transition
 274  * from state LOGGING_ON to state LOGGED_ON.
 275  */
 276 int
 277 smb_user_logon(
 278     smb_user_t          *user,
 279     cred_t              *cr,
 280     char                *domain_name,
 281     char                *account_name,
 282     uint32_t            flags,
 283     uint32_t            privileges,
 284     uint32_t            audit_sid)
 285 {
 286         ksocket_t authsock = NULL;
 287 
 288         ASSERT(user->u_magic == SMB_USER_MAGIC);
 289         ASSERT(cr);
 290         ASSERT(account_name);
 291         ASSERT(domain_name);
 292 
 293         mutex_enter(&user->u_mutex);
 294 
 295         if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
 296                 mutex_exit(&user->u_mutex);
 297                 return (-1);
 298         }
 299 
 300         /*
 301          * In the transition from LOGGING_ON to LOGGED_ON,
 302          * we always have an auth. socket to close.
 303          */
 304         authsock = user->u_authsock;
 305         user->u_authsock = NULL;
 306         if (user->u_auth_tmo != NULL) {
 307                 (void) untimeout(user->u_auth_tmo);
 308                 user->u_auth_tmo = NULL;
 309         }
 310 
 311         user->u_state = SMB_USER_STATE_LOGGED_ON;
 312         user->u_flags = flags;
 313         user->u_name_len = strlen(account_name) + 1;
 314         user->u_domain_len = strlen(domain_name) + 1;
 315         user->u_name = smb_mem_strdup(account_name);
 316         user->u_domain = smb_mem_strdup(domain_name);
 317         user->u_audit_sid = audit_sid;
 318 
 319         smb_user_setcred(user, cr, privileges);
 320 
 321         mutex_exit(&user->u_mutex);
 322 
 323         /* This close can block, so not under the mutex. */
 324         if (authsock != NULL)
 325                 smb_authsock_close(user, authsock);
 326 
 327         return (0);
 328 }
 329 
 330 /*
 331  * smb_user_logoff
 332  *
 333  * Change the user state to "logging off" and disconnect trees.
 334  * The user list must not be entered or modified here.
 335  *
 336  * We remain in state "logging off" until the last ref. is gone,
 337  * then smb_user_release takes us to state "logged off".
 338  */
 339 void
 340 smb_user_logoff(
 341     smb_user_t          *user)
 342 {
 343         ksocket_t authsock = NULL;
 344 
 345         ASSERT(user->u_magic == SMB_USER_MAGIC);
 346 
 347         mutex_enter(&user->u_mutex);
 348         ASSERT(user->u_refcnt);
 349         switch (user->u_state) {
 350         case SMB_USER_STATE_LOGGING_ON:
 351                 authsock = user->u_authsock;
 352                 user->u_authsock = NULL;
 353                 if (user->u_auth_tmo != NULL) {
 354                         (void) untimeout(user->u_auth_tmo);
 355                         user->u_auth_tmo = NULL;
 356                 }
 357                 user->u_state = SMB_USER_STATE_LOGGING_OFF;
 358                 mutex_exit(&user->u_mutex);
 359                 /* This close can block, so not under the mutex. */
 360                 if (authsock != NULL) {
 361                         smb_authsock_close(user, authsock);
 362                 }
 363                 break;
 364 
 365         case SMB_USER_STATE_LOGGED_ON:
 366                 /*
 367                  * The user is moved into a state indicating that the log off
 368                  * process has started.
 369                  */
 370                 user->u_state = SMB_USER_STATE_LOGGING_OFF;
 371                 mutex_exit(&user->u_mutex);
 372                 smb_session_disconnect_owned_trees(user->u_session, user);
 373                 smb_user_auth_logoff(user);
 374                 break;
 375 
 376         case SMB_USER_STATE_LOGGED_OFF:
 377         case SMB_USER_STATE_LOGGING_OFF:
 378                 mutex_exit(&user->u_mutex);
 379                 break;
 380 
 381         default:
 382                 ASSERT(0);
 383                 mutex_exit(&user->u_mutex);
 384                 break;
 385         }
 386 }
 387 
 388 /*
 389  * Take a reference on a user.  Do not return a reference unless the user is in
 390  * the logged-in state.
 391  */
 392 boolean_t
 393 smb_user_hold(smb_user_t *user)
 394 {
 395         SMB_USER_VALID(user);
 396 
 397         mutex_enter(&user->u_mutex);
 398 
 399         if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
 400                 user->u_refcnt++;
 401                 mutex_exit(&user->u_mutex);
 402                 return (B_TRUE);
 403         }
 404 
 405         mutex_exit(&user->u_mutex);
 
 412 void
 413 smb_user_hold_internal(smb_user_t *user)
 414 {
 415         SMB_USER_VALID(user);
 416 
 417         mutex_enter(&user->u_mutex);
 418         user->u_refcnt++;
 419         mutex_exit(&user->u_mutex);
 420 }
 421 
 422 /*
 423  * Release a reference on a user.  If the reference count falls to
 424  * zero and the user has logged off, post the object for deletion.
 425  * Object deletion is deferred to avoid modifying a list while an
 426  * iteration may be in progress.
 427  */
 428 void
 429 smb_user_release(
 430     smb_user_t          *user)
 431 {
 432         smb_session_t *ssn = user->u_session;
 433 
 434         SMB_USER_VALID(user);
 435 
 436         /* flush the tree list delete queue */
 437         smb_llist_flush(&ssn->s_tree_list);
 438 
 439         mutex_enter(&user->u_mutex);
 440         ASSERT(user->u_refcnt);
 441         user->u_refcnt--;
 442 
 443         switch (user->u_state) {
 444         case SMB_USER_STATE_LOGGING_OFF:
 445                 if (user->u_refcnt == 0) {
 446                         smb_session_t *ssn = user->u_session;
 447                         user->u_state = SMB_USER_STATE_LOGGED_OFF;
 448                         smb_llist_post(&ssn->s_user_list, user,
 449                             smb_user_delete);
 450                 }
 451                 break;
 452 
 453         case SMB_USER_STATE_LOGGING_ON:
 454         case SMB_USER_STATE_LOGGED_ON:
 455                 break;
 456 
 457         case SMB_USER_STATE_LOGGED_OFF:
 458         default:
 459                 ASSERT(0);
 460                 break;
 461         }
 462         mutex_exit(&user->u_mutex);
 463 }
 464 
 465 /*
 466  * Timeout handler for user logons that stay too long in
 467  * state SMB_USER_STATE_LOGGING_ON.  This is setup by a
 468  * timeout call in smb_authsock_open, and called in a
 469  * callout thread, so schedule a taskq job to do the
 470  * real work of logging off this user.
 471  */
 472 void
 473 smb_user_auth_tmo(void *arg)
 474 {
 475         smb_user_t *user = arg;
 476         smb_request_t *sr;
 477 
 478         SMB_USER_VALID(user);
 479 
 480         /*
 481          * If we can't allocate a request, it means the
 482          * session is being torn down, so nothing to do.
 483          */
 484         sr = smb_request_alloc(user->u_session, 0);
 485         if (sr == NULL)
 486                 return;
 487 
 488         /*
 489          * Check user state, and take a hold if it's
 490          * still logging on.  If not, we're done.
 491          */
 492         mutex_enter(&user->u_mutex);
 493         if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
 494                 mutex_exit(&user->u_mutex);
 495                 smb_request_free(sr);
 496                 return;
 497         }
 498         /* smb_user_hold_internal */
 499         user->u_refcnt++;
 500         mutex_exit(&user->u_mutex);
 501 
 502         /*
 503          * The user hold is given to the SR, and released in
 504          * smb_user_logoff_tq / smb_request_free
 505          */
 506         sr->uid_user = user;
 507         sr->user_cr = user->u_cred;
 508         sr->sr_state = SMB_REQ_STATE_SUBMITTED;
 509 
 510         (void) taskq_dispatch(
 511             user->u_server->sv_worker_pool,
 512             smb_user_logoff_tq, sr, TQ_SLEEP);
 513 }
 514 
 515 /*
 516  * Helper for smb_user_auth_tmo()
 517  */
 518 static void
 519 smb_user_logoff_tq(void *arg)
 520 {
 521         smb_request_t   *sr = arg;
 522 
 523         SMB_REQ_VALID(sr);
 524 
 525         mutex_enter(&sr->sr_mutex);
 526         sr->sr_worker = curthread;
 527         sr->sr_state = SMB_REQ_STATE_ACTIVE;
 528         mutex_exit(&sr->sr_mutex);
 529 
 530         smb_user_logoff(sr->uid_user);
 531 
 532         sr->sr_state = SMB_REQ_STATE_COMPLETED;
 533         smb_request_free(sr);
 534 }
 535 
 536 /*
 537  * Determine whether or not the user is an administrator.
 538  * Members of the administrators group have administrative rights.
 539  */
 540 boolean_t
 541 smb_user_is_admin(smb_user_t *user)
 542 {
 543 #ifdef  _KERNEL
 544         char            sidstr[SMB_SID_STRSZ];
 545         ksidlist_t      *ksidlist;
 546         ksid_t          ksid1;
 547         ksid_t          *ksid2;
 548         int             i;
 549 #endif  /* _KERNEL */
 550         boolean_t       rc = B_FALSE;
 551 
 552         ASSERT(user);
 553         ASSERT(user->u_cred);
 554 
 555         if (SMB_USER_IS_ADMIN(user))
 556                 return (B_TRUE);
 
 628 {
 629         int             rc = 0;
 630 
 631         ASSERT(user);
 632         ASSERT(user->u_magic == SMB_USER_MAGIC);
 633 
 634         if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
 635                 return (smb_user_enum_private(user, svcenum));
 636 
 637         return (rc);
 638 }
 639 
 640 /* *************************** Static Functions ***************************** */
 641 
 642 /*
 643  * Delete a user.  The tree list should be empty.
 644  *
 645  * Remove the user from the session's user list before freeing resources
 646  * associated with the user.
 647  */
 648 static void
 649 smb_user_delete(void *arg)
 650 {
 651         smb_session_t   *session;
 652         smb_user_t      *user = (smb_user_t *)arg;
 653         uint32_t        ucount;
 654 
 655         SMB_USER_VALID(user);
 656         ASSERT(user->u_refcnt == 0);
 657         ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
 658         ASSERT(user->u_authsock == NULL);
 659         ASSERT(user->u_auth_tmo == NULL);
 660 
 661         session = user->u_session;
 662 
 663         smb_server_dec_users(session->s_server);
 664         smb_llist_enter(&session->s_user_list, RW_WRITER);
 665         smb_llist_remove(&session->s_user_list, user);
 666         smb_idpool_free(&session->s_uid_pool, user->u_uid);
 667         ucount = smb_llist_get_count(&session->s_user_list);
 668         smb_llist_exit(&session->s_user_list);
 669 
 670         if (ucount == 0) {
 671                 smb_rwx_rwenter(&session->s_lock, RW_WRITER);
 672                 session->s_state = SMB_SESSION_STATE_SHUTDOWN;
 673                 smb_rwx_cvbcast(&session->s_lock);
 674                 smb_rwx_rwexit(&session->s_lock);
 675         }
 676 
 677         /*
 678          * This user is no longer on s_user_list, however...
 679          *
 680          * This is called via smb_llist_post, which means it may run
 681          * BEFORE smb_user_release drops u_mutex (if another thread
 682          * flushes the delete queue before we do).  Synchronize.
 683          */
 684         mutex_enter(&user->u_mutex);
 685         mutex_exit(&user->u_mutex);
 686 
 687         user->u_magic = (uint32_t)~SMB_USER_MAGIC;
 688         mutex_destroy(&user->u_mutex);
 689         if (user->u_cred)
 690                 crfree(user->u_cred);
 691         if (user->u_privcred)
 692                 crfree(user->u_privcred);
 693         smb_mem_free(user->u_name);
 694         smb_mem_free(user->u_domain);
 695         kmem_cache_free(smb_cache_user, user);
 696 }
 697 
 698 cred_t *
 699 smb_user_getcred(smb_user_t *user)
 700 {
 701         return (user->u_cred);
 702 }
 703 
 
 797 }
 798 
 799 void
 800 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
 801 {
 802         smb_session_t   *session;
 803         char            *buf;
 804 
 805         ASSERT(user);
 806         ASSERT(user->u_domain);
 807         ASSERT(user->u_name);
 808 
 809         session = user->u_session;
 810         ASSERT(session);
 811         ASSERT(session->workstation);
 812 
 813         info->ui_session_id = session->s_kid;
 814         info->ui_native_os = session->native_os;
 815         info->ui_ipaddr = session->ipaddr;
 816         info->ui_numopens = session->s_file_cnt;
 817         info->ui_logon_time = user->u_logon_time;
 818         info->ui_flags = user->u_flags;
 819         info->ui_posix_uid = crgetuid(user->u_cred);
 820 
 821         info->ui_domain_len = user->u_domain_len;
 822         info->ui_domain = smb_mem_strdup(user->u_domain);
 823 
 824         info->ui_account_len = user->u_name_len;
 825         info->ui_account = smb_mem_strdup(user->u_name);
 826 
 827         buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 828         smb_session_getclient(session, buf, MAXNAMELEN);
 829         info->ui_workstation_len = strlen(buf) + 1;
 830         info->ui_workstation = smb_mem_strdup(buf);
 831         kmem_free(buf, MAXNAMELEN);
 832 }
 833 
 834 void
 835 smb_user_netinfo_fini(smb_netuserinfo_t *info)
 836 {
 837         if (info == NULL)
 838                 return;
 839 
 840         if (info->ui_domain)
 841                 smb_mem_free(info->ui_domain);
 842         if (info->ui_account)
 843                 smb_mem_free(info->ui_account);
 844         if (info->ui_workstation)
 845                 smb_mem_free(info->ui_workstation);
 846 
 847         bzero(info, sizeof (smb_netuserinfo_t));
 848 }
 849 
 850 /*
 851  * Tell smbd this user is going away so it can clean up their
 852  * audit session, autohome dir, etc.
 853  *
 854  * Note that when we're shutting down, smbd will already have set
 855  * smbd.s_shutting_down and therefore will ignore door calls.
 856  * Skip this during shutdown to reduce upcall noise.
 857  */
 858 static void
 859 smb_user_auth_logoff(smb_user_t *user)
 860 {
 861         smb_server_t *sv = user->u_server;
 862         uint32_t audit_sid;
 863 
 864         if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
 865                 return;
 866 
 867         audit_sid = user->u_audit_sid;
 868         (void) smb_kdoor_upcall(sv, SMB_DR_USER_AUTH_LOGOFF,
 869             &audit_sid, xdr_uint32_t, NULL, NULL);
 870 }
 871 
 872 boolean_t
 873 smb_is_same_user(cred_t *cr1, cred_t *cr2)
 874 {
 875         ksid_t *ks1 = crgetsid(cr1, KSID_USER);
 876         ksid_t *ks2 = crgetsid(cr2, KSID_USER);
 877 
 878         return (ks1->ks_rid == ks2->ks_rid &&
 879             strcmp(ks1->ks_domain->kd_name, ks2->ks_domain->kd_name) == 0);
 880 }
 |