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 2018 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); 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_BACKUP_LUID)) 533 privileges |= SMB_USER_PRIV_BACKUP; 534 535 if (smb_token_query_privilege(token, SE_RESTORE_LUID)) 536 privileges |= SMB_USER_PRIV_RESTORE; 537 538 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) 539 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; 540 541 if (smb_token_query_privilege(token, SE_SECURITY_LUID)) 542 privileges |= SMB_USER_PRIV_SECURITY; 543 544 return (privileges); 545 } 546 547 /* 548 * Unblock a request that might be blocked reading some 549 * authentication socket. This can happen when either the 550 * client cancels a session setup or closes the connection. 551 */ 552 static void 553 smb_authsock_cancel(smb_request_t *sr) 554 { 555 smb_user_t *user = sr->cancel_arg2; 556 ksocket_t authsock = NULL; 557 558 if (user == NULL) 559 return; 560 ASSERT(user == sr->uid_user); 561 562 /* 563 * Check user state, and get a hold on the auth socket. 564 */ 565 mutex_enter(&user->u_mutex); 566 if (user->u_state == SMB_USER_STATE_LOGGING_ON) { 567 if ((authsock = user->u_authsock) != NULL) 568 ksocket_hold(authsock); 569 } 570 mutex_exit(&user->u_mutex); 571 572 if (authsock != NULL) { 573 (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr); 574 ksocket_rele(authsock); 575 } 576 } 577 578 /* 579 * Send/recv a request/reply sequence on the auth socket. 580 * Returns zero or an NT status. 581 * 582 * Errors here mean we can't communicate with the smbd_authsvc. 583 * With limited authsock instances, this should be rare. 584 */ 585 static uint32_t 586 smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr, 587 void *sndbuf, void **recvbuf) 588 { 589 smb_user_t *user = sr->uid_user; 590 ksocket_t so; 591 uint32_t status; 592 int rc; 593 594 /* 595 * Get a hold on the auth socket. 596 */ 597 mutex_enter(&user->u_mutex); 598 so = user->u_authsock; 599 if (so == NULL) { 600 mutex_exit(&user->u_mutex); 601 return (NT_STATUS_INTERNAL_ERROR); 602 } 603 ksocket_hold(so); 604 mutex_exit(&user->u_mutex); 605 606 mutex_enter(&sr->sr_mutex); 607 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 608 mutex_exit(&sr->sr_mutex); 609 status = NT_STATUS_CANCELLED; 610 goto out; 611 } 612 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 613 sr->cancel_method = smb_authsock_cancel; 614 sr->cancel_arg2 = user; 615 mutex_exit(&sr->sr_mutex); 616 617 rc = smb_authsock_send(so, hdr, sizeof (*hdr)); 618 if (rc == 0 && hdr->lmh_msglen != 0) { 619 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen); 620 } 621 if (rc == 0) 622 rc = smb_authsock_recv(so, hdr, sizeof (*hdr)); 623 if (rc == 0 && hdr->lmh_msglen != 0) { 624 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP); 625 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen); 626 } 627 628 switch (rc) { 629 case 0: 630 status = 0; 631 break; 632 case EIO: 633 status = RPC_NT_COMM_FAILURE; 634 break; 635 case ENOTCONN: 636 status = RPC_NT_PIPE_CLOSED; 637 break; 638 default: 639 status = RPC_NT_CALL_FAILED; 640 break; 641 } 642 643 mutex_enter(&sr->sr_mutex); 644 sr->cancel_method = NULL; 645 sr->cancel_arg2 = NULL; 646 switch (sr->sr_state) { 647 case SMB_REQ_STATE_WAITING_AUTH: 648 sr->sr_state = SMB_REQ_STATE_ACTIVE; 649 break; 650 case SMB_REQ_STATE_CANCEL_PENDING: 651 sr->sr_state = SMB_REQ_STATE_CANCELLED; 652 status = NT_STATUS_CANCELLED; 653 break; 654 default: 655 status = NT_STATUS_INTERNAL_ERROR; 656 break; 657 } 658 mutex_exit(&sr->sr_mutex); 659 660 out: 661 ksocket_rele(so); 662 663 if (status != 0 && *recvbuf != NULL) { 664 kmem_free(*recvbuf, hdr->lmh_msglen); 665 *recvbuf = NULL; 666 } 667 return (status); 668 } 669 670 /* 671 * Hope this is interpreted per-zone... 672 */ 673 static struct sockaddr_un smbauth_sockname = { 674 AF_UNIX, SMB_AUTHSVC_SOCKNAME }; 675 676 /* 677 * Limit how long smb_authsock_sendrecv() will wait for a 678 * response from the local authentication service. 679 */ 680 struct timeval smb_auth_recv_tmo = { 45, 0 }; 681 682 /* 683 * Also limit the time smb_authsock_sendrecv() will wait 684 * trying to send a request to the authentication service. 685 */ 686 struct timeval smb_auth_send_tmo = { 15, 0 }; 687 688 /* 689 * Maximum time a user object may stay in state LOGGING_ON 690 */ 691 int smb_auth_total_tmo = 45; /* seconds */ 692 693 static uint32_t 694 smb_authsock_open(smb_request_t *sr) 695 { 696 smb_user_t *user = sr->uid_user; 697 smb_server_t *sv = sr->sr_server; 698 ksocket_t so = NULL; 699 uint32_t status = 0; 700 int rc; 701 702 /* 703 * If the auth. service is busy, wait our turn. This threshold 704 * limits the number of auth sockets we might have trying to 705 * communicate with the auth. service up in smbd. Until we've 706 * set u_authsock, we need to "exit this threshold" in any 707 * error code paths after this "enter". 708 * 709 * Failure to "enter" may be frequent, so don't log. 710 */ 711 if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0) 712 return (NT_STATUS_NO_LOGON_SERVERS); 713 714 rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0, 715 KSOCKET_SLEEP, CRED()); 716 if (rc != 0) { 717 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc); 718 smb_threshold_exit(&sv->sv_ssetup_ct); 719 status = NT_STATUS_INSUFF_SERVER_RESOURCES; 720 goto errout; 721 } 722 723 /* 724 * This (new) user object now gets an authsocket. 725 * Note: u_authsock cleanup in smb_user_logoff. 726 * After we've set u_authsock, smb_threshold_exit 727 * is done in smb_authsock_close(). If we somehow 728 * already have an authsock, close the new one and 729 * error out. 730 */ 731 mutex_enter(&user->u_mutex); 732 if (user->u_authsock != NULL) { 733 mutex_exit(&user->u_mutex); 734 smb_authsock_close(user, so); 735 status = NT_STATUS_INTERNAL_ERROR; 736 goto errout; 737 } 738 user->u_authsock = so; 739 if (smb_auth_total_tmo != 0) { 740 user->u_auth_tmo = timeout(smb_user_auth_tmo, user, 741 SEC_TO_TICK(smb_auth_total_tmo)); 742 } 743 mutex_exit(&user->u_mutex); 744 745 /* 746 * Set the send/recv timeouts. 747 */ 748 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, 749 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED()); 750 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, 751 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED()); 752 753 /* 754 * Connect to the smbd auth. service. 755 * 756 * Would like to set the connect timeout too, but there's 757 * apparently no easy way to do that for AF_UNIX. 758 */ 759 mutex_enter(&sr->sr_mutex); 760 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 761 mutex_exit(&sr->sr_mutex); 762 status = NT_STATUS_CANCELLED; 763 goto errout; 764 } 765 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 766 sr->cancel_method = smb_authsock_cancel; 767 sr->cancel_arg2 = user; 768 mutex_exit(&sr->sr_mutex); 769 770 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname, 771 sizeof (smbauth_sockname), CRED()); 772 if (rc != 0) { 773 DTRACE_PROBE1(error, int, rc); 774 status = NT_STATUS_NETLOGON_NOT_STARTED; 775 } 776 777 mutex_enter(&sr->sr_mutex); 778 sr->cancel_method = NULL; 779 sr->cancel_arg2 = NULL; 780 switch (sr->sr_state) { 781 case SMB_REQ_STATE_WAITING_AUTH: 782 sr->sr_state = SMB_REQ_STATE_ACTIVE; 783 break; 784 case SMB_REQ_STATE_CANCEL_PENDING: 785 sr->sr_state = SMB_REQ_STATE_CANCELLED; 786 status = NT_STATUS_CANCELLED; 787 break; 788 default: 789 status = NT_STATUS_INTERNAL_ERROR; 790 break; 791 } 792 mutex_exit(&sr->sr_mutex); 793 794 errout: 795 return (status); 796 } 797 798 static int 799 smb_authsock_send(ksocket_t so, void *buf, size_t len) 800 { 801 int rc; 802 size_t iocnt = 0; 803 804 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED()); 805 if (rc == 0 && iocnt != len) { 806 DTRACE_PROBE1(short, size_t, iocnt); 807 rc = EIO; 808 } 809 if (rc != 0) { 810 DTRACE_PROBE1(error, int, rc); 811 } 812 813 return (rc); 814 } 815 816 static int 817 smb_authsock_recv(ksocket_t so, void *buf, size_t len) 818 { 819 int rc; 820 size_t iocnt = 0; 821 822 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED()); 823 if (rc == 0) { 824 if (iocnt == 0) { 825 DTRACE_PROBE1(discon, struct sonode *, so); 826 rc = ENOTCONN; 827 } else if (iocnt != len) { 828 /* Should not happen with MSG_WAITALL */ 829 DTRACE_PROBE1(short, size_t, iocnt); 830 rc = EIO; 831 } 832 } 833 if (rc != 0) { 834 DTRACE_PROBE1(error, int, rc); 835 } 836 837 return (rc); 838 } 839 840 /* 841 * Caller has cleared user->u_authsock, passing the last ref 842 * as the 2nd arg here. This can block, so it's called 843 * after exiting u_mutex. 844 */ 845 void 846 smb_authsock_close(smb_user_t *user, ksocket_t so) 847 { 848 849 (void) ksocket_shutdown(so, SHUT_RDWR, CRED()); 850 (void) ksocket_close(so, CRED()); 851 smb_threshold_exit(&user->u_server->sv_ssetup_ct); 852 } 853