Print this page
    
NEX-19040 SMB2 session ID re-use can confuse clients
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-18761 panic in smb_ofile_free with vdbench
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-16604 Windows 10 SMB client exhausts smbauth sockets
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-16519 Panic while running IOmeter to a pool through an SMB share
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-7267 Codenomicon causes panic in smb_authsock_cancel
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-3553 SMB2/3 durable handles
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3776 SMB should handle PreviousSessionID
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-5560 smb2 should use 64-bit server-global uids
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-5537 Want reference counts for users, trees...
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-2485 SMB authentication flood handled poorly
SMB-56 extended security NTLMSSP, inbound
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb_user.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_user.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
  24   24   * Copyright (c) 2016 by Delphix. All rights reserved.
  25   25   */
  26   26  
  27   27  /*
  28   28   * General Structures Layout
  29   29   * -------------------------
  30   30   *
  31   31   * This is a simplified diagram showing the relationship between most of the
  32   32   * main structures.
  33   33   *
  34   34   * +-------------------+
  35   35   * |     SMB_INFO      |
  36   36   * +-------------------+
  37   37   *          |
  38   38   *          |
  39   39   *          v
  40   40   * +-------------------+       +-------------------+      +-------------------+
  41   41   * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
  42   42   * +-------------------+       +-------------------+      +-------------------+
  43   43   *   |          |
  44   44   *   |          |
  45   45   *   |          v
  46   46   *   |  +-------------------+     +-------------------+   +-------------------+
  47   47   *   |  |       USER        |<--->|       USER        |...|       USER        |
  48   48   *   |  +-------------------+     +-------------------+   +-------------------+
  49   49   *   |
  50   50   *   |
  51   51   *   v
  52   52   * +-------------------+       +-------------------+      +-------------------+
  53   53   * |       TREE        |<----->|       TREE        |......|       TREE        |
  54   54   * +-------------------+       +-------------------+      +-------------------+
  55   55   *      |         |
  56   56   *      |         |
  57   57   *      |         v
  58   58   *      |     +-------+       +-------+      +-------+
  59   59   *      |     | OFILE |<----->| OFILE |......| OFILE |
  60   60   *      |     +-------+       +-------+      +-------+
  61   61   *      |
  62   62   *      |
  63   63   *      v
  64   64   *  +-------+       +------+      +------+
  65   65   *  | ODIR  |<----->| ODIR |......| ODIR |
  66   66   *  +-------+       +------+      +------+
  67   67   *
  68   68   *
  69   69   * User State Machine
  70   70   * ------------------
  71   71   *
  72   72   *
  73   73   *                  | T0:  Creation/Allocation
  74   74   *                  |      (1st session setup)
  75   75   *                  v
  76   76   *    +-----------------------------+
  77   77   *    |  SMB_USER_STATE_LOGGING_ON  |<----------+
  78   78   *    +-----------------------------+    addl. session setup
  79   79   *                  |           |       (more proc. required)
  80   80   *                  | T2        |               ^
  81   81   *                  |           |               | T1: (cont.)
  82   82   *                  |           +------->-------?
  83   83   *                  v                           | T3: (fail)
  84   84   *    +-----------------------------+           v
  85   85   *    |  SMB_USER_STATE_LOGGED_ON   |       (logged off)
  86   86   *    +-----------------------------+
  87   87   *                  |
  88   88   *                  | T4
  89   89   *                  |
  90   90   *                  v
  91   91   *    +-----------------------------+
  92   92   *    |  SMB_USER_STATE_LOGGING_OFF |
  93   93   *    +-----------------------------+
  94   94   *                  |
  95   95   *                  | T5
  96   96   *                  |
  97   97   *                  v
  98   98   *    +-----------------------------+    T6
  99   99   *    |  SMB_USER_STATE_LOGGED_OFF  |----------> Deletion/Free
 100  100   *    +-----------------------------+
 101  101   *
 102  102   * SMB_USER_STATE_LOGGING_ON
 103  103   *
 104  104   *    While in this state:
 105  105   *      - The user is in the list of users for their session.
 106  106   *      - References will be given out ONLY for session setup.
 107  107   *      - This user can not access anything yet.
 108  108   *
 109  109   * SMB_USER_STATE_LOGGED_ON
 110  110   *
 111  111   *    While in this state:
 112  112   *      - The user is in the list of users for their session.
 113  113   *      - References will be given out if the user is looked up.
 114  114   *      - The user can access files and pipes.
 115  115   *
 116  116   * SMB_USER_STATE_LOGGING_OFF
 117  117   *
 118  118   *    While in this state:
 119  119   *      - The user is in the list of users for their session.
 120  120   *      - References will not be given out if the user is looked up.
 121  121   *      - The trees the user connected are being disconnected.
 122  122   *      - The resources associated with the user remain.
 123  123   *
 124  124   * SMB_USER_STATE_LOGGED_OFF
 125  125   *
 126  126   *    While in this state:
 127  127   *      - The user is queued in the list of users of their session.
 128  128   *      - References will not be given out if the user is looked up.
 129  129   *      - The user has no more trees connected.
 130  130   *      - The resources associated with the user remain.
 131  131   *
 132  132   * Transition T0
 133  133   *
 134  134   *    First request in an SMB Session Setup sequence creates a
 135  135   *    new user object and adds it to the list of users for
 136  136   *    this session.  User UID is assigned and returned.
 137  137   *
 138  138   * Transition T1
 139  139   *
 140  140   *    Subsequent SMB Session Setup requests (on the same UID
 141  141   *    assigned in T0) update the state of this user object,
 142  142   *    communicating with smbd for the crypto work.
 143  143   *
 144  144   * Transition T2
 145  145   *
 146  146   *    If the SMB Session Setup sequence is successful, T2
 147  147   *    makes the new user object available for requests.
 148  148   *
 149  149   * Transition T3
 150  150   *
 151  151   *    If an Session Setup request gets an error other than
 152  152   *    the expected "more processing required", then T3
 153  153   *    leads to state "LOGGED_OFF" and then tear-down of the
 154  154   *    partially constructed user.
 155  155   *
 156  156   * Transition T4
 157  157   *
 158  158   *    Normal SMB User Logoff request, or session tear-down.
 159  159   *
 160  160   * Transition T5
 161  161   *
 162  162   *    This transition occurs in smb_user_release(). The resources associated
 163  163   *    with the user are deleted as well as the user. For the transition to
 164  164   *    occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the
 165  165   *    reference count be zero.
 166  166   *
 167  167   * Comments
 168  168   * --------
 169  169   *
 170  170   *    The state machine of the user structures is controlled by 3 elements:
 171  171   *      - The list of users of the session they belong to.
 172  172   *      - The mutex embedded in the structure itself.
 173  173   *      - The reference count.
  
    | 
      ↓ open down ↓ | 
    140 lines elided | 
    
      ↑ open up ↑ | 
  
 174  174   *
 175  175   *    There's a mutex embedded in the user structure used to protect its fields
 176  176   *    and there's a lock embedded in the list of users of a session. To
 177  177   *    increment or to decrement the reference count the mutex must be entered.
 178  178   *    To insert the user into the list of users of the session and to remove
 179  179   *    the user from it, the lock must be entered in RW_WRITER mode.
 180  180   *
 181  181   *    Rules of access to a user structure:
 182  182   *
 183  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.
      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.
 185  187   *
 186  188   *    2) All actions applied to a user require a reference count.
 187  189   *
 188  190   *    3) There are 2 ways of getting a reference count. One is when the user
 189  191   *       logs in. The other when the user is looked up.
 190  192   *
 191  193   *    It should be noted that the reference count of a user registers the
 192  194   *    number of references to the user in other structures (such as an smb
 193  195   *    request). The reference count is not incremented in these 2 instances:
 194  196   *
 195  197   *    1) The user is logged in. An user is anchored by their state. If there's
 196  198   *       no activity involving a user currently logged in, the reference
 197  199   *       count of that user is zero.
 198  200   *
 199  201   *    2) The user is queued in the list of users of the session. The fact of
 200  202   *       being queued in that list is NOT registered by incrementing the
  
    | 
      ↓ open down ↓ | 
    6 lines elided | 
    
      ↑ open up ↑ | 
  
 201  203   *       reference count.
 202  204   */
 203  205  #include <sys/types.h>
 204  206  #include <sys/sid.h>
 205  207  #include <sys/priv_names.h>
 206  208  #include <smbsrv/smb_kproto.h>
 207  209  #include <smbsrv/smb_door.h>
 208  210  
 209  211  #define ADMINISTRATORS_SID      "S-1-5-32-544"
 210  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 *);
 211  218  static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
 212  219  static void smb_user_auth_logoff(smb_user_t *);
      220 +static void smb_user_logoff_tq(void *);
 213  221  
 214      -
 215  222  /*
 216  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.
 217  231   */
 218  232  smb_user_t *
 219  233  smb_user_new(smb_session_t *session)
 220  234  {
 221  235          smb_user_t      *user;
      236 +        uint_t          gen;    // generation (low 3 bits of ssnid)
 222  237  
 223  238          ASSERT(session);
 224  239          ASSERT(session->s_magic == SMB_SESSION_MAGIC);
 225  240  
 226  241          user = kmem_cache_alloc(smb_cache_user, KM_SLEEP);
      242 +        gen = (user->u_ssnid + 1) & 7;
 227  243          bzero(user, sizeof (smb_user_t));
 228  244  
 229  245          user->u_refcnt = 1;
 230  246          user->u_session = session;
 231  247          user->u_server = session->s_server;
 232  248          user->u_logon_time = gethrestime_sec();
 233  249  
 234  250          if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid))
 235  251                  goto errout;
      252 +        user->u_ssnid = SMB_USER_SSNID(user) + gen;
 236  253  
 237  254          mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
 238  255          user->u_state = SMB_USER_STATE_LOGGING_ON;
 239  256          user->u_magic = SMB_USER_MAGIC;
 240  257  
 241  258          smb_llist_enter(&session->s_user_list, RW_WRITER);
 242  259          smb_llist_insert_tail(&session->s_user_list, user);
 243  260          smb_llist_exit(&session->s_user_list);
 244  261          smb_server_inc_users(session->s_server);
 245  262  
 246  263          return (user);
 247  264  
 248  265  errout:
 249  266          if (user->u_uid != 0)
 250  267                  smb_idpool_free(&session->s_uid_pool, user->u_uid);
 251  268          kmem_cache_free(smb_cache_user, user);
 252  269          return (NULL);
 253  270  }
 254  271  
 255  272  /*
 256  273   * Fill in the details of a user, meaning a transition
 257  274   * from state LOGGING_ON to state LOGGED_ON.
 258  275   */
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
 259  276  int
 260  277  smb_user_logon(
 261  278      smb_user_t          *user,
 262  279      cred_t              *cr,
 263  280      char                *domain_name,
 264  281      char                *account_name,
 265  282      uint32_t            flags,
 266  283      uint32_t            privileges,
 267  284      uint32_t            audit_sid)
 268  285  {
      286 +        ksocket_t authsock = NULL;
 269  287  
 270  288          ASSERT(user->u_magic == SMB_USER_MAGIC);
 271  289          ASSERT(cr);
 272  290          ASSERT(account_name);
 273  291          ASSERT(domain_name);
 274  292  
 275  293          mutex_enter(&user->u_mutex);
 276  294  
 277  295          if (user->u_state != SMB_USER_STATE_LOGGING_ON) {
 278  296                  mutex_exit(&user->u_mutex);
 279  297                  return (-1);
 280  298          }
 281  299  
 282      -        smb_authsock_close(user);
      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 +        }
 283  310  
 284  311          user->u_state = SMB_USER_STATE_LOGGED_ON;
 285  312          user->u_flags = flags;
 286  313          user->u_name_len = strlen(account_name) + 1;
 287  314          user->u_domain_len = strlen(domain_name) + 1;
 288  315          user->u_name = smb_mem_strdup(account_name);
 289  316          user->u_domain = smb_mem_strdup(domain_name);
 290  317          user->u_audit_sid = audit_sid;
 291  318  
 292  319          smb_user_setcred(user, cr, privileges);
 293  320  
 294  321          mutex_exit(&user->u_mutex);
 295  322  
      323 +        /* This close can block, so not under the mutex. */
      324 +        if (authsock != NULL)
      325 +                smb_authsock_close(user, authsock);
      326 +
 296  327          return (0);
 297  328  }
 298  329  
 299  330  /*
 300  331   * smb_user_logoff
 301  332   *
 302      - * Change the user state and disconnect trees.
      333 + * Change the user state to "logging off" and disconnect trees.
 303  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".
 304  338   */
 305  339  void
 306  340  smb_user_logoff(
 307  341      smb_user_t          *user)
 308  342  {
      343 +        ksocket_t authsock = NULL;
      344 +
 309  345          ASSERT(user->u_magic == SMB_USER_MAGIC);
 310  346  
 311  347          mutex_enter(&user->u_mutex);
 312  348          ASSERT(user->u_refcnt);
 313  349          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);
      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 +                }
 318  363                  break;
 319      -        }
 320  364  
 321      -        case SMB_USER_STATE_LOGGED_ON: {
      365 +        case SMB_USER_STATE_LOGGED_ON:
 322  366                  /*
 323  367                   * The user is moved into a state indicating that the log off
 324  368                   * process has started.
 325  369                   */
 326  370                  user->u_state = SMB_USER_STATE_LOGGING_OFF;
 327  371                  mutex_exit(&user->u_mutex);
 328  372                  smb_session_disconnect_owned_trees(user->u_session, user);
 329  373                  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  374                  break;
 334      -        }
      375 +
 335  376          case SMB_USER_STATE_LOGGED_OFF:
 336  377          case SMB_USER_STATE_LOGGING_OFF:
      378 +                mutex_exit(&user->u_mutex);
 337  379                  break;
 338  380  
 339  381          default:
 340  382                  ASSERT(0);
      383 +                mutex_exit(&user->u_mutex);
 341  384                  break;
 342  385          }
 343      -        mutex_exit(&user->u_mutex);
 344  386  }
 345  387  
 346  388  /*
 347  389   * Take a reference on a user.  Do not return a reference unless the user is in
 348  390   * the logged-in state.
 349  391   */
 350  392  boolean_t
 351  393  smb_user_hold(smb_user_t *user)
 352  394  {
 353  395          SMB_USER_VALID(user);
 354  396  
 355  397          mutex_enter(&user->u_mutex);
 356  398  
 357  399          if (user->u_state == SMB_USER_STATE_LOGGED_ON) {
 358  400                  user->u_refcnt++;
 359  401                  mutex_exit(&user->u_mutex);
 360  402                  return (B_TRUE);
 361  403          }
 362  404  
 363  405          mutex_exit(&user->u_mutex);
 364  406          return (B_FALSE);
 365  407  }
 366  408  
 367  409  /*
 368  410   * Unconditionally take a reference on a user.
 369  411   */
 370  412  void
 371  413  smb_user_hold_internal(smb_user_t *user)
 372  414  {
 373  415          SMB_USER_VALID(user);
 374  416  
 375  417          mutex_enter(&user->u_mutex);
 376  418          user->u_refcnt++;
 377  419          mutex_exit(&user->u_mutex);
 378  420  }
 379  421  
  
    | 
      ↓ open down ↓ | 
    26 lines elided | 
    
      ↑ open up ↑ | 
  
 380  422  /*
 381  423   * Release a reference on a user.  If the reference count falls to
 382  424   * zero and the user has logged off, post the object for deletion.
 383  425   * Object deletion is deferred to avoid modifying a list while an
 384  426   * iteration may be in progress.
 385  427   */
 386  428  void
 387  429  smb_user_release(
 388  430      smb_user_t          *user)
 389  431  {
 390      -        ASSERT(user->u_magic == SMB_USER_MAGIC);
      432 +        smb_session_t *ssn = user->u_session;
 391  433  
      434 +        SMB_USER_VALID(user);
      435 +
      436 +        /* flush the tree list delete queue */
      437 +        smb_llist_flush(&ssn->s_tree_list);
      438 +
 392  439          mutex_enter(&user->u_mutex);
 393  440          ASSERT(user->u_refcnt);
 394  441          user->u_refcnt--;
 395  442  
 396  443          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);
      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 +                }
 400  451                  break;
 401  452  
 402  453          case SMB_USER_STATE_LOGGING_ON:
 403  454          case SMB_USER_STATE_LOGGED_ON:
 404      -        case SMB_USER_STATE_LOGGING_OFF:
 405  455                  break;
 406  456  
      457 +        case SMB_USER_STATE_LOGGED_OFF:
 407  458          default:
 408  459                  ASSERT(0);
 409  460                  break;
 410  461          }
 411  462          mutex_exit(&user->u_mutex);
 412  463  }
 413  464  
 414  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 +/*
 415  537   * Determine whether or not the user is an administrator.
 416  538   * Members of the administrators group have administrative rights.
 417  539   */
 418  540  boolean_t
 419  541  smb_user_is_admin(smb_user_t *user)
 420  542  {
 421  543  #ifdef  _KERNEL
 422  544          char            sidstr[SMB_SID_STRSZ];
 423  545          ksidlist_t      *ksidlist;
 424  546          ksid_t          ksid1;
 425  547          ksid_t          *ksid2;
 426  548          int             i;
 427  549  #endif  /* _KERNEL */
 428  550          boolean_t       rc = B_FALSE;
 429  551  
 430  552          ASSERT(user);
 431  553          ASSERT(user->u_cred);
 432  554  
 433  555          if (SMB_USER_IS_ADMIN(user))
 434  556                  return (B_TRUE);
 435  557  
 436  558  #ifdef  _KERNEL
 437  559          bzero(&ksid1, sizeof (ksid_t));
 438  560          (void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ);
 439  561          ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0);
 440  562          ksid1.ks_domain = ksid_lookupdomain(sidstr);
 441  563  
 442  564          ksidlist = crgetsidlist(user->u_cred);
 443  565          ASSERT(ksidlist);
 444  566          ASSERT(ksid1.ks_domain);
 445  567          ASSERT(ksid1.ks_domain->kd_name);
 446  568  
 447  569          i = 0;
 448  570          ksid2 = crgetsid(user->u_cred, KSID_USER);
 449  571          do {
 450  572                  ASSERT(ksid2->ks_domain);
 451  573                  ASSERT(ksid2->ks_domain->kd_name);
 452  574  
 453  575                  if (strcmp(ksid1.ks_domain->kd_name,
 454  576                      ksid2->ks_domain->kd_name) == 0 &&
 455  577                      ksid1.ks_rid == ksid2->ks_rid) {
 456  578                          user->u_flags |= SMB_USER_FLAG_ADMIN;
 457  579                          rc = B_TRUE;
 458  580                          break;
 459  581                  }
 460  582  
 461  583                  ksid2 = &ksidlist->ksl_sids[i];
 462  584          } while (i++ < ksidlist->ksl_nsid);
 463  585  
 464  586          ksid_rele(&ksid1);
 465  587  #endif  /* _KERNEL */
 466  588          return (rc);
 467  589  }
 468  590  
 469  591  /*
 470  592   * This function should be called with a hold on the user.
 471  593   */
 472  594  boolean_t
 473  595  smb_user_namecmp(smb_user_t *user, const char *name)
 474  596  {
 475  597          char            *fq_name;
 476  598          boolean_t       match;
 477  599  
 478  600          if (smb_strcasecmp(name, user->u_name, 0) == 0)
 479  601                  return (B_TRUE);
 480  602  
 481  603          fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 482  604  
 483  605          (void) snprintf(fq_name, MAXNAMELEN, "%s\\%s",
 484  606              user->u_domain, user->u_name);
 485  607  
 486  608          match = (smb_strcasecmp(name, fq_name, 0) == 0);
 487  609          if (!match) {
 488  610                  (void) snprintf(fq_name, MAXNAMELEN, "%s@%s",
 489  611                      user->u_name, user->u_domain);
 490  612  
 491  613                  match = (smb_strcasecmp(name, fq_name, 0) == 0);
 492  614          }
 493  615  
 494  616          kmem_free(fq_name, MAXNAMELEN);
 495  617          return (match);
 496  618  }
 497  619  
 498  620  /*
 499  621   * If the enumeration request is for user data, handle the request
 500  622   * here.  Otherwise, pass it on to the trees.
 501  623   *
 502  624   * This function should be called with a hold on the user.
 503  625   */
 504  626  int
 505  627  smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
 506  628  {
 507  629          int             rc = 0;
 508  630  
 509  631          ASSERT(user);
 510  632          ASSERT(user->u_magic == SMB_USER_MAGIC);
 511  633  
 512  634          if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
 513  635                  return (smb_user_enum_private(user, svcenum));
 514  636  
 515  637          return (rc);
  
    | 
      ↓ open down ↓ | 
    91 lines elided | 
    
      ↑ open up ↑ | 
  
 516  638  }
 517  639  
 518  640  /* *************************** Static Functions ***************************** */
 519  641  
 520  642  /*
 521  643   * Delete a user.  The tree list should be empty.
 522  644   *
 523  645   * Remove the user from the session's user list before freeing resources
 524  646   * associated with the user.
 525  647   */
 526      -void
      648 +static void
 527  649  smb_user_delete(void *arg)
 528  650  {
 529  651          smb_session_t   *session;
 530  652          smb_user_t      *user = (smb_user_t *)arg;
      653 +        uint32_t        ucount;
 531  654  
 532  655          SMB_USER_VALID(user);
 533  656          ASSERT(user->u_refcnt == 0);
 534  657          ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
 535  658          ASSERT(user->u_authsock == NULL);
      659 +        ASSERT(user->u_auth_tmo == NULL);
 536  660  
 537  661          session = user->u_session;
      662 +
      663 +        smb_server_dec_users(session->s_server);
 538  664          smb_llist_enter(&session->s_user_list, RW_WRITER);
 539  665          smb_llist_remove(&session->s_user_list, user);
 540  666          smb_idpool_free(&session->s_uid_pool, user->u_uid);
      667 +        ucount = smb_llist_get_count(&session->s_user_list);
 541  668          smb_llist_exit(&session->s_user_list);
 542  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 +         */
 543  684          mutex_enter(&user->u_mutex);
 544  685          mutex_exit(&user->u_mutex);
 545  686  
 546  687          user->u_magic = (uint32_t)~SMB_USER_MAGIC;
 547  688          mutex_destroy(&user->u_mutex);
 548  689          if (user->u_cred)
 549  690                  crfree(user->u_cred);
 550  691          if (user->u_privcred)
 551  692                  crfree(user->u_privcred);
 552  693          smb_mem_free(user->u_name);
 553  694          smb_mem_free(user->u_domain);
 554  695          kmem_cache_free(smb_cache_user, user);
 555  696  }
 556  697  
 557  698  cred_t *
 558  699  smb_user_getcred(smb_user_t *user)
 559  700  {
 560  701          return (user->u_cred);
 561  702  }
 562  703  
 563  704  cred_t *
 564  705  smb_user_getprivcred(smb_user_t *user)
 565  706  {
 566  707          return ((user->u_privcred)? user->u_privcred : user->u_cred);
 567  708  }
 568  709  
 569  710  #ifdef  _KERNEL
 570  711  /*
 571  712   * Assign the user cred and privileges.
 572  713   *
 573  714   * If the user has backup and/or restore privleges, dup the cred
 574  715   * and add those privileges to this new privileged cred.
 575  716   */
 576  717  void
 577  718  smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
 578  719  {
 579  720          cred_t *privcred = NULL;
 580  721  
 581  722          ASSERT(cr);
 582  723          crhold(cr);
 583  724  
 584  725          if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
 585  726                  privcred = crdup(cr);
 586  727  
 587  728          if (privcred != NULL) {
 588  729                  if (privileges & SMB_USER_PRIV_BACKUP) {
 589  730                          (void) crsetpriv(privcred, PRIV_FILE_DAC_READ,
 590  731                              PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
 591  732                  }
 592  733  
 593  734                  if (privileges & SMB_USER_PRIV_RESTORE) {
 594  735                          (void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE,
 595  736                              PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
 596  737                              PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
 597  738                              PRIV_FILE_OWNER, PRIV_FILE_SETID,
 598  739                              PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL);
 599  740                  }
 600  741          }
 601  742  
 602  743          user->u_cred = cr;
 603  744          user->u_privcred = privcred;
 604  745          user->u_privileges = privileges;
 605  746  }
 606  747  #endif  /* _KERNEL */
 607  748  
 608  749  /*
 609  750   * Private function to support smb_user_enum.
 610  751   */
 611  752  static int
 612  753  smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum)
 613  754  {
 614  755          uint8_t *pb;
 615  756          uint_t nbytes;
 616  757          int rc;
 617  758  
 618  759          if (svcenum->se_nskip > 0) {
 619  760                  svcenum->se_nskip--;
 620  761                  return (0);
 621  762          }
 622  763  
 623  764          if (svcenum->se_nitems >= svcenum->se_nlimit) {
 624  765                  svcenum->se_nitems = svcenum->se_nlimit;
 625  766                  return (0);
 626  767          }
 627  768  
 628  769          pb = &svcenum->se_buf[svcenum->se_bused];
 629  770          rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes);
 630  771          if (rc == 0) {
 631  772                  svcenum->se_bavail -= nbytes;
 632  773                  svcenum->se_bused += nbytes;
 633  774                  svcenum->se_nitems++;
 634  775          }
 635  776  
 636  777          return (rc);
 637  778  }
 638  779  
 639  780  /*
 640  781   * Encode the NetInfo for a user into a buffer.  NetInfo contains
 641  782   * information that is often needed in user space to support RPC
 642  783   * requests.
 643  784   */
 644  785  int
 645  786  smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen,
 646  787      uint32_t *nbytes)
 647  788  {
 648  789          smb_netuserinfo_t       info;
 649  790          int                     rc;
 650  791  
 651  792          smb_user_netinfo_init(user, &info);
 652  793          rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes);
 653  794          smb_user_netinfo_fini(&info);
 654  795  
 655  796          return (rc);
 656  797  }
 657  798  
 658  799  void
 659  800  smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info)
 660  801  {
 661  802          smb_session_t   *session;
 662  803          char            *buf;
 663  804  
 664  805          ASSERT(user);
 665  806          ASSERT(user->u_domain);
  
    | 
      ↓ open down ↓ | 
    113 lines elided | 
    
      ↑ open up ↑ | 
  
 666  807          ASSERT(user->u_name);
 667  808  
 668  809          session = user->u_session;
 669  810          ASSERT(session);
 670  811          ASSERT(session->workstation);
 671  812  
 672  813          info->ui_session_id = session->s_kid;
 673  814          info->ui_native_os = session->native_os;
 674  815          info->ui_ipaddr = session->ipaddr;
 675  816          info->ui_numopens = session->s_file_cnt;
 676      -        info->ui_smb_uid = user->u_uid;
 677  817          info->ui_logon_time = user->u_logon_time;
 678  818          info->ui_flags = user->u_flags;
 679  819          info->ui_posix_uid = crgetuid(user->u_cred);
 680  820  
 681  821          info->ui_domain_len = user->u_domain_len;
 682  822          info->ui_domain = smb_mem_strdup(user->u_domain);
 683  823  
 684  824          info->ui_account_len = user->u_name_len;
 685  825          info->ui_account = smb_mem_strdup(user->u_name);
 686  826  
 687  827          buf = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 688  828          smb_session_getclient(session, buf, MAXNAMELEN);
 689  829          info->ui_workstation_len = strlen(buf) + 1;
 690  830          info->ui_workstation = smb_mem_strdup(buf);
 691  831          kmem_free(buf, MAXNAMELEN);
 692  832  }
 693  833  
 694  834  void
 695  835  smb_user_netinfo_fini(smb_netuserinfo_t *info)
 696  836  {
 697  837          if (info == NULL)
 698  838                  return;
 699  839  
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
 700  840          if (info->ui_domain)
 701  841                  smb_mem_free(info->ui_domain);
 702  842          if (info->ui_account)
 703  843                  smb_mem_free(info->ui_account);
 704  844          if (info->ui_workstation)
 705  845                  smb_mem_free(info->ui_workstation);
 706  846  
 707  847          bzero(info, sizeof (smb_netuserinfo_t));
 708  848  }
 709  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 + */
 710  858  static void
 711  859  smb_user_auth_logoff(smb_user_t *user)
 712  860  {
 713      -        uint32_t audit_sid = user->u_audit_sid;
      861 +        smb_server_t *sv = user->u_server;
      862 +        uint32_t audit_sid;
 714  863  
 715      -        (void) smb_kdoor_upcall(user->u_server, SMB_DR_USER_AUTH_LOGOFF,
      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,
 716  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);
 717  880  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX