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 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_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 int rc; 392 bool_t ok; 393 394 msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK; 395 msg_hdr.lmh_msglen = 0; 396 397 status = smb_authsock_sendrecv(sr, &msg_hdr, NULL, &rbuf); 398 if (status != 0) 399 goto errout; 400 401 rlen = msg_hdr.lmh_msglen; 402 switch (msg_hdr.lmh_msgtype) { 403 404 case LSA_MTYPE_TOKEN: 405 status = 0; 406 break; 407 408 case LSA_MTYPE_ERROR: 409 if (rlen == sizeof (smb_lsa_eresp_t)) { 410 smb_lsa_eresp_t *ler = rbuf; 411 status = ler->ler_ntstatus; 412 goto errout; 413 } 414 /* FALLTHROUGH */ 415 416 default: 417 status = NT_STATUS_INTERNAL_ERROR; 418 goto errout; 419 } 420 421 /* 422 * Authenticated. Decode the LSA_MTYPE_TOKEN. 423 */ 424 xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE); 425 token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP); 426 ok = smb_token_xdr(&xdrs, token); 427 xdr_destroy(&xdrs); 428 if (!ok) { 429 status = RPC_NT_BAD_STUB_DATA; 430 goto errout; 431 } 432 kmem_free(rbuf, rlen); 433 rbuf = NULL; 434 435 /* 436 * Setup the logon object. 437 */ 438 cr = smb_cred_create(token); 439 if (cr == NULL) 440 goto errout; 441 privileges = smb_priv_xlate(token); 442 (void) smb_user_logon(user, cr, 443 token->tkn_domain_name, token->tkn_account_name, 444 token->tkn_flags, privileges, token->tkn_audit_sid); 445 crfree(cr); 446 447 /* 448 * Save the session key, and (maybe) enable signing, 449 * but only for real logon (not ANON or GUEST). 450 */ 451 if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) { 452 if (sr->session->dialect >= SMB_VERS_2_BASE) { 453 rc = smb2_sign_begin(sr, token); 454 } else { 455 rc = smb_sign_begin(sr, token); 456 } 457 if (rc != 0) { 458 status = NT_STATUS_INTERNAL_ERROR; 459 goto errout; 460 } 461 } 462 463 smb_token_free(token); 464 465 sr->user_cr = user->u_cred; 466 return (0); 467 468 errout: 469 if (rbuf != NULL) 470 kmem_free(rbuf, rlen); 471 if (token != NULL) 472 smb_token_free(token); 473 return (status); 474 } 475 476 /* 477 * Tokens are allocated in the kernel via XDR. 478 * Call xdr_free before freeing the token structure. 479 */ 480 void 481 smb_token_free(smb_token_t *token) 482 { 483 if (token != NULL) { 484 xdr_free(smb_token_xdr, (char *)token); 485 kmem_free(token, sizeof (smb_token_t)); 486 } 487 } 488 489 /* 490 * Convert access token privileges to local definitions. 491 */ 492 static uint32_t 493 smb_priv_xlate(smb_token_t *token) 494 { 495 uint32_t privileges = 0; 496 497 if (smb_token_query_privilege(token, SE_BACKUP_LUID)) 498 privileges |= SMB_USER_PRIV_BACKUP; 499 500 if (smb_token_query_privilege(token, SE_RESTORE_LUID)) 501 privileges |= SMB_USER_PRIV_RESTORE; 502 503 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) 504 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; 505 506 if (smb_token_query_privilege(token, SE_SECURITY_LUID)) 507 privileges |= SMB_USER_PRIV_SECURITY; 508 509 return (privileges); 510 } 511 512 /* 513 * Unblock a request that might be blocked reading some 514 * authentication socket. This can happen when either the 515 * client cancels a session setup or closes the connection. 516 */ 517 static void 518 smb_authsock_cancel(smb_request_t *sr) 519 { 520 smb_user_t *user = sr->cancel_arg2; 521 ksocket_t authsock = NULL; 522 523 if (user == NULL) 524 return; 525 ASSERT(user == sr->uid_user); 526 527 /* 528 * Check user state, and get a hold on the auth socket. 529 */ 530 mutex_enter(&user->u_mutex); 531 if (user->u_state == SMB_USER_STATE_LOGGING_ON) { 532 if ((authsock = user->u_authsock) != NULL) 533 ksocket_hold(authsock); 534 } 535 mutex_exit(&user->u_mutex); 536 537 if (authsock != NULL) { 538 (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr); 539 ksocket_rele(authsock); 540 } 541 } 542 543 /* 544 * Send/recv a request/reply sequence on the auth socket. 545 * Returns zero or an NT status. 546 * 547 * Errors here mean we can't communicate with the smbd_authsvc. 548 * With limited authsock instances, this should be rare. 549 */ 550 static uint32_t 551 smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr, 552 void *sndbuf, void **recvbuf) 553 { 554 smb_user_t *user = sr->uid_user; 555 ksocket_t so; 556 uint32_t status; 557 int rc; 558 559 /* 560 * Get a hold on the auth socket. 561 */ 562 mutex_enter(&user->u_mutex); 563 so = user->u_authsock; 564 if (so == NULL) { 565 mutex_exit(&user->u_mutex); 566 return (NT_STATUS_INTERNAL_ERROR); 567 } 568 ksocket_hold(so); 569 mutex_exit(&user->u_mutex); 570 571 mutex_enter(&sr->sr_mutex); 572 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 573 mutex_exit(&sr->sr_mutex); 574 status = NT_STATUS_CANCELLED; 575 goto out; 576 } 577 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 578 sr->cancel_method = smb_authsock_cancel; 579 sr->cancel_arg2 = user; 580 mutex_exit(&sr->sr_mutex); 581 582 rc = smb_authsock_send(so, hdr, sizeof (*hdr)); 583 if (rc == 0 && hdr->lmh_msglen != 0) { 584 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen); 585 } 586 if (rc == 0) 587 rc = smb_authsock_recv(so, hdr, sizeof (*hdr)); 588 if (rc == 0 && hdr->lmh_msglen != 0) { 589 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP); 590 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen); 591 } 592 593 switch (rc) { 594 case 0: 595 status = 0; 596 break; 597 case EIO: 598 status = RPC_NT_COMM_FAILURE; 599 break; 600 case ENOTCONN: 601 status = RPC_NT_PIPE_CLOSED; 602 break; 603 default: 604 status = RPC_NT_CALL_FAILED; 605 break; 606 } 607 608 mutex_enter(&sr->sr_mutex); 609 sr->cancel_method = NULL; 610 sr->cancel_arg2 = NULL; 611 switch (sr->sr_state) { 612 case SMB_REQ_STATE_WAITING_AUTH: 613 sr->sr_state = SMB_REQ_STATE_ACTIVE; 614 break; 615 case SMB_REQ_STATE_CANCEL_PENDING: 616 sr->sr_state = SMB_REQ_STATE_CANCELLED; 617 status = NT_STATUS_CANCELLED; 618 break; 619 default: 620 status = NT_STATUS_INTERNAL_ERROR; 621 break; 622 } 623 mutex_exit(&sr->sr_mutex); 624 625 out: 626 ksocket_rele(so); 627 628 if (status != 0 && *recvbuf != NULL) { 629 kmem_free(*recvbuf, hdr->lmh_msglen); 630 *recvbuf = NULL; 631 } 632 return (status); 633 } 634 635 /* 636 * Hope this is interpreted per-zone... 637 */ 638 static struct sockaddr_un smbauth_sockname = { 639 AF_UNIX, SMB_AUTHSVC_SOCKNAME }; 640 641 /* 642 * Limit how long smb_authsock_sendrecv() will wait for a 643 * response from the local authentication service. 644 */ 645 struct timeval smb_auth_recv_tmo = { 45, 0 }; 646 647 /* 648 * Also limit the time smb_authsock_sendrecv() will wait 649 * trying to send a request to the authentication service. 650 */ 651 struct timeval smb_auth_send_tmo = { 15, 0 }; 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(). 688 */ 689 mutex_enter(&user->u_mutex); 690 if (user->u_authsock != NULL) { 691 mutex_exit(&user->u_mutex); 692 (void) ksocket_close(so, CRED()); 693 smb_threshold_exit(&sv->sv_ssetup_ct); 694 status = NT_STATUS_INTERNAL_ERROR; 695 goto errout; 696 } 697 user->u_authsock = so; 698 mutex_exit(&user->u_mutex); 699 700 /* 701 * Set the send/recv timeouts. 702 */ 703 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, 704 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED()); 705 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, 706 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED()); 707 708 /* 709 * Connect to the smbd auth. service. 710 * 711 * Would like to set the connect timeout too, but there's 712 * apparently no easy way to do that for AF_UNIX. 713 */ 714 mutex_enter(&sr->sr_mutex); 715 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 716 mutex_exit(&sr->sr_mutex); 717 status = NT_STATUS_CANCELLED; 718 goto errout; 719 } 720 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 721 sr->cancel_method = smb_authsock_cancel; 722 sr->cancel_arg2 = user; 723 mutex_exit(&sr->sr_mutex); 724 725 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname, 726 sizeof (smbauth_sockname), CRED()); 727 if (rc != 0) { 728 DTRACE_PROBE1(error, int, rc); 729 status = NT_STATUS_NETLOGON_NOT_STARTED; 730 } 731 732 mutex_enter(&sr->sr_mutex); 733 sr->cancel_method = NULL; 734 sr->cancel_arg2 = NULL; 735 switch (sr->sr_state) { 736 case SMB_REQ_STATE_WAITING_AUTH: 737 sr->sr_state = SMB_REQ_STATE_ACTIVE; 738 break; 739 case SMB_REQ_STATE_CANCEL_PENDING: 740 sr->sr_state = SMB_REQ_STATE_CANCELLED; 741 status = NT_STATUS_CANCELLED; 742 break; 743 default: 744 status = NT_STATUS_INTERNAL_ERROR; 745 break; 746 } 747 mutex_exit(&sr->sr_mutex); 748 749 errout: 750 return (status); 751 } 752 753 static int 754 smb_authsock_send(ksocket_t so, void *buf, size_t len) 755 { 756 int rc; 757 size_t iocnt = 0; 758 759 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED()); 760 if (rc == 0 && iocnt != len) { 761 DTRACE_PROBE1(short, size_t, iocnt); 762 rc = EIO; 763 } 764 if (rc != 0) { 765 DTRACE_PROBE1(error, int, rc); 766 } 767 768 return (rc); 769 } 770 771 static int 772 smb_authsock_recv(ksocket_t so, void *buf, size_t len) 773 { 774 int rc; 775 size_t iocnt = 0; 776 777 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED()); 778 if (rc == 0) { 779 if (iocnt == 0) { 780 DTRACE_PROBE1(discon, struct sonode *, so); 781 rc = ENOTCONN; 782 } else if (iocnt != len) { 783 /* Should not happen with MSG_WAITALL */ 784 DTRACE_PROBE1(short, size_t, iocnt); 785 rc = EIO; 786 } 787 } 788 if (rc != 0) { 789 DTRACE_PROBE1(error, int, rc); 790 } 791 792 return (rc); 793 } 794 795 /* 796 * Caller has cleared user->u_authsock, passing the last ref 797 * as the 2nd arg here. This can block, so it's called 798 * after exiting u_mutex. 799 */ 800 void 801 smb_authsock_close(smb_user_t *user, ksocket_t so) 802 { 803 804 (void) ksocket_close(so, CRED()); 805 smb_threshold_exit(&user->u_server->sv_ssetup_ct); 806 } 807