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