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
↓ 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
↓ 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;
↓ 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) {
↓ 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) {
↓ 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  /*
↓ 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  
↓ 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);
↓ 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  /*
↓ 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());
↓ 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