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


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Authentication support for SMB session setup
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <sys/sid.h>
  32 #include <sys/priv_names.h>
  33 #include <sys/socket.h>
  34 #include <sys/un.h>
  35 #include <netinet/in.h>
  36 #include <smbsrv/smb_idmap.h>
  37 #include <smbsrv/smb_kproto.h>
  38 #include <smbsrv/smb_token.h>
  39 
  40 static uint32_t smb_authsock_open(smb_user_t *);
  41 static int smb_authsock_send(ksocket_t, void *, size_t);
  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,
  44                                 void *sndbuf, void **recvbuf);
  45 /* void smb_authsock_close(smb_user_t *); kproto.h */
  46 
  47 static uint32_t smb_auth_do_clinfo(smb_request_t *);
  48 static uint32_t smb_auth_do_oldreq(smb_request_t *);
  49 static uint32_t smb_auth_get_token(smb_request_t *);
  50 static uint32_t smb_priv_xlate(smb_token_t *);
  51 
  52 /*
  53  * Handle old-style session setup (non-extended security)

  54  *
  55  * The user information is passed to smbd for authentication.
  56  * If smbd can authenticate the user an access token is returned and we
  57  * generate a cred and new user based on the token.
  58  */
  59 int
  60 smb_authenticate_old(smb_request_t *sr)
  61 {
  62         smb_user_t      *user = NULL;
  63         uint32_t        status;
  64 
  65         user = smb_user_new(sr->session);
  66         if (user == NULL)
  67                 return (NT_STATUS_TOO_MANY_SESSIONS);
  68 
  69         /* user cleanup in smb_request_free */
  70         sr->uid_user = user;
  71         sr->smb_uid = user->u_uid;

  72 
  73         /*
  74          * Open a connection to the local logon service.
  75          * If we can't, it may be busy, or not running.
  76          * Don't log here - this may be frequent.
  77          */
  78         if ((status = smb_authsock_open(user)) != 0)
  79                 goto errout;
  80 
  81         /*
  82          * Tell the auth. svc who this client is.
  83          */
  84         if ((status = smb_auth_do_clinfo(sr)) != 0)
  85                 goto errout;
  86 
  87         /*
  88          * Authentication proper
  89          */
  90         if ((status = smb_auth_do_oldreq(sr)) != 0)
  91                 goto errout;
  92 
  93         /*
  94          * Get the final auth. token.
  95          */
  96         if ((status = smb_auth_get_token(sr)) != 0)
  97                 goto errout;
  98 
  99         return (0);
 100 
 101 errout:
 102         smb_user_logoff(user);
 103         return (status);
 104 }
 105 
 106 /*
 107  * Build an authentication request message and
 108  * send it to the local logon service.
 109  */
 110 static uint32_t
 111 smb_auth_do_oldreq(smb_request_t *sr)
 112 {
 113         smb_lsa_msg_hdr_t       msg_hdr;
 114         smb_logon_t     user_info;
 115         XDR             xdrs;
 116         smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
 117         smb_user_t      *user = sr->uid_user;
 118         void            *sbuf = NULL;
 119         void            *rbuf = NULL;
 120         uint32_t        slen = 0;
 121         uint32_t        rlen = 0;
 122         uint32_t        status;
 123         bool_t          ok;
 124 
 125         bzero(&user_info, sizeof (smb_logon_t));
 126 
 127         user_info.lg_level = NETR_NETWORK_LOGON;
 128         user_info.lg_username = sinfo->ssi_user;
 129         user_info.lg_domain = sinfo->ssi_domain;
 130         user_info.lg_workstation = sr->session->workstation;
 131         user_info.lg_clnt_ipaddr = sr->session->ipaddr;
 132         user_info.lg_local_ipaddr = sr->session->local_ipaddr;
 133         user_info.lg_local_port = sr->session->s_local_port;
 134         user_info.lg_challenge_key.val = sr->session->challenge_key;
 135         user_info.lg_challenge_key.len = sr->session->challenge_len;
 136         user_info.lg_nt_password.val = sinfo->ssi_ntpwd;
 137         user_info.lg_nt_password.len = sinfo->ssi_ntpwlen;
 138         user_info.lg_lm_password.val = sinfo->ssi_lmpwd;
 139         user_info.lg_lm_password.len = sinfo->ssi_lmpwlen;
 140         user_info.lg_native_os = sr->session->native_os;
 141         user_info.lg_native_lm = sr->session->native_lm;
 142         /* lg_flags? */
 143 
 144         slen = xdr_sizeof(smb_logon_xdr, &user_info);
 145         sbuf = kmem_alloc(slen, KM_SLEEP);
 146         xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE);
 147         ok = smb_logon_xdr(&xdrs, &user_info);
 148         xdr_destroy(&xdrs);
 149         if (!ok) {
 150                 status = RPC_NT_BAD_STUB_DATA;
 151                 goto out;
 152         }
 153 
 154         msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
 155         msg_hdr.lmh_msglen = slen;
 156         status = smb_authsock_sendrecv(user, &msg_hdr, sbuf, &rbuf);
 157         if (status != 0)
 158                 goto out;
 159         rlen = msg_hdr.lmh_msglen;
 160         kmem_free(sbuf, slen);
 161         sbuf = NULL;
 162 
 163         /*
 164          * Decode the response message.
 165          */
 166         switch (msg_hdr.lmh_msgtype) {
 167 
 168         case LSA_MTYPE_OK:
 169                 status = 0;
 170                 break;
 171 
 172         case LSA_MTYPE_ERROR:
 173                 if (rlen == sizeof (smb_lsa_eresp_t)) {
 174                         smb_lsa_eresp_t *ler = rbuf;
 175                         status = ler->ler_ntstatus;
 176                         break;


 215  * Outline:
 216  * (a) On the first request (UID==0) create a USER object,
 217  *     and on subsequent requests, find USER by SMB UID.
 218  * (b) Send message / recv. response as above,
 219  * (c) If response says "we're done", close authsock
 220  *     (both success and failure must close authsock)
 221  */
 222 int
 223 smb_authenticate_ext(smb_request_t *sr)
 224 {
 225         smb_lsa_msg_hdr_t       msg_hdr;
 226         smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
 227         smb_user_t      *user = NULL;
 228         void            *rbuf = NULL;
 229         uint32_t        rlen = 0;
 230         uint32_t        status;
 231 
 232         ASSERT(sr->uid_user == NULL);
 233 
 234         /*
 235          * On the first request (UID==0) create a USER object.
 236          * On subsequent requests (UID!=0) find the USER object.
















 237          * Either way, sr->uid_user is set, so our ref. on the
 238          * user object is dropped during normal cleanup work
 239          * for the smb_request (sr).  Ditto u_authsock.
 240          */
 241         if (sr->smb_uid == 0) {
 242                 user = smb_user_new(sr->session);
 243                 if (user == NULL)
 244                         return (NT_STATUS_TOO_MANY_SESSIONS);
 245 
 246                 /* user cleanup in smb_request_free */
 247                 sr->uid_user = user;





 248                 sr->smb_uid = user->u_uid;

 249 
 250                 /*
 251                  * Open a connection to the local logon service.
 252                  * If we can't, it may be busy, or not running.
 253                  * Don't log here - this may be frequent.
 254                  */
 255                 if ((status = smb_authsock_open(user)) != 0)
 256                         goto errout;
 257 
 258                 /*
 259                  * Tell the auth. svc who this client is.
 260                  */
 261                 if ((status = smb_auth_do_clinfo(sr)) != 0)
 262                         goto errout;
 263 
 264                 msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST;
 265         } else {
 266                 user = smb_session_lookup_uid_st(sr->session,
 267                     sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
 268                 if (user == NULL)
 269                         return (NT_STATUS_USER_SESSION_DELETED);
 270 
 271                 /* user cleanup in smb_request_free */
 272                 sr->uid_user = user;
 273 
 274                 msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT;
 275         }
 276 
 277         /*
 278          * Wrap the "security blob" with our header
 279          * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT)
 280          * and send it up the authsock with either
 281          */
 282         msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
 283         status = smb_authsock_sendrecv(user, &msg_hdr,
 284             sinfo->ssi_isecblob, &rbuf);
 285         if (status != 0)
 286                 goto errout;
 287         rlen = msg_hdr.lmh_msglen;
 288 
 289         /*
 290          * Decode the response message.
 291          * Note: allocated rbuf
 292          */
 293         switch (msg_hdr.lmh_msgtype) {
 294 
 295         case LSA_MTYPE_ES_CONT:
 296                 sinfo->ssi_oseclen = (uint16_t)rlen;
 297                 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
 298                 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
 299                 /*
 300                  * This is not really an error, but tells the client
 301                  * it should send another session setup request.
 302                  */
 303                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;


 333 
 334         if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
 335         errout:
 336                 smb_user_logoff(user);
 337         }
 338 
 339         if (rbuf != NULL)
 340                 kmem_free(rbuf, rlen);
 341 
 342         return (status);
 343 }
 344 
 345 /*
 346  * Send the "client info" up to the auth service.
 347  */
 348 static uint32_t
 349 smb_auth_do_clinfo(smb_request_t *sr)
 350 {
 351         smb_lsa_msg_hdr_t msg_hdr;
 352         smb_lsa_clinfo_t clinfo;
 353         smb_user_t *user = sr->uid_user;
 354         void *rbuf = NULL;
 355         uint32_t status;
 356 
 357         /*
 358          * Send a message with info. about the client
 359          * (IP address, etc) and wait for an ACK.
 360          */
 361         msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO;
 362         msg_hdr.lmh_msglen = sizeof (clinfo);
 363         clinfo.lci_clnt_ipaddr = sr->session->ipaddr;
 364         (void) memcpy(clinfo.lci_challenge_key,
 365             sr->session->challenge_key,
 366             sizeof (clinfo.lci_challenge_key));
 367         status = smb_authsock_sendrecv(user, &msg_hdr, &clinfo, &rbuf);
 368         /* We don't use this response. */
 369         if (rbuf != NULL) {
 370                 kmem_free(rbuf, msg_hdr.lmh_msglen);
 371                 rbuf = NULL;
 372         }
 373 
 374         return (status);
 375 }
 376 
 377 /*
 378  * After a successful authentication, ask the authsvc to
 379  * send us the authentication token.
 380  */
 381 static uint32_t
 382 smb_auth_get_token(smb_request_t *sr)
 383 {
 384         smb_lsa_msg_hdr_t msg_hdr;
 385         XDR             xdrs;
 386         smb_user_t      *user = sr->uid_user;
 387         smb_token_t     *token = NULL;
 388         cred_t          *cr = NULL;
 389         void            *rbuf = NULL;
 390         uint32_t        rlen = 0;
 391         uint32_t        privileges;
 392         uint32_t        status;
 393         int             rc;
 394         bool_t          ok;
 395 
 396         msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
 397         msg_hdr.lmh_msglen = 0;
 398 
 399         status = smb_authsock_sendrecv(user, &msg_hdr, NULL, &rbuf);
 400         if (status != 0)
 401                 goto errout;
 402 
 403         rlen = msg_hdr.lmh_msglen;
 404         switch (msg_hdr.lmh_msgtype) {
 405 
 406         case LSA_MTYPE_TOKEN:
 407                 status = 0;
 408                 break;
 409 
 410         case LSA_MTYPE_ERROR:
 411                 if (rlen == sizeof (smb_lsa_eresp_t)) {
 412                         smb_lsa_eresp_t *ler = rbuf;
 413                         status = ler->ler_ntstatus;
 414                         goto errout;
 415                 }
 416                 /* FALLTHROUGH */
 417 
 418         default:
 419                 status = NT_STATUS_INTERNAL_ERROR;
 420                 goto errout;
 421         }
 422 
 423         /*
 424          * Authenticated.  Decode the LSA_MTYPE_TOKEN.
 425          */
 426         xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
 427         token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
 428         ok = smb_token_xdr(&xdrs, token);
 429         xdr_destroy(&xdrs);
 430         if (!ok) {
 431                 status = RPC_NT_BAD_STUB_DATA;
 432                 goto errout;
 433         }
 434         kmem_free(rbuf, rlen);
 435         rbuf = NULL;
 436 
 437         /*
 438          * Setup the logon object.
 439          */
 440         cr = smb_cred_create(token);
 441         if (cr == NULL)
 442                 goto errout;
 443         privileges = smb_priv_xlate(token);
 444         (void) smb_user_logon(user, cr,
 445             token->tkn_domain_name, token->tkn_account_name,
 446             token->tkn_flags, privileges, token->tkn_audit_sid);
 447         crfree(cr);
 448 
 449         /*
















 450          * Save the session key, and (maybe) enable signing,
 451          * but only for real logon (not ANON or GUEST).
 452          */
 453         if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
 454                 if (sr->session->dialect >= SMB_VERS_2_BASE) {
 455                         rc = smb2_sign_begin(sr, token);
 456                 } else {
 457                         rc = smb_sign_begin(sr, token);
 458                 }
 459                 if (rc != 0) {
 460                         status = NT_STATUS_INTERNAL_ERROR;
 461                         goto errout;
 462                 }
 463         }
 464 
 465         smb_token_free(token);
 466 
 467         sr->user_cr = user->u_cred;
 468         return (0);
 469 
 470 errout:
 471         if (rbuf != NULL)
 472                 kmem_free(rbuf, rlen);
 473         if (token != NULL)
 474                 smb_token_free(token);
 475         return (status);
 476 }
 477 
 478 /*
 479  * Tokens are allocated in the kernel via XDR.
 480  * Call xdr_free before freeing the token structure.
 481  */
 482 void
 483 smb_token_free(smb_token_t *token)
 484 {
 485         if (token != NULL) {
 486                 xdr_free(smb_token_xdr, (char *)token);
 487                 kmem_free(token, sizeof (smb_token_t));
 488         }
 489 }
 490 
 491 /*
 492  * Convert access token privileges to local definitions.
 493  */
 494 static uint32_t
 495 smb_priv_xlate(smb_token_t *token)
 496 {
 497         uint32_t        privileges = 0;
 498 






 499         if (smb_token_query_privilege(token, SE_BACKUP_LUID))
 500                 privileges |= SMB_USER_PRIV_BACKUP;
 501 
 502         if (smb_token_query_privilege(token, SE_RESTORE_LUID))
 503                 privileges |= SMB_USER_PRIV_RESTORE;
 504 
 505         if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
 506                 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
 507 
 508         if (smb_token_query_privilege(token, SE_SECURITY_LUID))
 509                 privileges |= SMB_USER_PRIV_SECURITY;
 510 
 511         return (privileges);
 512 }
 513 
 514 /*































 515  * Send/recv a request/reply sequence on the auth socket.
 516  * Returns zero or an NT status.
 517  *
 518  * Errors here mean we can't communicate with the smbd_authsvc.
 519  * With limited authsock instances, this should be rare.
 520  */
 521 static uint32_t
 522 smb_authsock_sendrecv(smb_user_t *user, smb_lsa_msg_hdr_t *hdr,
 523         void *sndbuf, void **recvbuf)
 524 {

 525         ksocket_t so;
 526         uint32_t status;
 527         int rc;
 528 
 529         /*
 530          * Get a hold on the auth socket.
 531          */
 532         mutex_enter(&user->u_mutex);
 533         so = user->u_authsock;
 534         if (so == NULL) {
 535                 mutex_exit(&user->u_mutex);
 536                 return (NT_STATUS_INTERNAL_ERROR);
 537         }
 538         ksocket_hold(so);
 539         mutex_exit(&user->u_mutex);
 540 











 541         rc = smb_authsock_send(so, hdr, sizeof (*hdr));
 542         if (rc == 0 && hdr->lmh_msglen != 0) {
 543                 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
 544         }
 545         if (rc)
 546                 goto out;
 547 
 548         rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
 549         if (rc == 0 && hdr->lmh_msglen != 0) {
 550                 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
 551                 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);
 552                 if (rc) {
 553                         kmem_free(*recvbuf, hdr->lmh_msglen);
 554                         *recvbuf = NULL;
 555                 }
 556         }
 557 
 558 out:
 559         ksocket_rele(so);
 560         switch (rc) {
 561         case 0:
 562                 status = 0;
 563                 break;
 564         case EIO:
 565                 status = RPC_NT_COMM_FAILURE;
 566                 break;
 567         case ENOTCONN:
 568                 status = RPC_NT_PIPE_CLOSED;
 569                 break;
 570         default:
 571                 status = RPC_NT_CALL_FAILED;
 572                 break;
 573         }
 574 
























 575         return (status);
 576 }
 577 
 578 /*
 579  * Hope this is interpreted per-zone...
 580  */
 581 static struct sockaddr_un smbauth_sockname = {
 582         AF_UNIX, SMB_AUTHSVC_SOCKNAME };
 583 
 584 /*
 585  * Limit how long smb_authsock_sendrecv() will wait for a
 586  * response from the local authentication service.
 587  */
 588 struct timeval smb_auth_recv_tmo = { 45, 0 };
 589 
 590 /*
 591  * Also limit the time smb_authsock_sendrecv() will wait
 592  * trying to send a request to the authentication service.
 593  */
 594 struct timeval smb_auth_send_tmo = { 15, 0 };
 595 





 596 static uint32_t
 597 smb_authsock_open(smb_user_t *user)
 598 {
 599         smb_server_t *sv = user->u_server;

 600         ksocket_t so = NULL;
 601         uint32_t status;
 602         int rc;
 603 
 604         /*
 605          * If the auth. service is busy, wait our turn.
 606          * This may be frequent, so don't log.





 607          */
 608         if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
 609                 return (NT_STATUS_NO_LOGON_SERVERS);
 610 
 611         rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0,
 612             KSOCKET_SLEEP, CRED());
 613         if (rc != 0) {
 614                 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);

 615                 status = NT_STATUS_INSUFF_SERVER_RESOURCES;
 616                 goto errout;
 617         }
 618 
 619         /*






















 620          * Set the send/recv timeouts.
 621          */
 622         (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
 623             &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED());
 624         (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO,
 625             &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED());
 626 
 627         /*
 628          * Connect to the smbd auth. service.
 629          *
 630          * Would like to set the connect timeout too, but there's
 631          * apparently no easy way to do that for AF_UNIX.
 632          */











 633         rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
 634             sizeof (smbauth_sockname), CRED());
 635         if (rc != 0) {
 636                 DTRACE_PROBE1(error, int, rc);
 637                 status = NT_STATUS_NETLOGON_NOT_STARTED;
 638                 goto errout;
 639         }
 640 
 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);








 645                 status = NT_STATUS_INTERNAL_ERROR;
 646                 goto errout;
 647         }
 648         user->u_authsock = so;
 649         mutex_exit(&user->u_mutex);
 650         return (0);
 651 
 652 errout:
 653         if (so != NULL)
 654                 (void) ksocket_close(so, CRED());
 655         smb_threshold_exit(&sv->sv_ssetup_ct);
 656 
 657         return (status);
 658 }
 659 
 660 static int
 661 smb_authsock_send(ksocket_t so, void *buf, size_t len)
 662 {
 663         int rc;
 664         size_t iocnt = 0;
 665 
 666         rc = ksocket_send(so, buf, len, 0, &iocnt, CRED());
 667         if (rc == 0 && iocnt != len) {
 668                 DTRACE_PROBE1(short, size_t, iocnt);
 669                 rc = EIO;
 670         }
 671         if (rc != 0) {
 672                 DTRACE_PROBE1(error, int, rc);
 673         }
 674 
 675         return (rc);
 676 }


 682         size_t iocnt = 0;
 683 
 684         rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED());
 685         if (rc == 0) {
 686                 if (iocnt == 0) {
 687                         DTRACE_PROBE1(discon, struct sonode *, so);
 688                         rc = ENOTCONN;
 689                 } else if (iocnt != len) {
 690                         /* Should not happen with MSG_WAITALL */
 691                         DTRACE_PROBE1(short, size_t, iocnt);
 692                         rc = EIO;
 693                 }
 694         }
 695         if (rc != 0) {
 696                 DTRACE_PROBE1(error, int, rc);
 697         }
 698 
 699         return (rc);
 700 }
 701 





 702 void
 703 smb_authsock_close(smb_user_t *user)
 704 {
 705 
 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;
 711         smb_threshold_exit(&user->u_server->sv_ssetup_ct);
 712 }


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Authentication support for SMB session setup
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <sys/sid.h>
  32 #include <sys/priv_names.h>
  33 #include <sys/socket.h>
  34 #include <sys/un.h>
  35 #include <netinet/in.h>
  36 #include <smbsrv/smb_idmap.h>
  37 #include <smbsrv/smb_kproto.h>
  38 #include <smbsrv/smb_token.h>
  39 
  40 static uint32_t smb_authsock_open(smb_request_t *);
  41 static int smb_authsock_send(ksocket_t, void *, size_t);
  42 static int smb_authsock_recv(ksocket_t, void *, size_t);
  43 static uint32_t smb_authsock_sendrecv(smb_request_t *, smb_lsa_msg_hdr_t *hdr,
  44                                 void *sndbuf, void **recvbuf);
  45 /* void smb_authsock_close(smb_user_t *); kproto.h */
  46 
  47 static uint32_t smb_auth_do_clinfo(smb_request_t *);
  48 static uint32_t smb_auth_do_oldreq(smb_request_t *);
  49 static uint32_t smb_auth_get_token(smb_request_t *);
  50 static uint32_t smb_priv_xlate(smb_token_t *);
  51 
  52 /*
  53  * Handle old-style session setup (non-extended security)
  54  * Note: Used only by SMB1
  55  *
  56  * The user information is passed to smbd for authentication.
  57  * If smbd can authenticate the user an access token is returned and we
  58  * generate a cred and new user based on the token.
  59  */
  60 int
  61 smb_authenticate_old(smb_request_t *sr)
  62 {
  63         smb_user_t      *user = NULL;
  64         uint32_t        status;
  65 
  66         user = smb_user_new(sr->session);
  67         if (user == NULL)
  68                 return (NT_STATUS_TOO_MANY_SESSIONS);
  69 
  70         /* user cleanup in smb_request_free */
  71         sr->uid_user = user;
  72         sr->smb_uid = user->u_uid;
  73         sr->smb2_ssnid = 0;
  74 
  75         /*
  76          * Open a connection to the local logon service.
  77          * If we can't, it may be busy, or not running.
  78          * Don't log here - this may be frequent.
  79          */
  80         if ((status = smb_authsock_open(sr)) != 0)
  81                 goto errout;
  82 
  83         /*
  84          * Tell the auth. svc who this client is.
  85          */
  86         if ((status = smb_auth_do_clinfo(sr)) != 0)
  87                 goto errout;
  88 
  89         /*
  90          * Authentication proper
  91          */
  92         if ((status = smb_auth_do_oldreq(sr)) != 0)
  93                 goto errout;
  94 
  95         /*
  96          * Get the final auth. token.
  97          */
  98         if ((status = smb_auth_get_token(sr)) != 0)
  99                 goto errout;
 100 
 101         return (0);
 102 
 103 errout:
 104         smb_user_logoff(user);
 105         return (status);
 106 }
 107 
 108 /*
 109  * Build an authentication request message and
 110  * send it to the local logon service.
 111  */
 112 static uint32_t
 113 smb_auth_do_oldreq(smb_request_t *sr)
 114 {
 115         smb_lsa_msg_hdr_t       msg_hdr;
 116         smb_logon_t     user_info;
 117         XDR             xdrs;
 118         smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;

 119         void            *sbuf = NULL;
 120         void            *rbuf = NULL;
 121         uint32_t        slen = 0;
 122         uint32_t        rlen = 0;
 123         uint32_t        status;
 124         bool_t          ok;
 125 
 126         bzero(&user_info, sizeof (smb_logon_t));
 127 
 128         user_info.lg_level = NETR_NETWORK_LOGON;
 129         user_info.lg_username = sinfo->ssi_user;
 130         user_info.lg_domain = sinfo->ssi_domain;
 131         user_info.lg_workstation = sr->session->workstation;
 132         user_info.lg_clnt_ipaddr = sr->session->ipaddr;
 133         user_info.lg_local_ipaddr = sr->session->local_ipaddr;
 134         user_info.lg_local_port = sr->session->s_local_port;
 135         user_info.lg_challenge_key.val = sr->session->challenge_key;
 136         user_info.lg_challenge_key.len = sr->session->challenge_len;
 137         user_info.lg_nt_password.val = sinfo->ssi_ntpwd;
 138         user_info.lg_nt_password.len = sinfo->ssi_ntpwlen;
 139         user_info.lg_lm_password.val = sinfo->ssi_lmpwd;
 140         user_info.lg_lm_password.len = sinfo->ssi_lmpwlen;
 141         user_info.lg_native_os = sr->session->native_os;
 142         user_info.lg_native_lm = sr->session->native_lm;
 143         /* lg_flags? */
 144 
 145         slen = xdr_sizeof(smb_logon_xdr, &user_info);
 146         sbuf = kmem_alloc(slen, KM_SLEEP);
 147         xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE);
 148         ok = smb_logon_xdr(&xdrs, &user_info);
 149         xdr_destroy(&xdrs);
 150         if (!ok) {
 151                 status = RPC_NT_BAD_STUB_DATA;
 152                 goto out;
 153         }
 154 
 155         msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
 156         msg_hdr.lmh_msglen = slen;
 157         status = smb_authsock_sendrecv(sr, &msg_hdr, sbuf, &rbuf);
 158         if (status != 0)
 159                 goto out;
 160         rlen = msg_hdr.lmh_msglen;
 161         kmem_free(sbuf, slen);
 162         sbuf = NULL;
 163 
 164         /*
 165          * Decode the response message.
 166          */
 167         switch (msg_hdr.lmh_msgtype) {
 168 
 169         case LSA_MTYPE_OK:
 170                 status = 0;
 171                 break;
 172 
 173         case LSA_MTYPE_ERROR:
 174                 if (rlen == sizeof (smb_lsa_eresp_t)) {
 175                         smb_lsa_eresp_t *ler = rbuf;
 176                         status = ler->ler_ntstatus;
 177                         break;


 216  * Outline:
 217  * (a) On the first request (UID==0) create a USER object,
 218  *     and on subsequent requests, find USER by SMB UID.
 219  * (b) Send message / recv. response as above,
 220  * (c) If response says "we're done", close authsock
 221  *     (both success and failure must close authsock)
 222  */
 223 int
 224 smb_authenticate_ext(smb_request_t *sr)
 225 {
 226         smb_lsa_msg_hdr_t       msg_hdr;
 227         smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
 228         smb_user_t      *user = NULL;
 229         void            *rbuf = NULL;
 230         uint32_t        rlen = 0;
 231         uint32_t        status;
 232 
 233         ASSERT(sr->uid_user == NULL);
 234 
 235         /*
 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.
 254          * Either way, sr->uid_user is set, so our ref. on the
 255          * user object is dropped during normal cleanup work
 256          * for the smb_request (sr).  Ditto u_authsock.
 257          */
 258         if (sr->smb2_ssnid == 0 && sr->smb_uid == 0) {
 259                 user = smb_user_new(sr->session);
 260                 if (user == NULL)
 261                         return (NT_STATUS_TOO_MANY_SESSIONS);
 262 
 263                 /* user cleanup in smb_request_free */
 264                 sr->uid_user = user;
 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                 }
 272 
 273                 /*
 274                  * Open a connection to the local logon service.
 275                  * If we can't, it may be busy, or not running.
 276                  * Don't log here - this may be frequent.
 277                  */
 278                 if ((status = smb_authsock_open(sr)) != 0)
 279                         goto errout;
 280 
 281                 /*
 282                  * Tell the auth. svc who this client is.
 283                  */
 284                 if ((status = smb_auth_do_clinfo(sr)) != 0)
 285                         goto errout;
 286 
 287                 msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST;
 288         } else {
 289                 user = smb_session_lookup_uid_st(sr->session,
 290                     sr->smb2_ssnid, sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
 291                 if (user == NULL)
 292                         return (NT_STATUS_USER_SESSION_DELETED);
 293 
 294                 /* user cleanup in smb_request_free */
 295                 sr->uid_user = user;
 296 
 297                 msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT;
 298         }
 299 
 300         /*
 301          * Wrap the "security blob" with our header
 302          * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT)
 303          * and send it up the authsock with either
 304          */
 305         msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
 306         status = smb_authsock_sendrecv(sr, &msg_hdr,
 307             sinfo->ssi_isecblob, &rbuf);
 308         if (status != 0)
 309                 goto errout;
 310         rlen = msg_hdr.lmh_msglen;
 311 
 312         /*
 313          * Decode the response message.
 314          * Note: allocated rbuf
 315          */
 316         switch (msg_hdr.lmh_msgtype) {
 317 
 318         case LSA_MTYPE_ES_CONT:
 319                 sinfo->ssi_oseclen = (uint16_t)rlen;
 320                 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
 321                 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
 322                 /*
 323                  * This is not really an error, but tells the client
 324                  * it should send another session setup request.
 325                  */
 326                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;


 356 
 357         if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
 358         errout:
 359                 smb_user_logoff(user);
 360         }
 361 
 362         if (rbuf != NULL)
 363                 kmem_free(rbuf, rlen);
 364 
 365         return (status);
 366 }
 367 
 368 /*
 369  * Send the "client info" up to the auth service.
 370  */
 371 static uint32_t
 372 smb_auth_do_clinfo(smb_request_t *sr)
 373 {
 374         smb_lsa_msg_hdr_t msg_hdr;
 375         smb_lsa_clinfo_t clinfo;

 376         void *rbuf = NULL;
 377         uint32_t status;
 378 
 379         /*
 380          * Send a message with info. about the client
 381          * (IP address, etc) and wait for an ACK.
 382          */
 383         msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO;
 384         msg_hdr.lmh_msglen = sizeof (clinfo);
 385         clinfo.lci_clnt_ipaddr = sr->session->ipaddr;
 386         (void) memcpy(clinfo.lci_challenge_key,
 387             sr->session->challenge_key,
 388             sizeof (clinfo.lci_challenge_key));
 389         status = smb_authsock_sendrecv(sr, &msg_hdr, &clinfo, &rbuf);
 390         /* We don't use this response. */
 391         if (rbuf != NULL) {
 392                 kmem_free(rbuf, msg_hdr.lmh_msglen);
 393                 rbuf = NULL;
 394         }
 395 
 396         return (status);
 397 }
 398 
 399 /*
 400  * After a successful authentication, ask the authsvc to
 401  * send us the authentication token.
 402  */
 403 static uint32_t
 404 smb_auth_get_token(smb_request_t *sr)
 405 {
 406         smb_lsa_msg_hdr_t msg_hdr;
 407         XDR             xdrs;
 408         smb_user_t      *user = sr->uid_user;
 409         smb_token_t     *token = NULL;
 410         cred_t          *cr = NULL;
 411         void            *rbuf = NULL;
 412         uint32_t        rlen = 0;
 413         uint32_t        privileges;
 414         uint32_t        status;

 415         bool_t          ok;
 416 
 417         msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
 418         msg_hdr.lmh_msglen = 0;
 419 
 420         status = smb_authsock_sendrecv(sr, &msg_hdr, NULL, &rbuf);
 421         if (status != 0)
 422                 goto errout;
 423 
 424         rlen = msg_hdr.lmh_msglen;
 425         switch (msg_hdr.lmh_msgtype) {
 426 
 427         case LSA_MTYPE_TOKEN:
 428                 status = 0;
 429                 break;
 430 
 431         case LSA_MTYPE_ERROR:
 432                 if (rlen == sizeof (smb_lsa_eresp_t)) {
 433                         smb_lsa_eresp_t *ler = rbuf;
 434                         status = ler->ler_ntstatus;
 435                         goto errout;
 436                 }
 437                 /* FALLTHROUGH */
 438 
 439         default:
 440                 status = NT_STATUS_INTERNAL_ERROR;
 441                 goto errout;
 442         }
 443 
 444         /*
 445          * Authenticated.  Decode the LSA_MTYPE_TOKEN.
 446          */
 447         xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
 448         token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
 449         ok = smb_token_xdr(&xdrs, token);
 450         xdr_destroy(&xdrs);
 451         if (!ok) {
 452                 status = RPC_NT_BAD_STUB_DATA;
 453                 goto errout;
 454         }
 455         kmem_free(rbuf, rlen);
 456         rbuf = NULL;
 457 
 458         /*
 459          * Setup the logon object.
 460          */
 461         cr = smb_cred_create(token, sr->session);
 462         if (cr == NULL)
 463                 goto errout;
 464         privileges = smb_priv_xlate(token);
 465         (void) smb_user_logon(user, cr,
 466             token->tkn_domain_name, token->tkn_account_name,
 467             token->tkn_flags, privileges, token->tkn_audit_sid);
 468         crfree(cr);
 469 
 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         /*
 487          * Save the session key, and (maybe) enable signing,
 488          * but only for real logon (not ANON or GUEST).
 489          */
 490         if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
 491                 if (sr->session->dialect >= SMB_VERS_2_BASE) {
 492                         smb2_sign_begin(sr, token);
 493                 } else {
 494                         smb_sign_begin(sr, token);
 495                 }



 496         }

 497 
 498         smb_token_free(token);
 499 
 500         sr->user_cr = user->u_cred;
 501         return (0);
 502 
 503 errout:
 504         if (rbuf != NULL)
 505                 kmem_free(rbuf, rlen);
 506         if (token != NULL)
 507                 smb_token_free(token);
 508         return (status);
 509 }
 510 
 511 /*
 512  * Tokens are allocated in the kernel via XDR.
 513  * Call xdr_free before freeing the token structure.
 514  */
 515 void
 516 smb_token_free(smb_token_t *token)
 517 {
 518         if (token != NULL) {
 519                 xdr_free(smb_token_xdr, (char *)token);
 520                 kmem_free(token, sizeof (smb_token_t));
 521         }
 522 }
 523 
 524 /*
 525  * Convert access token privileges to local definitions.
 526  */
 527 static uint32_t
 528 smb_priv_xlate(smb_token_t *token)
 529 {
 530         uint32_t        privileges = 0;
 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 
 538         if (smb_token_query_privilege(token, SE_BACKUP_LUID))
 539                 privileges |= SMB_USER_PRIV_BACKUP;
 540 
 541         if (smb_token_query_privilege(token, SE_RESTORE_LUID))
 542                 privileges |= SMB_USER_PRIV_RESTORE;
 543 
 544         if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID))
 545                 privileges |= SMB_USER_PRIV_CHANGE_NOTIFY;
 546 



 547         return (privileges);
 548 }
 549 
 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 /*
 582  * Send/recv a request/reply sequence on the auth socket.
 583  * Returns zero or an NT status.
 584  *
 585  * Errors here mean we can't communicate with the smbd_authsvc.
 586  * With limited authsock instances, this should be rare.
 587  */
 588 static uint32_t
 589 smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr,
 590     void *sndbuf, void **recvbuf)
 591 {
 592         smb_user_t *user = sr->uid_user;
 593         ksocket_t so;
 594         uint32_t status;
 595         int rc;
 596 
 597         /*
 598          * Get a hold on the auth socket.
 599          */
 600         mutex_enter(&user->u_mutex);
 601         so = user->u_authsock;
 602         if (so == NULL) {
 603                 mutex_exit(&user->u_mutex);
 604                 return (NT_STATUS_INTERNAL_ERROR);
 605         }
 606         ksocket_hold(so);
 607         mutex_exit(&user->u_mutex);
 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 
 620         rc = smb_authsock_send(so, hdr, sizeof (*hdr));
 621         if (rc == 0 && hdr->lmh_msglen != 0) {
 622                 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
 623         }
 624         if (rc == 0)


 625                 rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
 626         if (rc == 0 && hdr->lmh_msglen != 0) {
 627                 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
 628                 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);



 629         }

 630 


 631         switch (rc) {
 632         case 0:
 633                 status = 0;
 634                 break;
 635         case EIO:
 636                 status = RPC_NT_COMM_FAILURE;
 637                 break;
 638         case ENOTCONN:
 639                 status = RPC_NT_PIPE_CLOSED;
 640                 break;
 641         default:
 642                 status = RPC_NT_CALL_FAILED;
 643                 break;
 644         }
 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         }
 670         return (status);
 671 }
 672 
 673 /*
 674  * Hope this is interpreted per-zone...
 675  */
 676 static struct sockaddr_un smbauth_sockname = {
 677         AF_UNIX, SMB_AUTHSVC_SOCKNAME };
 678 
 679 /*
 680  * Limit how long smb_authsock_sendrecv() will wait for a
 681  * response from the local authentication service.
 682  */
 683 struct timeval smb_auth_recv_tmo = { 45, 0 };
 684 
 685 /*
 686  * Also limit the time smb_authsock_sendrecv() will wait
 687  * trying to send a request to the authentication service.
 688  */
 689 struct timeval smb_auth_send_tmo = { 15, 0 };
 690 
 691 /*
 692  * Maximum time a user object may stay in state LOGGING_ON
 693  */
 694 int smb_auth_total_tmo = 45;    /* seconds */
 695 
 696 static uint32_t
 697 smb_authsock_open(smb_request_t *sr)
 698 {
 699         smb_user_t *user = sr->uid_user;
 700         smb_server_t *sv = sr->sr_server;
 701         ksocket_t so = NULL;
 702         uint32_t status = 0;
 703         int rc;
 704 
 705         /*
 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.
 713          */
 714         if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
 715                 return (NT_STATUS_NO_LOGON_SERVERS);
 716 
 717         rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0,
 718             KSOCKET_SLEEP, CRED());
 719         if (rc != 0) {
 720                 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);
 721                 smb_threshold_exit(&sv->sv_ssetup_ct);
 722                 status = NT_STATUS_INSUFF_SERVER_RESOURCES;
 723                 goto errout;
 724         }
 725 
 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         /*
 749          * Set the send/recv timeouts.
 750          */
 751         (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
 752             &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED());
 753         (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO,
 754             &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED());
 755 
 756         /*
 757          * Connect to the smbd auth. service.
 758          *
 759          * Would like to set the connect timeout too, but there's
 760          * apparently no easy way to do that for AF_UNIX.
 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 
 773         rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
 774             sizeof (smbauth_sockname), CRED());
 775         if (rc != 0) {
 776                 DTRACE_PROBE1(error, int, rc);
 777                 status = NT_STATUS_NETLOGON_NOT_STARTED;

 778         }
 779 
 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:
 792                 status = NT_STATUS_INTERNAL_ERROR;
 793                 break;
 794         }
 795         mutex_exit(&sr->sr_mutex);


 796 
 797 errout:




 798         return (status);
 799 }
 800 
 801 static int
 802 smb_authsock_send(ksocket_t so, void *buf, size_t len)
 803 {
 804         int rc;
 805         size_t iocnt = 0;
 806 
 807         rc = ksocket_send(so, buf, len, 0, &iocnt, CRED());
 808         if (rc == 0 && iocnt != len) {
 809                 DTRACE_PROBE1(short, size_t, iocnt);
 810                 rc = EIO;
 811         }
 812         if (rc != 0) {
 813                 DTRACE_PROBE1(error, int, rc);
 814         }
 815 
 816         return (rc);
 817 }


 823         size_t iocnt = 0;
 824 
 825         rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED());
 826         if (rc == 0) {
 827                 if (iocnt == 0) {
 828                         DTRACE_PROBE1(discon, struct sonode *, so);
 829                         rc = ENOTCONN;
 830                 } else if (iocnt != len) {
 831                         /* Should not happen with MSG_WAITALL */
 832                         DTRACE_PROBE1(short, size_t, iocnt);
 833                         rc = EIO;
 834                 }
 835         }
 836         if (rc != 0) {
 837                 DTRACE_PROBE1(error, int, rc);
 838         }
 839 
 840         return (rc);
 841 }
 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  */
 848 void
 849 smb_authsock_close(smb_user_t *user, ksocket_t so)
 850 {
 851 
 852         (void) ksocket_shutdown(so, SHUT_RDWR, CRED());
 853         (void) ksocket_close(so, CRED());



 854         smb_threshold_exit(&user->u_server->sv_ssetup_ct);
 855 }