Print this page
    
NEX-19781 SMB service shutdown hang with threads in smb_authsock_recv
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Matt Barden <matt.barden@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-13644 File access audit logging
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-9497 SMB should bypass ACL traverse checking
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10231 SMB logon fails in fksmbd
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-7267 Codenomicon causes panic in smb_authsock_cancel (lint)
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-6888 Defensics test causes panic due to bad free
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-5560 smb2 should use 64-bit server-global uids
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-2522 svcadm disable network/smb/server may hang
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3610 CLONE NEX-3591 SMB3 signing
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
NEX-3080 SMB1 signing problem with Kerberos auth.
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-2485 SMB authentication flood handled poorly
SUP-866 smbd lwps stuck in libsocket recv() for no apparent reason
SMB-152 mem leak in smb_authenticate_ext/smb_authsock_sendrecv
SMB-55 SMB2 signing
OS-6 mpathadm leads to panic in vhci_mpapi_sync_lu_oid_list
SMB-85 Codenomicon: SMB2 TC: 16193 - Panic in smb_authenticate_ext
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-56 extended security NTLMSSP, inbound
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb_authenticate.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_authenticate.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 2015 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * Authentication support for SMB session setup
  28   28   */
  29   29  
  30   30  #include <sys/types.h>
  31   31  #include <sys/sid.h>
  32   32  #include <sys/priv_names.h>
  33   33  #include <sys/socket.h>
  34   34  #include <sys/un.h>
  35   35  #include <netinet/in.h>
  36   36  #include <smbsrv/smb_idmap.h>
  37   37  #include <smbsrv/smb_kproto.h>
  38   38  #include <smbsrv/smb_token.h>
  39   39  
  40      -static uint32_t smb_authsock_open(smb_user_t *);
       40 +static uint32_t smb_authsock_open(smb_request_t *);
  41   41  static int smb_authsock_send(ksocket_t, void *, size_t);
  42   42  static int smb_authsock_recv(ksocket_t, void *, size_t);
  43      -static uint32_t smb_authsock_sendrecv(smb_user_t *, smb_lsa_msg_hdr_t *hdr,
       43 +static uint32_t smb_authsock_sendrecv(smb_request_t *, smb_lsa_msg_hdr_t *hdr,
  44   44                                  void *sndbuf, void **recvbuf);
  45   45  /* void smb_authsock_close(smb_user_t *); kproto.h */
  46   46  
  47   47  static uint32_t smb_auth_do_clinfo(smb_request_t *);
  48   48  static uint32_t smb_auth_do_oldreq(smb_request_t *);
  49   49  static uint32_t smb_auth_get_token(smb_request_t *);
  50   50  static uint32_t smb_priv_xlate(smb_token_t *);
  51   51  
  52   52  /*
  53   53   * Handle old-style session setup (non-extended security)
       54 + * Note: Used only by SMB1
  54   55   *
  55   56   * The user information is passed to smbd for authentication.
  56   57   * If smbd can authenticate the user an access token is returned and we
  57   58   * generate a cred and new user based on the token.
  58   59   */
  59   60  int
  60   61  smb_authenticate_old(smb_request_t *sr)
  61   62  {
  62   63          smb_user_t      *user = NULL;
  63   64          uint32_t        status;
  64   65  
  65   66          user = smb_user_new(sr->session);
  66   67          if (user == NULL)
  67   68                  return (NT_STATUS_TOO_MANY_SESSIONS);
  68   69  
  69   70          /* user cleanup in smb_request_free */
  70   71          sr->uid_user = user;
  71   72          sr->smb_uid = user->u_uid;
       73 +        sr->smb2_ssnid = 0;
  72   74  
  73   75          /*
  74   76           * Open a connection to the local logon service.
  75   77           * If we can't, it may be busy, or not running.
  76   78           * Don't log here - this may be frequent.
  77   79           */
  78      -        if ((status = smb_authsock_open(user)) != 0)
       80 +        if ((status = smb_authsock_open(sr)) != 0)
  79   81                  goto errout;
  80   82  
  81   83          /*
  82   84           * Tell the auth. svc who this client is.
  83   85           */
  84   86          if ((status = smb_auth_do_clinfo(sr)) != 0)
  85   87                  goto errout;
  86   88  
  87   89          /*
  88   90           * Authentication proper
  89   91           */
  90   92          if ((status = smb_auth_do_oldreq(sr)) != 0)
  91   93                  goto errout;
  92   94  
  93   95          /*
  94   96           * Get the final auth. token.
  95   97           */
  96   98          if ((status = smb_auth_get_token(sr)) != 0)
  97   99                  goto errout;
  98  100  
  99  101          return (0);
 100  102  
 101  103  errout:
 102  104          smb_user_logoff(user);
 103  105          return (status);
 104  106  }
 105  107  
 106  108  /*
  
    | 
      ↓ open down ↓ | 
    18 lines elided | 
    
      ↑ open up ↑ | 
  
 107  109   * Build an authentication request message and
 108  110   * send it to the local logon service.
 109  111   */
 110  112  static uint32_t
 111  113  smb_auth_do_oldreq(smb_request_t *sr)
 112  114  {
 113  115          smb_lsa_msg_hdr_t       msg_hdr;
 114  116          smb_logon_t     user_info;
 115  117          XDR             xdrs;
 116  118          smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
 117      -        smb_user_t      *user = sr->uid_user;
 118  119          void            *sbuf = NULL;
 119  120          void            *rbuf = NULL;
 120  121          uint32_t        slen = 0;
 121  122          uint32_t        rlen = 0;
 122  123          uint32_t        status;
 123  124          bool_t          ok;
 124  125  
 125  126          bzero(&user_info, sizeof (smb_logon_t));
 126  127  
 127  128          user_info.lg_level = NETR_NETWORK_LOGON;
 128  129          user_info.lg_username = sinfo->ssi_user;
 129  130          user_info.lg_domain = sinfo->ssi_domain;
 130  131          user_info.lg_workstation = sr->session->workstation;
 131  132          user_info.lg_clnt_ipaddr = sr->session->ipaddr;
 132  133          user_info.lg_local_ipaddr = sr->session->local_ipaddr;
 133  134          user_info.lg_local_port = sr->session->s_local_port;
 134  135          user_info.lg_challenge_key.val = sr->session->challenge_key;
 135  136          user_info.lg_challenge_key.len = sr->session->challenge_len;
 136  137          user_info.lg_nt_password.val = sinfo->ssi_ntpwd;
 137  138          user_info.lg_nt_password.len = sinfo->ssi_ntpwlen;
 138  139          user_info.lg_lm_password.val = sinfo->ssi_lmpwd;
 139  140          user_info.lg_lm_password.len = sinfo->ssi_lmpwlen;
 140  141          user_info.lg_native_os = sr->session->native_os;
 141  142          user_info.lg_native_lm = sr->session->native_lm;
 142  143          /* lg_flags? */
 143  144  
 144  145          slen = xdr_sizeof(smb_logon_xdr, &user_info);
 145  146          sbuf = kmem_alloc(slen, KM_SLEEP);
  
    | 
      ↓ open down ↓ | 
    18 lines elided | 
    
      ↑ open up ↑ | 
  
 146  147          xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE);
 147  148          ok = smb_logon_xdr(&xdrs, &user_info);
 148  149          xdr_destroy(&xdrs);
 149  150          if (!ok) {
 150  151                  status = RPC_NT_BAD_STUB_DATA;
 151  152                  goto out;
 152  153          }
 153  154  
 154  155          msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
 155  156          msg_hdr.lmh_msglen = slen;
 156      -        status = smb_authsock_sendrecv(user, &msg_hdr, sbuf, &rbuf);
      157 +        status = smb_authsock_sendrecv(sr, &msg_hdr, sbuf, &rbuf);
 157  158          if (status != 0)
 158  159                  goto out;
 159  160          rlen = msg_hdr.lmh_msglen;
 160  161          kmem_free(sbuf, slen);
 161  162          sbuf = NULL;
 162  163  
 163  164          /*
 164  165           * Decode the response message.
 165  166           */
 166  167          switch (msg_hdr.lmh_msgtype) {
 167  168  
 168  169          case LSA_MTYPE_OK:
 169  170                  status = 0;
 170  171                  break;
 171  172  
 172  173          case LSA_MTYPE_ERROR:
 173  174                  if (rlen == sizeof (smb_lsa_eresp_t)) {
 174  175                          smb_lsa_eresp_t *ler = rbuf;
 175  176                          status = ler->ler_ntstatus;
 176  177                          break;
 177  178                  }
 178  179                  /* FALLTHROUGH */
 179  180  
 180  181          default:        /*  Bogus message type */
 181  182                  status = NT_STATUS_INTERNAL_ERROR;
 182  183                  break;
 183  184          }
 184  185  
 185  186  out:
 186  187          if (rbuf != NULL)
 187  188                  kmem_free(rbuf, rlen);
 188  189          if (sbuf != NULL)
 189  190                  kmem_free(sbuf, slen);
 190  191  
 191  192          return (status);
 192  193  }
 193  194  
 194  195  /*
 195  196   * Handle new-style (extended security) session setup.
 196  197   * Returns zero: success, non-zero: error (value not used)
 197  198   *
 198  199   * Note that this style uses a sequence of session setup requests,
 199  200   * where the first has SMB UID=0, and subsequent requests in the
 200  201   * same authentication sequence have the SMB UID returned for that
 201  202   * first request.  We allocate a USER object when the first request
 202  203   * in the sequence arrives (SMB_USER_STATE_LOGGING_ON) and use that
 203  204   * to maintain state between requests in this sequence.  The state
 204  205   * for one sequence includes an AF_UNIX "authsock" connection to the
 205  206   * user-space smbd.  The neat part of this is: in smbd, the handler
 206  207   * for the server-side of one authsock gets only request specific to
 207  208   * one authentication sequence, simplifying it's work immensely.
 208  209   * When the authentication sequence is finished, with either success
 209  210   * or failure, the local side of the authsock is closed.
 210  211   *
 211  212   * As with the old-style authentication, if we succeed, then the
 212  213   * last message from smbd will be an smb_token_t encoding the
 213  214   * information about the new user.
 214  215   *
 215  216   * Outline:
 216  217   * (a) On the first request (UID==0) create a USER object,
 217  218   *     and on subsequent requests, find USER by SMB UID.
 218  219   * (b) Send message / recv. response as above,
 219  220   * (c) If response says "we're done", close authsock
 220  221   *     (both success and failure must close authsock)
 221  222   */
 222  223  int
 223  224  smb_authenticate_ext(smb_request_t *sr)
 224  225  {
  
    | 
      ↓ open down ↓ | 
    58 lines elided | 
    
      ↑ open up ↑ | 
  
 225  226          smb_lsa_msg_hdr_t       msg_hdr;
 226  227          smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
 227  228          smb_user_t      *user = NULL;
 228  229          void            *rbuf = NULL;
 229  230          uint32_t        rlen = 0;
 230  231          uint32_t        status;
 231  232  
 232  233          ASSERT(sr->uid_user == NULL);
 233  234  
 234  235          /*
 235      -         * On the first request (UID==0) create a USER object.
 236      -         * On subsequent requests (UID!=0) find the USER object.
      236 +         * Paranoid:  While finding/creating the user object, make sure
      237 +         * SMB2 ignores smb_uid, and SMB1 ignores smb2_ssnid.  The
      238 +         * logic below assumes the "other" one is always zero; both
      239 +         * the "first request" tests and smb_session_lookup_uid_st.
      240 +         */
      241 +        if (sr->session->dialect >= SMB_VERS_2_BASE) {
      242 +                /* SMB2+ ignores smb_uid */
      243 +                ASSERT(sr->smb_uid == 0);
      244 +                sr->smb_uid = 0;
      245 +        } else {
      246 +                /* SMB1 ignores smb2_ssnid */
      247 +                ASSERT(sr->smb2_ssnid == 0);
      248 +                sr->smb2_ssnid = 0;
      249 +        }
      250 +
      251 +        /*
      252 +         * On the first request (UID/ssnid==0) create a USER object.
      253 +         * On subsequent requests (UID/ssnid!=0) find the USER object.
 237  254           * Either way, sr->uid_user is set, so our ref. on the
 238  255           * user object is dropped during normal cleanup work
 239  256           * for the smb_request (sr).  Ditto u_authsock.
 240  257           */
 241      -        if (sr->smb_uid == 0) {
      258 +        if (sr->smb2_ssnid == 0 && sr->smb_uid == 0) {
 242  259                  user = smb_user_new(sr->session);
 243  260                  if (user == NULL)
 244  261                          return (NT_STATUS_TOO_MANY_SESSIONS);
 245  262  
 246  263                  /* user cleanup in smb_request_free */
 247  264                  sr->uid_user = user;
 248      -                sr->smb_uid = user->u_uid;
      265 +                if (sr->session->dialect >= SMB_VERS_2_BASE) {
      266 +                        /* Intentionally leave smb_uid=0 for SMB2 */
      267 +                        sr->smb2_ssnid = user->u_ssnid;
      268 +                } else {
      269 +                        /* Intentionally leave smb2_ssnid=0 for SMB1 */
      270 +                        sr->smb_uid = user->u_uid;
      271 +                }
 249  272  
 250  273                  /*
 251  274                   * Open a connection to the local logon service.
 252  275                   * If we can't, it may be busy, or not running.
 253  276                   * Don't log here - this may be frequent.
 254  277                   */
 255      -                if ((status = smb_authsock_open(user)) != 0)
      278 +                if ((status = smb_authsock_open(sr)) != 0)
 256  279                          goto errout;
 257  280  
 258  281                  /*
 259  282                   * Tell the auth. svc who this client is.
 260  283                   */
 261  284                  if ((status = smb_auth_do_clinfo(sr)) != 0)
 262  285                          goto errout;
 263  286  
 264  287                  msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST;
 265  288          } else {
 266  289                  user = smb_session_lookup_uid_st(sr->session,
 267      -                    sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
      290 +                    sr->smb2_ssnid, sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
 268  291                  if (user == NULL)
 269  292                          return (NT_STATUS_USER_SESSION_DELETED);
 270  293  
 271  294                  /* user cleanup in smb_request_free */
 272  295                  sr->uid_user = user;
 273  296  
 274  297                  msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT;
 275  298          }
 276  299  
 277  300          /*
 278  301           * Wrap the "security blob" with our header
 279  302           * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT)
 280  303           * and send it up the authsock with either
 281  304           */
 282  305          msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
 283      -        status = smb_authsock_sendrecv(user, &msg_hdr,
      306 +        status = smb_authsock_sendrecv(sr, &msg_hdr,
 284  307              sinfo->ssi_isecblob, &rbuf);
 285  308          if (status != 0)
 286  309                  goto errout;
 287  310          rlen = msg_hdr.lmh_msglen;
 288  311  
 289  312          /*
 290  313           * Decode the response message.
 291  314           * Note: allocated rbuf
 292  315           */
 293  316          switch (msg_hdr.lmh_msgtype) {
 294  317  
 295  318          case LSA_MTYPE_ES_CONT:
 296  319                  sinfo->ssi_oseclen = (uint16_t)rlen;
 297  320                  sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
 298  321                  bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
 299  322                  /*
 300  323                   * This is not really an error, but tells the client
 301  324                   * it should send another session setup request.
 302  325                   */
 303  326                  status = NT_STATUS_MORE_PROCESSING_REQUIRED;
 304  327                  break;
 305  328  
 306  329          case LSA_MTYPE_ES_DONE:
 307  330                  sinfo->ssi_oseclen = (uint16_t)rlen;
 308  331                  sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
 309  332                  bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
 310  333                  sinfo->ssi_ntpwlen = 0;
 311  334                  /*
 312  335                   * Get the final auth. token.
 313  336                   */
 314  337                  status = smb_auth_get_token(sr);
 315  338                  break;
 316  339  
 317  340          case LSA_MTYPE_ERROR:
 318  341                  /*
 319  342                   * Authentication failed.  Return the error
 320  343                   * provided in the reply message.
 321  344                   */
 322  345                  if (rlen == sizeof (smb_lsa_eresp_t)) {
 323  346                          smb_lsa_eresp_t *ler = rbuf;
 324  347                          status = ler->ler_ntstatus;
 325  348                          goto errout;
 326  349                  }
 327  350                  /* FALLTHROUGH */
 328  351  
 329  352          default:        /*  Bogus message type */
 330  353                  status = NT_STATUS_INTERNAL_ERROR;
 331  354                  goto errout;
 332  355          }
 333  356  
 334  357          if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
 335  358          errout:
 336  359                  smb_user_logoff(user);
 337  360          }
 338  361  
 339  362          if (rbuf != NULL)
 340  363                  kmem_free(rbuf, rlen);
 341  364  
 342  365          return (status);
  
    | 
      ↓ open down ↓ | 
    49 lines elided | 
    
      ↑ open up ↑ | 
  
 343  366  }
 344  367  
 345  368  /*
 346  369   * Send the "client info" up to the auth service.
 347  370   */
 348  371  static uint32_t
 349  372  smb_auth_do_clinfo(smb_request_t *sr)
 350  373  {
 351  374          smb_lsa_msg_hdr_t msg_hdr;
 352  375          smb_lsa_clinfo_t clinfo;
 353      -        smb_user_t *user = sr->uid_user;
 354  376          void *rbuf = NULL;
 355  377          uint32_t status;
 356  378  
 357  379          /*
 358  380           * Send a message with info. about the client
 359  381           * (IP address, etc) and wait for an ACK.
 360  382           */
 361  383          msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO;
 362  384          msg_hdr.lmh_msglen = sizeof (clinfo);
 363  385          clinfo.lci_clnt_ipaddr = sr->session->ipaddr;
 364  386          (void) memcpy(clinfo.lci_challenge_key,
 365  387              sr->session->challenge_key,
 366  388              sizeof (clinfo.lci_challenge_key));
 367      -        status = smb_authsock_sendrecv(user, &msg_hdr, &clinfo, &rbuf);
      389 +        status = smb_authsock_sendrecv(sr, &msg_hdr, &clinfo, &rbuf);
 368  390          /* We don't use this response. */
 369  391          if (rbuf != NULL) {
 370  392                  kmem_free(rbuf, msg_hdr.lmh_msglen);
 371  393                  rbuf = NULL;
 372  394          }
 373  395  
 374  396          return (status);
 375  397  }
 376  398  
 377  399  /*
 378  400   * After a successful authentication, ask the authsvc to
 379  401   * send us the authentication token.
 380  402   */
 381  403  static uint32_t
 382  404  smb_auth_get_token(smb_request_t *sr)
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
 383  405  {
 384  406          smb_lsa_msg_hdr_t msg_hdr;
 385  407          XDR             xdrs;
 386  408          smb_user_t      *user = sr->uid_user;
 387  409          smb_token_t     *token = NULL;
 388  410          cred_t          *cr = NULL;
 389  411          void            *rbuf = NULL;
 390  412          uint32_t        rlen = 0;
 391  413          uint32_t        privileges;
 392  414          uint32_t        status;
 393      -        int             rc;
 394  415          bool_t          ok;
 395  416  
 396  417          msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
 397  418          msg_hdr.lmh_msglen = 0;
 398  419  
 399      -        status = smb_authsock_sendrecv(user, &msg_hdr, NULL, &rbuf);
      420 +        status = smb_authsock_sendrecv(sr, &msg_hdr, NULL, &rbuf);
 400  421          if (status != 0)
 401  422                  goto errout;
 402  423  
 403  424          rlen = msg_hdr.lmh_msglen;
 404  425          switch (msg_hdr.lmh_msgtype) {
 405  426  
 406  427          case LSA_MTYPE_TOKEN:
 407  428                  status = 0;
 408  429                  break;
 409  430  
 410  431          case LSA_MTYPE_ERROR:
 411  432                  if (rlen == sizeof (smb_lsa_eresp_t)) {
 412  433                          smb_lsa_eresp_t *ler = rbuf;
 413  434                          status = ler->ler_ntstatus;
 414  435                          goto errout;
 415  436                  }
 416  437                  /* FALLTHROUGH */
 417  438  
 418  439          default:
 419  440                  status = NT_STATUS_INTERNAL_ERROR;
 420  441                  goto errout;
 421  442          }
 422  443  
 423  444          /*
 424  445           * Authenticated.  Decode the LSA_MTYPE_TOKEN.
 425  446           */
 426  447          xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
 427  448          token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
 428  449          ok = smb_token_xdr(&xdrs, token);
 429  450          xdr_destroy(&xdrs);
  
    | 
      ↓ open down ↓ | 
    20 lines elided | 
    
      ↑ open up ↑ | 
  
 430  451          if (!ok) {
 431  452                  status = RPC_NT_BAD_STUB_DATA;
 432  453                  goto errout;
 433  454          }
 434  455          kmem_free(rbuf, rlen);
 435  456          rbuf = NULL;
 436  457  
 437  458          /*
 438  459           * Setup the logon object.
 439  460           */
 440      -        cr = smb_cred_create(token);
      461 +        cr = smb_cred_create(token, sr->session);
 441  462          if (cr == NULL)
 442  463                  goto errout;
 443  464          privileges = smb_priv_xlate(token);
 444  465          (void) smb_user_logon(user, cr,
 445  466              token->tkn_domain_name, token->tkn_account_name,
 446  467              token->tkn_flags, privileges, token->tkn_audit_sid);
 447  468          crfree(cr);
 448  469  
 449  470          /*
      471 +         * Some basic processing for encryption needs to be done,
      472 +         * even for anonymous/guest sessions. In particular,
      473 +         * we need to set Session.EncryptData.
      474 +         *
      475 +         * Windows handling of anon/guest and encryption is strange.
      476 +         * It allows these accounts to get through session setup,
      477 +         * even when they provide no key material.
      478 +         * Additionally, Windows somehow manages to have key material
      479 +         * for anonymous accounts under unknown circumstances.
      480 +         * As such, We set EncryptData on anon/guest to behave like Windows,
      481 +         * at least through Session Setup.
      482 +         */
      483 +        if (sr->session->dialect >= SMB_VERS_3_0)
      484 +                smb3_encrypt_begin(sr, token);
      485 +
      486 +        /*
 450  487           * Save the session key, and (maybe) enable signing,
 451  488           * but only for real logon (not ANON or GUEST).
 452  489           */
 453  490          if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
 454  491                  if (sr->session->dialect >= SMB_VERS_2_BASE) {
 455      -                        rc = smb2_sign_begin(sr, token);
      492 +                        smb2_sign_begin(sr, token);
 456  493                  } else {
 457      -                        rc = smb_sign_begin(sr, token);
      494 +                        smb_sign_begin(sr, token);
 458  495                  }
 459      -                if (rc != 0) {
 460      -                        status = NT_STATUS_INTERNAL_ERROR;
 461      -                        goto errout;
 462      -                }
 463  496          }
 464  497  
 465  498          smb_token_free(token);
 466  499  
 467  500          sr->user_cr = user->u_cred;
 468  501          return (0);
 469  502  
 470  503  errout:
 471  504          if (rbuf != NULL)
 472  505                  kmem_free(rbuf, rlen);
 473  506          if (token != NULL)
 474  507                  smb_token_free(token);
 475  508          return (status);
 476  509  }
 477  510  
 478  511  /*
 479  512   * Tokens are allocated in the kernel via XDR.
 480  513   * Call xdr_free before freeing the token structure.
 481  514   */
 482  515  void
 483  516  smb_token_free(smb_token_t *token)
 484  517  {
 485  518          if (token != NULL) {
 486  519                  xdr_free(smb_token_xdr, (char *)token);
 487  520                  kmem_free(token, sizeof (smb_token_t));
 488  521          }
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
 489  522  }
 490  523  
 491  524  /*
 492  525   * Convert access token privileges to local definitions.
 493  526   */
 494  527  static uint32_t
 495  528  smb_priv_xlate(smb_token_t *token)
 496  529  {
 497  530          uint32_t        privileges = 0;
 498  531  
      532 +        if (smb_token_query_privilege(token, SE_SECURITY_LUID))
      533 +                privileges |= SMB_USER_PRIV_SECURITY;
      534 +
      535 +        if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
      536 +                privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
      537 +
 499  538          if (smb_token_query_privilege(token, SE_BACKUP_LUID))
 500  539                  privileges |= SMB_USER_PRIV_BACKUP;
 501  540  
 502  541          if (smb_token_query_privilege(token, SE_RESTORE_LUID))
 503  542                  privileges |= SMB_USER_PRIV_RESTORE;
 504  543  
 505      -        if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
 506      -                privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
      544 +        if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID))
      545 +                privileges |= SMB_USER_PRIV_CHANGE_NOTIFY;
 507  546  
 508      -        if (smb_token_query_privilege(token, SE_SECURITY_LUID))
 509      -                privileges |= SMB_USER_PRIV_SECURITY;
 510      -
 511  547          return (privileges);
 512  548  }
 513  549  
 514  550  /*
      551 + * Unblock a request that might be blocked reading some
      552 + * authentication socket.  This can happen when either the
      553 + * client cancels a session setup or closes the connection.
      554 + */
      555 +static void
      556 +smb_authsock_cancel(smb_request_t *sr)
      557 +{
      558 +        smb_user_t *user = sr->cancel_arg2;
      559 +        ksocket_t authsock = NULL;
      560 +
      561 +        if (user == NULL)
      562 +                return;
      563 +        ASSERT(user == sr->uid_user);
      564 +
      565 +        /*
      566 +         * Check user state, and get a hold on the auth socket.
      567 +         */
      568 +        mutex_enter(&user->u_mutex);
      569 +        if (user->u_state == SMB_USER_STATE_LOGGING_ON) {
      570 +                if ((authsock = user->u_authsock) != NULL)
      571 +                        ksocket_hold(authsock);
      572 +        }
      573 +        mutex_exit(&user->u_mutex);
      574 +
      575 +        if (authsock != NULL) {
      576 +                (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr);
      577 +                ksocket_rele(authsock);
      578 +        }
      579 +}
      580 +
      581 +/*
 515  582   * Send/recv a request/reply sequence on the auth socket.
 516  583   * Returns zero or an NT status.
 517  584   *
 518  585   * Errors here mean we can't communicate with the smbd_authsvc.
 519  586   * With limited authsock instances, this should be rare.
 520  587   */
 521  588  static uint32_t
 522      -smb_authsock_sendrecv(smb_user_t *user, smb_lsa_msg_hdr_t *hdr,
 523      -        void *sndbuf, void **recvbuf)
      589 +smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr,
      590 +    void *sndbuf, void **recvbuf)
 524  591  {
      592 +        smb_user_t *user = sr->uid_user;
 525  593          ksocket_t so;
 526  594          uint32_t status;
 527  595          int rc;
 528  596  
 529  597          /*
 530  598           * Get a hold on the auth socket.
 531  599           */
 532  600          mutex_enter(&user->u_mutex);
 533  601          so = user->u_authsock;
 534  602          if (so == NULL) {
 535  603                  mutex_exit(&user->u_mutex);
 536  604                  return (NT_STATUS_INTERNAL_ERROR);
 537  605          }
 538  606          ksocket_hold(so);
 539  607          mutex_exit(&user->u_mutex);
 540  608  
      609 +        mutex_enter(&sr->sr_mutex);
      610 +        if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
      611 +                mutex_exit(&sr->sr_mutex);
      612 +                status = NT_STATUS_CANCELLED;
      613 +                goto out;
      614 +        }
      615 +        sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
      616 +        sr->cancel_method = smb_authsock_cancel;
      617 +        sr->cancel_arg2 = user;
      618 +        mutex_exit(&sr->sr_mutex);
      619 +
 541  620          rc = smb_authsock_send(so, hdr, sizeof (*hdr));
 542  621          if (rc == 0 && hdr->lmh_msglen != 0) {
 543  622                  rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
 544  623          }
 545      -        if (rc)
 546      -                goto out;
 547      -
 548      -        rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
      624 +        if (rc == 0)
      625 +                rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
 549  626          if (rc == 0 && hdr->lmh_msglen != 0) {
 550  627                  *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
 551  628                  rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);
 552      -                if (rc) {
 553      -                        kmem_free(*recvbuf, hdr->lmh_msglen);
 554      -                        *recvbuf = NULL;
 555      -                }
 556  629          }
 557  630  
 558      -out:
 559      -        ksocket_rele(so);
 560  631          switch (rc) {
 561  632          case 0:
 562  633                  status = 0;
 563  634                  break;
 564  635          case EIO:
 565  636                  status = RPC_NT_COMM_FAILURE;
 566  637                  break;
 567  638          case ENOTCONN:
 568  639                  status = RPC_NT_PIPE_CLOSED;
 569  640                  break;
 570  641          default:
 571  642                  status = RPC_NT_CALL_FAILED;
 572  643                  break;
 573  644          }
 574  645  
      646 +        mutex_enter(&sr->sr_mutex);
      647 +        sr->cancel_method = NULL;
      648 +        sr->cancel_arg2 = NULL;
      649 +        switch (sr->sr_state) {
      650 +        case SMB_REQ_STATE_WAITING_AUTH:
      651 +                sr->sr_state = SMB_REQ_STATE_ACTIVE;
      652 +                break;
      653 +        case SMB_REQ_STATE_CANCEL_PENDING:
      654 +                sr->sr_state = SMB_REQ_STATE_CANCELLED;
      655 +                status = NT_STATUS_CANCELLED;
      656 +                break;
      657 +        default:
      658 +                status = NT_STATUS_INTERNAL_ERROR;
      659 +                break;
      660 +        }
      661 +        mutex_exit(&sr->sr_mutex);
      662 +
      663 +out:
      664 +        ksocket_rele(so);
      665 +
      666 +        if (status != 0 && *recvbuf != NULL) {
      667 +                kmem_free(*recvbuf, hdr->lmh_msglen);
      668 +                *recvbuf = NULL;
      669 +        }
 575  670          return (status);
 576  671  }
 577  672  
 578  673  /*
 579  674   * Hope this is interpreted per-zone...
 580  675   */
 581  676  static struct sockaddr_un smbauth_sockname = {
 582  677          AF_UNIX, SMB_AUTHSVC_SOCKNAME };
 583  678  
 584  679  /*
 585  680   * Limit how long smb_authsock_sendrecv() will wait for a
  
    | 
      ↓ open down ↓ | 
    1 lines elided | 
    
      ↑ open up ↑ | 
  
 586  681   * response from the local authentication service.
 587  682   */
 588  683  struct timeval smb_auth_recv_tmo = { 45, 0 };
 589  684  
 590  685  /*
 591  686   * Also limit the time smb_authsock_sendrecv() will wait
 592  687   * trying to send a request to the authentication service.
 593  688   */
 594  689  struct timeval smb_auth_send_tmo = { 15, 0 };
 595  690  
      691 +/*
      692 + * Maximum time a user object may stay in state LOGGING_ON
      693 + */
      694 +int smb_auth_total_tmo = 45;    /* seconds */
      695 +
 596  696  static uint32_t
 597      -smb_authsock_open(smb_user_t *user)
      697 +smb_authsock_open(smb_request_t *sr)
 598  698  {
 599      -        smb_server_t *sv = user->u_server;
      699 +        smb_user_t *user = sr->uid_user;
      700 +        smb_server_t *sv = sr->sr_server;
 600  701          ksocket_t so = NULL;
 601      -        uint32_t status;
      702 +        uint32_t status = 0;
 602  703          int rc;
 603  704  
 604  705          /*
 605      -         * If the auth. service is busy, wait our turn.
 606      -         * This may be frequent, so don't log.
      706 +         * If the auth. service is busy, wait our turn.  This threshold
      707 +         * limits the number of auth sockets we might have trying to
      708 +         * communicate with the auth. service up in smbd.  Until we've
      709 +         * set u_authsock, we need to "exit this threshold" in any
      710 +         * error code paths after this "enter".
      711 +         *
      712 +         * Failure to "enter" may be frequent, so don't log.
 607  713           */
 608  714          if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
 609  715                  return (NT_STATUS_NO_LOGON_SERVERS);
 610  716  
 611  717          rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0,
 612  718              KSOCKET_SLEEP, CRED());
 613  719          if (rc != 0) {
 614  720                  cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);
      721 +                smb_threshold_exit(&sv->sv_ssetup_ct);
 615  722                  status = NT_STATUS_INSUFF_SERVER_RESOURCES;
 616  723                  goto errout;
 617  724          }
 618  725  
 619  726          /*
      727 +         * This (new) user object now gets an authsocket.
      728 +         * Note: u_authsock cleanup in smb_user_logoff.
      729 +         * After we've set u_authsock, smb_threshold_exit
      730 +         * is done in smb_authsock_close().  If we somehow
      731 +         * already have an authsock, close the new one and
      732 +         * error out.
      733 +         */
      734 +        mutex_enter(&user->u_mutex);
      735 +        if (user->u_authsock != NULL) {
      736 +                mutex_exit(&user->u_mutex);
      737 +                smb_authsock_close(user, so);
      738 +                status = NT_STATUS_INTERNAL_ERROR;
      739 +                goto errout;
      740 +        }
      741 +        user->u_authsock = so;
      742 +        if (smb_auth_total_tmo != 0) {
      743 +                user->u_auth_tmo = timeout(smb_user_auth_tmo, user,
      744 +                    SEC_TO_TICK(smb_auth_total_tmo));
      745 +        }
      746 +        mutex_exit(&user->u_mutex);
      747 +
      748 +        /*
 620  749           * Set the send/recv timeouts.
 621  750           */
 622  751          (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
 623  752              &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED());
 624  753          (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO,
 625  754              &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED());
 626  755  
 627  756          /*
 628  757           * Connect to the smbd auth. service.
 629  758           *
 630  759           * Would like to set the connect timeout too, but there's
 631  760           * apparently no easy way to do that for AF_UNIX.
 632  761           */
      762 +        mutex_enter(&sr->sr_mutex);
      763 +        if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
      764 +                mutex_exit(&sr->sr_mutex);
      765 +                status = NT_STATUS_CANCELLED;
      766 +                goto errout;
      767 +        }
      768 +        sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
      769 +        sr->cancel_method = smb_authsock_cancel;
      770 +        sr->cancel_arg2 = user;
      771 +        mutex_exit(&sr->sr_mutex);
      772 +
 633  773          rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
 634  774              sizeof (smbauth_sockname), CRED());
 635  775          if (rc != 0) {
 636  776                  DTRACE_PROBE1(error, int, rc);
 637  777                  status = NT_STATUS_NETLOGON_NOT_STARTED;
 638      -                goto errout;
 639  778          }
 640  779  
 641      -        /* Note: u_authsock cleanup in smb_authsock_close() */
 642      -        mutex_enter(&user->u_mutex);
 643      -        if (user->u_authsock != NULL) {
 644      -                mutex_exit(&user->u_mutex);
      780 +        mutex_enter(&sr->sr_mutex);
      781 +        sr->cancel_method = NULL;
      782 +        sr->cancel_arg2 = NULL;
      783 +        switch (sr->sr_state) {
      784 +        case SMB_REQ_STATE_WAITING_AUTH:
      785 +                sr->sr_state = SMB_REQ_STATE_ACTIVE;
      786 +                break;
      787 +        case SMB_REQ_STATE_CANCEL_PENDING:
      788 +                sr->sr_state = SMB_REQ_STATE_CANCELLED;
      789 +                status = NT_STATUS_CANCELLED;
      790 +                break;
      791 +        default:
 645  792                  status = NT_STATUS_INTERNAL_ERROR;
 646      -                goto errout;
      793 +                break;
 647  794          }
 648      -        user->u_authsock = so;
 649      -        mutex_exit(&user->u_mutex);
 650      -        return (0);
      795 +        mutex_exit(&sr->sr_mutex);
 651  796  
 652  797  errout:
 653      -        if (so != NULL)
 654      -                (void) ksocket_close(so, CRED());
 655      -        smb_threshold_exit(&sv->sv_ssetup_ct);
 656      -
 657  798          return (status);
 658  799  }
 659  800  
 660  801  static int
 661  802  smb_authsock_send(ksocket_t so, void *buf, size_t len)
 662  803  {
 663  804          int rc;
 664  805          size_t iocnt = 0;
 665  806  
 666  807          rc = ksocket_send(so, buf, len, 0, &iocnt, CRED());
 667  808          if (rc == 0 && iocnt != len) {
 668  809                  DTRACE_PROBE1(short, size_t, iocnt);
 669  810                  rc = EIO;
 670  811          }
 671  812          if (rc != 0) {
 672  813                  DTRACE_PROBE1(error, int, rc);
 673  814          }
 674  815  
 675  816          return (rc);
 676  817  }
 677  818  
 678  819  static int
 679  820  smb_authsock_recv(ksocket_t so, void *buf, size_t len)
 680  821  {
 681  822          int rc;
 682  823          size_t iocnt = 0;
 683  824  
 684  825          rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED());
 685  826          if (rc == 0) {
 686  827                  if (iocnt == 0) {
 687  828                          DTRACE_PROBE1(discon, struct sonode *, so);
 688  829                          rc = ENOTCONN;
 689  830                  } else if (iocnt != len) {
 690  831                          /* Should not happen with MSG_WAITALL */
 691  832                          DTRACE_PROBE1(short, size_t, iocnt);
  
    | 
      ↓ open down ↓ | 
    25 lines elided | 
    
      ↑ open up ↑ | 
  
 692  833                          rc = EIO;
 693  834                  }
 694  835          }
 695  836          if (rc != 0) {
 696  837                  DTRACE_PROBE1(error, int, rc);
 697  838          }
 698  839  
 699  840          return (rc);
 700  841  }
 701  842  
      843 +/*
      844 + * Caller has cleared user->u_authsock, passing the last ref
      845 + * as the 2nd arg here.  This can block, so it's called
      846 + * after exiting u_mutex.
      847 + */
 702  848  void
 703      -smb_authsock_close(smb_user_t *user)
      849 +smb_authsock_close(smb_user_t *user, ksocket_t so)
 704  850  {
 705  851  
 706      -        ASSERT(MUTEX_HELD(&user->u_mutex));
 707      -        if (user->u_authsock == NULL)
 708      -                return;
 709      -        (void) ksocket_close(user->u_authsock, CRED());
 710      -        user->u_authsock = NULL;
      852 +        (void) ksocket_shutdown(so, SHUT_RDWR, CRED());
      853 +        (void) ksocket_close(so, CRED());
 711  854          smb_threshold_exit(&user->u_server->sv_ssetup_ct);
 712  855  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX