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 * 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(sr)) != 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 void *sbuf = NULL; 118 void *rbuf = NULL; 119 uint32_t slen = 0; 120 uint32_t rlen = 0; 121 uint32_t status; 122 bool_t ok; 123 124 bzero(&user_info, sizeof (smb_logon_t)); 125 126 user_info.lg_level = NETR_NETWORK_LOGON; 127 user_info.lg_username = sinfo->ssi_user; 128 user_info.lg_domain = sinfo->ssi_domain; 129 user_info.lg_workstation = sr->session->workstation; 130 user_info.lg_clnt_ipaddr = sr->session->ipaddr; 131 user_info.lg_local_ipaddr = sr->session->local_ipaddr; 132 user_info.lg_local_port = sr->session->s_local_port; 133 user_info.lg_challenge_key.val = sr->session->challenge_key; 134 user_info.lg_challenge_key.len = sr->session->challenge_len; 135 user_info.lg_nt_password.val = sinfo->ssi_ntpwd; 136 user_info.lg_nt_password.len = sinfo->ssi_ntpwlen; 137 user_info.lg_lm_password.val = sinfo->ssi_lmpwd; 138 user_info.lg_lm_password.len = sinfo->ssi_lmpwlen; 139 user_info.lg_native_os = sr->session->native_os; 140 user_info.lg_native_lm = sr->session->native_lm; 141 /* lg_flags? */ 142 143 slen = xdr_sizeof(smb_logon_xdr, &user_info); 144 sbuf = kmem_alloc(slen, KM_SLEEP); 145 xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE); 146 ok = smb_logon_xdr(&xdrs, &user_info); 147 xdr_destroy(&xdrs); 148 if (!ok) { 149 status = RPC_NT_BAD_STUB_DATA; 150 goto out; 151 } 152 153 msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ; 154 msg_hdr.lmh_msglen = slen; 155 status = smb_authsock_sendrecv(sr, &msg_hdr, sbuf, &rbuf); 156 if (status != 0) 157 goto out; 158 rlen = msg_hdr.lmh_msglen; 159 kmem_free(sbuf, slen); 160 sbuf = NULL; 161 162 /* 163 * Decode the response message. 164 */ 165 switch (msg_hdr.lmh_msgtype) { 166 167 case LSA_MTYPE_OK: 168 status = 0; 169 break; 170 171 case LSA_MTYPE_ERROR: 172 if (rlen == sizeof (smb_lsa_eresp_t)) { 173 smb_lsa_eresp_t *ler = rbuf; 174 status = ler->ler_ntstatus; 175 break; 176 } 177 /* FALLTHROUGH */ 178 179 default: /* Bogus message type */ 180 status = NT_STATUS_INTERNAL_ERROR; 181 break; 182 } 183 184 out: 185 if (rbuf != NULL) 186 kmem_free(rbuf, rlen); 187 if (sbuf != NULL) 188 kmem_free(sbuf, slen); 189 190 return (status); 191 } 192 193 /* 194 * Handle new-style (extended security) session setup. 195 * Returns zero: success, non-zero: error (value not used) 196 * 197 * Note that this style uses a sequence of session setup requests, 198 * where the first has SMB UID=0, and subsequent requests in the 199 * same authentication sequence have the SMB UID returned for that 200 * first request. We allocate a USER object when the first request 201 * in the sequence arrives (SMB_USER_STATE_LOGGING_ON) and use that 202 * to maintain state between requests in this sequence. The state 203 * for one sequence includes an AF_UNIX "authsock" connection to the 204 * user-space smbd. The neat part of this is: in smbd, the handler 205 * for the server-side of one authsock gets only request specific to 206 * one authentication sequence, simplifying it's work immensely. 207 * When the authentication sequence is finished, with either success 208 * or failure, the local side of the authsock is closed. 209 * 210 * As with the old-style authentication, if we succeed, then the 211 * last message from smbd will be an smb_token_t encoding the 212 * information about the new user. 213 * 214 * Outline: 215 * (a) On the first request (UID==0) create a USER object, 216 * and on subsequent requests, find USER by SMB UID. 217 * (b) Send message / recv. response as above, 218 * (c) If response says "we're done", close authsock 219 * (both success and failure must close authsock) 220 */ 221 int 222 smb_authenticate_ext(smb_request_t *sr) 223 { 224 smb_lsa_msg_hdr_t msg_hdr; 225 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup; 226 smb_user_t *user = NULL; 227 void *rbuf = NULL; 228 uint32_t rlen = 0; 229 uint32_t status; 230 231 ASSERT(sr->uid_user == NULL); 232 233 /* 234 * On the first request (UID==0) create a USER object. 235 * On subsequent requests (UID!=0) find the USER object. 236 * Either way, sr->uid_user is set, so our ref. on the 237 * user object is dropped during normal cleanup work 238 * for the smb_request (sr). Ditto u_authsock. 239 */ 240 if (sr->smb_uid == 0) { 241 user = smb_user_new(sr->session); 242 if (user == NULL) 243 return (NT_STATUS_TOO_MANY_SESSIONS); 244 245 /* user cleanup in smb_request_free */ 246 sr->uid_user = user; 247 sr->smb_uid = user->u_uid; 248 249 /* 250 * Open a connection to the local logon service. 251 * If we can't, it may be busy, or not running. 252 * Don't log here - this may be frequent. 253 */ 254 if ((status = smb_authsock_open(sr)) != 0) 255 goto errout; 256 257 /* 258 * Tell the auth. svc who this client is. 259 */ 260 if ((status = smb_auth_do_clinfo(sr)) != 0) 261 goto errout; 262 263 msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST; 264 } else { 265 user = smb_session_lookup_uid_st(sr->session, 266 sr->smb_uid, SMB_USER_STATE_LOGGING_ON); 267 if (user == NULL) 268 return (NT_STATUS_USER_SESSION_DELETED); 269 270 /* user cleanup in smb_request_free */ 271 sr->uid_user = user; 272 273 msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT; 274 } 275 276 /* 277 * Wrap the "security blob" with our header 278 * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT) 279 * and send it up the authsock with either 280 */ 281 msg_hdr.lmh_msglen = sinfo->ssi_iseclen; 282 status = smb_authsock_sendrecv(sr, &msg_hdr, 283 sinfo->ssi_isecblob, &rbuf); 284 if (status != 0) 285 goto errout; 286 rlen = msg_hdr.lmh_msglen; 287 288 /* 289 * Decode the response message. 290 * Note: allocated rbuf 291 */ 292 switch (msg_hdr.lmh_msgtype) { 293 294 case LSA_MTYPE_ES_CONT: 295 sinfo->ssi_oseclen = (uint16_t)rlen; 296 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen); 297 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen); 298 /* 299 * This is not really an error, but tells the client 300 * it should send another session setup request. 301 */ 302 status = NT_STATUS_MORE_PROCESSING_REQUIRED; 303 break; 304 305 case LSA_MTYPE_ES_DONE: 306 sinfo->ssi_oseclen = (uint16_t)rlen; 307 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen); 308 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen); 309 sinfo->ssi_ntpwlen = 0; 310 /* 311 * Get the final auth. token. 312 */ 313 status = smb_auth_get_token(sr); 314 break; 315 316 case LSA_MTYPE_ERROR: 317 /* 318 * Authentication failed. Return the error 319 * provided in the reply message. 320 */ 321 if (rlen == sizeof (smb_lsa_eresp_t)) { 322 smb_lsa_eresp_t *ler = rbuf; 323 status = ler->ler_ntstatus; 324 goto errout; 325 } 326 /* FALLTHROUGH */ 327 328 default: /* Bogus message type */ 329 status = NT_STATUS_INTERNAL_ERROR; 330 goto errout; 331 } 332 333 if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) { 334 errout: 335 smb_user_logoff(user); 336 } 337 338 if (rbuf != NULL) 339 kmem_free(rbuf, rlen); 340 341 return (status); 342 } 343 344 /* 345 * Send the "client info" up to the auth service. 346 */ 347 static uint32_t 348 smb_auth_do_clinfo(smb_request_t *sr) 349 { 350 smb_lsa_msg_hdr_t msg_hdr; 351 smb_lsa_clinfo_t clinfo; 352 void *rbuf = NULL; 353 uint32_t status; 354 355 /* 356 * Send a message with info. about the client 357 * (IP address, etc) and wait for an ACK. 358 */ 359 msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO; 360 msg_hdr.lmh_msglen = sizeof (clinfo); 361 clinfo.lci_clnt_ipaddr = sr->session->ipaddr; 362 (void) memcpy(clinfo.lci_challenge_key, 363 sr->session->challenge_key, 364 sizeof (clinfo.lci_challenge_key)); 365 status = smb_authsock_sendrecv(sr, &msg_hdr, &clinfo, &rbuf); 366 /* We don't use this response. */ 367 if (rbuf != NULL) { 368 kmem_free(rbuf, msg_hdr.lmh_msglen); 369 rbuf = NULL; 370 } 371 372 return (status); 373 } 374 375 /* 376 * After a successful authentication, ask the authsvc to 377 * send us the authentication token. 378 */ 379 static uint32_t 380 smb_auth_get_token(smb_request_t *sr) 381 { 382 smb_lsa_msg_hdr_t msg_hdr; 383 XDR xdrs; 384 smb_user_t *user = sr->uid_user; 385 smb_token_t *token = NULL; 386 cred_t *cr = NULL; 387 void *rbuf = NULL; 388 uint32_t rlen = 0; 389 uint32_t privileges; 390 uint32_t status; 391 bool_t ok; 392 393 msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK; 394 msg_hdr.lmh_msglen = 0; 395 396 status = smb_authsock_sendrecv(sr, &msg_hdr, NULL, &rbuf); 397 if (status != 0) 398 goto errout; 399 400 rlen = msg_hdr.lmh_msglen; 401 switch (msg_hdr.lmh_msgtype) { 402 403 case LSA_MTYPE_TOKEN: 404 status = 0; 405 break; 406 407 case LSA_MTYPE_ERROR: 408 if (rlen == sizeof (smb_lsa_eresp_t)) { 409 smb_lsa_eresp_t *ler = rbuf; 410 status = ler->ler_ntstatus; 411 goto errout; 412 } 413 /* FALLTHROUGH */ 414 415 default: 416 status = NT_STATUS_INTERNAL_ERROR; 417 goto errout; 418 } 419 420 /* 421 * Authenticated. Decode the LSA_MTYPE_TOKEN. 422 */ 423 xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE); 424 token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP); 425 ok = smb_token_xdr(&xdrs, token); 426 xdr_destroy(&xdrs); 427 if (!ok) { 428 status = RPC_NT_BAD_STUB_DATA; 429 goto errout; 430 } 431 kmem_free(rbuf, rlen); 432 rbuf = NULL; 433 434 /* 435 * Setup the logon object. 436 */ 437 cr = smb_cred_create(token); 438 if (cr == NULL) 439 goto errout; 440 privileges = smb_priv_xlate(token); 441 (void) smb_user_logon(user, cr, 442 token->tkn_domain_name, token->tkn_account_name, 443 token->tkn_flags, privileges, token->tkn_audit_sid); 444 crfree(cr); 445 446 /* 447 * Save the session key, and (maybe) enable signing, 448 * but only for real logon (not ANON or GUEST). 449 */ 450 if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) { 451 if (sr->session->dialect >= SMB_VERS_2_BASE) { 452 smb2_sign_begin(sr, token); 453 } else { 454 smb_sign_begin(sr, token); 455 } 456 } 457 458 smb_token_free(token); 459 460 sr->user_cr = user->u_cred; 461 return (0); 462 463 errout: 464 if (rbuf != NULL) 465 kmem_free(rbuf, rlen); 466 if (token != NULL) 467 smb_token_free(token); 468 return (status); 469 } 470 471 /* 472 * Tokens are allocated in the kernel via XDR. 473 * Call xdr_free before freeing the token structure. 474 */ 475 void 476 smb_token_free(smb_token_t *token) 477 { 478 if (token != NULL) { 479 xdr_free(smb_token_xdr, (char *)token); 480 kmem_free(token, sizeof (smb_token_t)); 481 } 482 } 483 484 /* 485 * Convert access token privileges to local definitions. 486 */ 487 static uint32_t 488 smb_priv_xlate(smb_token_t *token) 489 { 490 uint32_t privileges = 0; 491 492 if (smb_token_query_privilege(token, SE_BACKUP_LUID)) 493 privileges |= SMB_USER_PRIV_BACKUP; 494 495 if (smb_token_query_privilege(token, SE_RESTORE_LUID)) 496 privileges |= SMB_USER_PRIV_RESTORE; 497 498 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) 499 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; 500 501 if (smb_token_query_privilege(token, SE_SECURITY_LUID)) 502 privileges |= SMB_USER_PRIV_SECURITY; 503 504 return (privileges); 505 } 506 507 /* 508 * Unblock a request that might be blocked reading some 509 * authentication socket. This can happen when either the 510 * client cancels a session setup or closes the connection. 511 */ 512 static void 513 smb_authsock_cancel(smb_request_t *sr) 514 { 515 smb_user_t *user = sr->cancel_arg2; 516 ksocket_t authsock = NULL; 517 518 if (user == NULL) 519 return; 520 ASSERT(user == sr->uid_user); 521 522 /* 523 * Check user state, and get a hold on the auth socket. 524 */ 525 mutex_enter(&user->u_mutex); 526 if (user->u_state == SMB_USER_STATE_LOGGING_ON) { 527 if ((authsock = user->u_authsock) != NULL) 528 ksocket_hold(authsock); 529 } 530 mutex_exit(&user->u_mutex); 531 532 if (authsock != NULL) { 533 (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr); 534 ksocket_rele(authsock); 535 } 536 } 537 538 /* 539 * Send/recv a request/reply sequence on the auth socket. 540 * Returns zero or an NT status. 541 * 542 * Errors here mean we can't communicate with the smbd_authsvc. 543 * With limited authsock instances, this should be rare. 544 */ 545 static uint32_t 546 smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr, 547 void *sndbuf, void **recvbuf) 548 { 549 smb_user_t *user = sr->uid_user; 550 ksocket_t so; 551 uint32_t status; 552 int rc; 553 554 /* 555 * Get a hold on the auth socket. 556 */ 557 mutex_enter(&user->u_mutex); 558 so = user->u_authsock; 559 if (so == NULL) { 560 mutex_exit(&user->u_mutex); 561 return (NT_STATUS_INTERNAL_ERROR); 562 } 563 ksocket_hold(so); 564 mutex_exit(&user->u_mutex); 565 566 mutex_enter(&sr->sr_mutex); 567 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 568 mutex_exit(&sr->sr_mutex); 569 status = NT_STATUS_CANCELLED; 570 goto out; 571 } 572 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 573 sr->cancel_method = smb_authsock_cancel; 574 sr->cancel_arg2 = user; 575 mutex_exit(&sr->sr_mutex); 576 577 rc = smb_authsock_send(so, hdr, sizeof (*hdr)); 578 if (rc == 0 && hdr->lmh_msglen != 0) { 579 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen); 580 } 581 if (rc == 0) 582 rc = smb_authsock_recv(so, hdr, sizeof (*hdr)); 583 if (rc == 0 && hdr->lmh_msglen != 0) { 584 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP); 585 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen); 586 } 587 588 switch (rc) { 589 case 0: 590 status = 0; 591 break; 592 case EIO: 593 status = RPC_NT_COMM_FAILURE; 594 break; 595 case ENOTCONN: 596 status = RPC_NT_PIPE_CLOSED; 597 break; 598 default: 599 status = RPC_NT_CALL_FAILED; 600 break; 601 } 602 603 mutex_enter(&sr->sr_mutex); 604 sr->cancel_method = NULL; 605 sr->cancel_arg2 = NULL; 606 switch (sr->sr_state) { 607 case SMB_REQ_STATE_WAITING_AUTH: 608 sr->sr_state = SMB_REQ_STATE_ACTIVE; 609 break; 610 case SMB_REQ_STATE_CANCEL_PENDING: 611 sr->sr_state = SMB_REQ_STATE_CANCELLED; 612 status = NT_STATUS_CANCELLED; 613 break; 614 default: 615 status = NT_STATUS_INTERNAL_ERROR; 616 break; 617 } 618 mutex_exit(&sr->sr_mutex); 619 620 out: 621 ksocket_rele(so); 622 623 if (status != 0 && *recvbuf != NULL) { 624 kmem_free(*recvbuf, hdr->lmh_msglen); 625 *recvbuf = NULL; 626 } 627 return (status); 628 } 629 630 /* 631 * Hope this is interpreted per-zone... 632 */ 633 static struct sockaddr_un smbauth_sockname = { 634 AF_UNIX, SMB_AUTHSVC_SOCKNAME }; 635 636 /* 637 * Limit how long smb_authsock_sendrecv() will wait for a 638 * response from the local authentication service. 639 */ 640 struct timeval smb_auth_recv_tmo = { 45, 0 }; 641 642 /* 643 * Also limit the time smb_authsock_sendrecv() will wait 644 * trying to send a request to the authentication service. 645 */ 646 struct timeval smb_auth_send_tmo = { 15, 0 }; 647 648 /* 649 * Maximum time a user object may stay in state LOGGING_ON 650 */ 651 int smb_auth_total_tmo = 45; /* seconds */ 652 653 static uint32_t 654 smb_authsock_open(smb_request_t *sr) 655 { 656 smb_user_t *user = sr->uid_user; 657 smb_server_t *sv = sr->sr_server; 658 ksocket_t so = NULL; 659 uint32_t status = 0; 660 int rc; 661 662 /* 663 * If the auth. service is busy, wait our turn. This threshold 664 * limits the number of auth sockets we might have trying to 665 * communicate with the auth. service up in smbd. Until we've 666 * set u_authsock, we need to "exit this threshold" in any 667 * error code paths after this "enter". 668 * 669 * Failure to "enter" may be frequent, so don't log. 670 */ 671 if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0) 672 return (NT_STATUS_NO_LOGON_SERVERS); 673 674 rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0, 675 KSOCKET_SLEEP, CRED()); 676 if (rc != 0) { 677 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc); 678 smb_threshold_exit(&sv->sv_ssetup_ct); 679 status = NT_STATUS_INSUFF_SERVER_RESOURCES; 680 goto errout; 681 } 682 683 /* 684 * This (new) user object now gets an authsocket. 685 * Note: u_authsock cleanup in smb_user_logoff. 686 * After we've set u_authsock, smb_threshold_exit 687 * is done in smb_authsock_close(). If we somehow 688 * already have an authsock, close the new one and 689 * error out. 690 */ 691 mutex_enter(&user->u_mutex); 692 if (user->u_authsock != NULL) { 693 mutex_exit(&user->u_mutex); 694 smb_authsock_close(user, so); 695 status = NT_STATUS_INTERNAL_ERROR; 696 goto errout; 697 } 698 user->u_authsock = so; 699 if (smb_auth_total_tmo != 0) { 700 user->u_auth_tmo = timeout(smb_user_auth_tmo, user, 701 SEC_TO_TICK(smb_auth_total_tmo)); 702 } 703 mutex_exit(&user->u_mutex); 704 705 /* 706 * Set the send/recv timeouts. 707 */ 708 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, 709 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED()); 710 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, 711 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED()); 712 713 /* 714 * Connect to the smbd auth. service. 715 * 716 * Would like to set the connect timeout too, but there's 717 * apparently no easy way to do that for AF_UNIX. 718 */ 719 mutex_enter(&sr->sr_mutex); 720 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 721 mutex_exit(&sr->sr_mutex); 722 status = NT_STATUS_CANCELLED; 723 goto errout; 724 } 725 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 726 sr->cancel_method = smb_authsock_cancel; 727 sr->cancel_arg2 = user; 728 mutex_exit(&sr->sr_mutex); 729 730 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname, 731 sizeof (smbauth_sockname), CRED()); 732 if (rc != 0) { 733 DTRACE_PROBE1(error, int, rc); 734 status = NT_STATUS_NETLOGON_NOT_STARTED; 735 } 736 737 mutex_enter(&sr->sr_mutex); 738 sr->cancel_method = NULL; 739 sr->cancel_arg2 = NULL; 740 switch (sr->sr_state) { 741 case SMB_REQ_STATE_WAITING_AUTH: 742 sr->sr_state = SMB_REQ_STATE_ACTIVE; 743 break; 744 case SMB_REQ_STATE_CANCEL_PENDING: 745 sr->sr_state = SMB_REQ_STATE_CANCELLED; 746 status = NT_STATUS_CANCELLED; 747 break; 748 default: 749 status = NT_STATUS_INTERNAL_ERROR; 750 break; 751 } 752 mutex_exit(&sr->sr_mutex); 753 754 errout: 755 return (status); 756 } 757 758 static int 759 smb_authsock_send(ksocket_t so, void *buf, size_t len) 760 { 761 int rc; 762 size_t iocnt = 0; 763 764 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED()); 765 if (rc == 0 && iocnt != len) { 766 DTRACE_PROBE1(short, size_t, iocnt); 767 rc = EIO; 768 } 769 if (rc != 0) { 770 DTRACE_PROBE1(error, int, rc); 771 } 772 773 return (rc); 774 } 775 776 static int 777 smb_authsock_recv(ksocket_t so, void *buf, size_t len) 778 { 779 int rc; 780 size_t iocnt = 0; 781 782 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED()); 783 if (rc == 0) { 784 if (iocnt == 0) { 785 DTRACE_PROBE1(discon, struct sonode *, so); 786 rc = ENOTCONN; 787 } else if (iocnt != len) { 788 /* Should not happen with MSG_WAITALL */ 789 DTRACE_PROBE1(short, size_t, iocnt); 790 rc = EIO; 791 } 792 } 793 if (rc != 0) { 794 DTRACE_PROBE1(error, int, rc); 795 } 796 797 return (rc); 798 } 799 800 /* 801 * Caller has cleared user->u_authsock, passing the last ref 802 * as the 2nd arg here. This can block, so it's called 803 * after exiting u_mutex. 804 */ 805 void 806 smb_authsock_close(smb_user_t *user, ksocket_t so) 807 { 808 809 (void) ksocket_shutdown(so, SHUT_RDWR, CRED()); 810 (void) ksocket_close(so, CRED()); 811 smb_threshold_exit(&user->u_server->sv_ssetup_ct); 812 } 813