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 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 /* 654 * Maximum time a user object may stay in state LOGGING_ON 655 */ 656 int smb_auth_total_tmo = 45; /* seconds */ 657 658 static uint32_t 659 smb_authsock_open(smb_request_t *sr) 660 { 661 smb_user_t *user = sr->uid_user; 662 smb_server_t *sv = sr->sr_server; 663 ksocket_t so = NULL; 664 uint32_t status = 0; 665 int rc; 666 667 /* 668 * If the auth. service is busy, wait our turn. This threshold 669 * limits the number of auth sockets we might have trying to 670 * communicate with the auth. service up in smbd. Until we've 671 * set u_authsock, we need to "exit this threshold" in any 672 * error code paths after this "enter". 673 * 674 * Failure to "enter" may be frequent, so don't log. 675 */ 676 if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0) 677 return (NT_STATUS_NO_LOGON_SERVERS); 678 679 rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0, 680 KSOCKET_SLEEP, CRED()); 681 if (rc != 0) { 682 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc); 683 smb_threshold_exit(&sv->sv_ssetup_ct); 684 status = NT_STATUS_INSUFF_SERVER_RESOURCES; 685 goto errout; 686 } 687 688 /* 689 * This (new) user object now gets an authsocket. 690 * Note: u_authsock cleanup in smb_user_logoff. 691 * After we've set u_authsock, smb_threshold_exit 692 * is done in smb_authsock_close(). If we somehow 693 * already have an authsock, close the new one and 694 * error out. 695 */ 696 mutex_enter(&user->u_mutex); 697 if (user->u_authsock != NULL) { 698 mutex_exit(&user->u_mutex); 699 smb_authsock_close(user, so); 700 status = NT_STATUS_INTERNAL_ERROR; 701 goto errout; 702 } 703 user->u_authsock = so; 704 if (smb_auth_total_tmo != 0) { 705 user->u_auth_tmo = timeout(smb_user_auth_tmo, user, 706 SEC_TO_TICK(smb_auth_total_tmo)); 707 } 708 mutex_exit(&user->u_mutex); 709 710 /* 711 * Set the send/recv timeouts. 712 */ 713 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, 714 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED()); 715 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, 716 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED()); 717 718 /* 719 * Connect to the smbd auth. service. 720 * 721 * Would like to set the connect timeout too, but there's 722 * apparently no easy way to do that for AF_UNIX. 723 */ 724 mutex_enter(&sr->sr_mutex); 725 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 726 mutex_exit(&sr->sr_mutex); 727 status = NT_STATUS_CANCELLED; 728 goto errout; 729 } 730 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 731 sr->cancel_method = smb_authsock_cancel; 732 sr->cancel_arg2 = user; 733 mutex_exit(&sr->sr_mutex); 734 735 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname, 736 sizeof (smbauth_sockname), CRED()); 737 if (rc != 0) { 738 DTRACE_PROBE1(error, int, rc); 739 status = NT_STATUS_NETLOGON_NOT_STARTED; 740 } 741 742 mutex_enter(&sr->sr_mutex); 743 sr->cancel_method = NULL; 744 sr->cancel_arg2 = NULL; 745 switch (sr->sr_state) { 746 case SMB_REQ_STATE_WAITING_AUTH: 747 sr->sr_state = SMB_REQ_STATE_ACTIVE; 748 break; 749 case SMB_REQ_STATE_CANCEL_PENDING: 750 sr->sr_state = SMB_REQ_STATE_CANCELLED; 751 status = NT_STATUS_CANCELLED; 752 break; 753 default: 754 status = NT_STATUS_INTERNAL_ERROR; 755 break; 756 } 757 mutex_exit(&sr->sr_mutex); 758 759 errout: 760 return (status); 761 } 762 763 static int 764 smb_authsock_send(ksocket_t so, void *buf, size_t len) 765 { 766 int rc; 767 size_t iocnt = 0; 768 769 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED()); 770 if (rc == 0 && iocnt != len) { 771 DTRACE_PROBE1(short, size_t, iocnt); 772 rc = EIO; 773 } 774 if (rc != 0) { 775 DTRACE_PROBE1(error, int, rc); 776 } 777 778 return (rc); 779 } 780 781 static int 782 smb_authsock_recv(ksocket_t so, void *buf, size_t len) 783 { 784 int rc; 785 size_t iocnt = 0; 786 787 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED()); 788 if (rc == 0) { 789 if (iocnt == 0) { 790 DTRACE_PROBE1(discon, struct sonode *, so); 791 rc = ENOTCONN; 792 } else if (iocnt != len) { 793 /* Should not happen with MSG_WAITALL */ 794 DTRACE_PROBE1(short, size_t, iocnt); 795 rc = EIO; 796 } 797 } 798 if (rc != 0) { 799 DTRACE_PROBE1(error, int, rc); 800 } 801 802 return (rc); 803 } 804 805 /* 806 * Caller has cleared user->u_authsock, passing the last ref 807 * as the 2nd arg here. This can block, so it's called 808 * after exiting u_mutex. 809 */ 810 void 811 smb_authsock_close(smb_user_t *user, ksocket_t so) 812 { 813 814 (void) ksocket_shutdown(so, SHUT_RDWR, CRED()); 815 (void) ksocket_close(so, CRED()); 816 smb_threshold_exit(&user->u_server->sv_ssetup_ct); 817 } 818