1 /*
   2  * CDDL HEADER START
   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;
 178                 }
 179                 /* FALLTHROUGH */
 180 
 181         default:        /*  Bogus message type */
 182                 status = NT_STATUS_INTERNAL_ERROR;
 183                 break;
 184         }
 185 
 186 out:
 187         if (rbuf != NULL)
 188                 kmem_free(rbuf, rlen);
 189         if (sbuf != NULL)
 190                 kmem_free(sbuf, slen);
 191 
 192         return (status);
 193 }
 194 
 195 /*
 196  * Handle new-style (extended security) session setup.
 197  * Returns zero: success, non-zero: error (value not used)
 198  *
 199  * Note that this style uses a sequence of session setup requests,
 200  * where the first has SMB UID=0, and subsequent requests in the
 201  * same authentication sequence have the SMB UID returned for that
 202  * first request.  We allocate a USER object when the first request
 203  * in the sequence arrives (SMB_USER_STATE_LOGGING_ON) and use that
 204  * to maintain state between requests in this sequence.  The state
 205  * for one sequence includes an AF_UNIX "authsock" connection to the
 206  * user-space smbd.  The neat part of this is: in smbd, the handler
 207  * for the server-side of one authsock gets only request specific to
 208  * one authentication sequence, simplifying it's work immensely.
 209  * When the authentication sequence is finished, with either success
 210  * or failure, the local side of the authsock is closed.
 211  *
 212  * As with the old-style authentication, if we succeed, then the
 213  * last message from smbd will be an smb_token_t encoding the
 214  * information about the new user.
 215  *
 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;
 327                 break;
 328 
 329         case LSA_MTYPE_ES_DONE:
 330                 sinfo->ssi_oseclen = (uint16_t)rlen;
 331                 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
 332                 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
 333                 sinfo->ssi_ntpwlen = 0;
 334                 /*
 335                  * Get the final auth. token.
 336                  */
 337                 status = smb_auth_get_token(sr);
 338                 break;
 339 
 340         case LSA_MTYPE_ERROR:
 341                 /*
 342                  * Authentication failed.  Return the error
 343                  * provided in the reply message.
 344                  */
 345                 if (rlen == sizeof (smb_lsa_eresp_t)) {
 346                         smb_lsa_eresp_t *ler = rbuf;
 347                         status = ler->ler_ntstatus;
 348                         goto errout;
 349                 }
 350                 /* FALLTHROUGH */
 351 
 352         default:        /*  Bogus message type */
 353                 status = NT_STATUS_INTERNAL_ERROR;
 354                 goto errout;
 355         }
 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 }
 818 
 819 static int
 820 smb_authsock_recv(ksocket_t so, void *buf, size_t len)
 821 {
 822         int rc;
 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 }