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_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 } 856