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 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 * Some basic processing for encryption needs to be done, 492 * even for anonymous/guest sessions. In particular, 493 * we need to set Session.EncryptData. 494 * 495 * Windows handling of anon/guest and encryption is strange. 496 * It allows these accounts to get through session setup, 497 * even when they provide no key material. 498 * Additionally, Windows somehow manages to have key material 499 * for anonymous accounts under unknown circumstances. 500 * As such, We set EncryptData on anon/guest to behave like Windows, 501 * at least through Session Setup. 502 */ 503 if (sr->session->dialect >= SMB_VERS_3_0) 504 smb3_encrypt_begin(sr, token); 505 506 /* 507 * Save the session key, and (maybe) enable signing, 508 * but only for real logon (not ANON or GUEST). 509 */ 510 if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) { 511 if (sr->session->dialect >= SMB_VERS_2_BASE) { 512 smb2_sign_begin(sr, token); 513 } else { 514 smb_sign_begin(sr, token); 515 } 516 } 517 518 smb_token_free(token); 519 520 sr->user_cr = user->u_cred; 521 return (0); 522 523 errout: 524 if (rbuf != NULL) 525 kmem_free(rbuf, rlen); 526 if (token != NULL) 527 smb_token_free(token); 528 return (status); 529 } 530 531 /* 532 * Tokens are allocated in the kernel via XDR. 533 * Call xdr_free before freeing the token structure. 534 */ 535 void 536 smb_token_free(smb_token_t *token) 537 { 538 if (token != NULL) { 539 xdr_free(smb_token_xdr, (char *)token); 540 kmem_free(token, sizeof (smb_token_t)); 541 } 542 } 543 544 /* 545 * Convert access token privileges to local definitions. 546 */ 547 static uint32_t 548 smb_priv_xlate(smb_token_t *token) 549 { 550 uint32_t privileges = 0; 551 552 if (smb_token_query_privilege(token, SE_SECURITY_LUID)) 553 privileges |= SMB_USER_PRIV_SECURITY; 554 555 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) 556 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; 557 558 if (smb_token_query_privilege(token, SE_BACKUP_LUID)) 559 privileges |= SMB_USER_PRIV_BACKUP; 560 561 if (smb_token_query_privilege(token, SE_RESTORE_LUID)) 562 privileges |= SMB_USER_PRIV_RESTORE; 563 564 if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID)) 565 privileges |= SMB_USER_PRIV_CHANGE_NOTIFY; 566 567 if (smb_token_query_privilege(token, SE_READ_FILE_LUID)) 568 privileges |= SMB_USER_PRIV_READ_FILE; 569 570 if (smb_token_query_privilege(token, SE_WRITE_FILE_LUID)) 571 privileges |= SMB_USER_PRIV_WRITE_FILE; 572 573 return (privileges); 574 } 575 576 /* 577 * Unblock a request that might be blocked reading some 578 * authentication socket. This can happen when either the 579 * client cancels a session setup or closes the connection. 580 */ 581 static void 582 smb_authsock_cancel(smb_request_t *sr) 583 { 584 smb_user_t *user = sr->cancel_arg2; 585 ksocket_t authsock = NULL; 586 587 if (user == NULL) 588 return; 589 ASSERT(user == sr->uid_user); 590 591 /* 592 * Check user state, and get a hold on the auth socket. 593 */ 594 mutex_enter(&user->u_mutex); 595 if (user->u_state == SMB_USER_STATE_LOGGING_ON) { 596 if ((authsock = user->u_authsock) != NULL) 597 ksocket_hold(authsock); 598 } 599 mutex_exit(&user->u_mutex); 600 601 if (authsock != NULL) { 602 (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr); 603 ksocket_rele(authsock); 604 } 605 } 606 607 /* 608 * Send/recv a request/reply sequence on the auth socket. 609 * Returns zero or an NT status. 610 * 611 * Errors here mean we can't communicate with the smbd_authsvc. 612 * With limited authsock instances, this should be rare. 613 */ 614 static uint32_t 615 smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr, 616 void *sndbuf, void **recvbuf) 617 { 618 smb_user_t *user = sr->uid_user; 619 ksocket_t so; 620 uint32_t status; 621 int rc; 622 623 /* 624 * Get a hold on the auth socket. 625 */ 626 mutex_enter(&user->u_mutex); 627 so = user->u_authsock; 628 if (so == NULL) { 629 mutex_exit(&user->u_mutex); 630 return (NT_STATUS_INTERNAL_ERROR); 631 } 632 ksocket_hold(so); 633 mutex_exit(&user->u_mutex); 634 635 mutex_enter(&sr->sr_mutex); 636 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 637 mutex_exit(&sr->sr_mutex); 638 status = NT_STATUS_CANCELLED; 639 goto out; 640 } 641 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 642 sr->cancel_method = smb_authsock_cancel; 643 sr->cancel_arg2 = user; 644 mutex_exit(&sr->sr_mutex); 645 646 rc = smb_authsock_send(so, hdr, sizeof (*hdr)); 647 if (rc == 0 && hdr->lmh_msglen != 0) { 648 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen); 649 } 650 if (rc == 0) 651 rc = smb_authsock_recv(so, hdr, sizeof (*hdr)); 652 if (rc == 0 && hdr->lmh_msglen != 0) { 653 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP); 654 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen); 655 } 656 657 switch (rc) { 658 case 0: 659 status = 0; 660 break; 661 case EIO: 662 status = RPC_NT_COMM_FAILURE; 663 break; 664 case ENOTCONN: 665 status = RPC_NT_PIPE_CLOSED; 666 break; 667 default: 668 status = RPC_NT_CALL_FAILED; 669 break; 670 } 671 672 mutex_enter(&sr->sr_mutex); 673 sr->cancel_method = NULL; 674 sr->cancel_arg2 = NULL; 675 switch (sr->sr_state) { 676 case SMB_REQ_STATE_WAITING_AUTH: 677 sr->sr_state = SMB_REQ_STATE_ACTIVE; 678 break; 679 case SMB_REQ_STATE_CANCEL_PENDING: 680 sr->sr_state = SMB_REQ_STATE_CANCELLED; 681 status = NT_STATUS_CANCELLED; 682 break; 683 default: 684 status = NT_STATUS_INTERNAL_ERROR; 685 break; 686 } 687 mutex_exit(&sr->sr_mutex); 688 689 out: 690 ksocket_rele(so); 691 692 if (status != 0 && *recvbuf != NULL) { 693 kmem_free(*recvbuf, hdr->lmh_msglen); 694 *recvbuf = NULL; 695 } 696 return (status); 697 } 698 699 /* 700 * Hope this is interpreted per-zone... 701 */ 702 static struct sockaddr_un smbauth_sockname = { 703 AF_UNIX, SMB_AUTHSVC_SOCKNAME }; 704 705 /* 706 * Limit how long smb_authsock_sendrecv() will wait for a 707 * response from the local authentication service. 708 */ 709 struct timeval smb_auth_recv_tmo = { 45, 0 }; 710 711 /* 712 * Also limit the time smb_authsock_sendrecv() will wait 713 * trying to send a request to the authentication service. 714 */ 715 struct timeval smb_auth_send_tmo = { 15, 0 }; 716 717 /* 718 * Maximum time a user object may stay in state LOGGING_ON 719 */ 720 int smb_auth_total_tmo = 45; /* seconds */ 721 722 static uint32_t 723 smb_authsock_open(smb_request_t *sr) 724 { 725 smb_user_t *user = sr->uid_user; 726 smb_server_t *sv = sr->sr_server; 727 ksocket_t so = NULL; 728 uint32_t status = 0; 729 int rc; 730 731 /* 732 * If the auth. service is busy, wait our turn. This threshold 733 * limits the number of auth sockets we might have trying to 734 * communicate with the auth. service up in smbd. Until we've 735 * set u_authsock, we need to "exit this threshold" in any 736 * error code paths after this "enter". 737 * 738 * Failure to "enter" may be frequent, so don't log. 739 */ 740 if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0) 741 return (NT_STATUS_NO_LOGON_SERVERS); 742 743 rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0, 744 KSOCKET_SLEEP, CRED()); 745 if (rc != 0) { 746 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc); 747 smb_threshold_exit(&sv->sv_ssetup_ct); 748 status = NT_STATUS_INSUFF_SERVER_RESOURCES; 749 goto errout; 750 } 751 752 /* 753 * This (new) user object now gets an authsocket. 754 * Note: u_authsock cleanup in smb_user_logoff. 755 * After we've set u_authsock, smb_threshold_exit 756 * is done in smb_authsock_close(). If we somehow 757 * already have an authsock, close the new one and 758 * error out. 759 */ 760 mutex_enter(&user->u_mutex); 761 if (user->u_authsock != NULL) { 762 mutex_exit(&user->u_mutex); 763 smb_authsock_close(user, so); 764 status = NT_STATUS_INTERNAL_ERROR; 765 goto errout; 766 } 767 user->u_authsock = so; 768 if (smb_auth_total_tmo != 0) { 769 user->u_auth_tmo = timeout(smb_user_auth_tmo, user, 770 SEC_TO_TICK(smb_auth_total_tmo)); 771 } 772 mutex_exit(&user->u_mutex); 773 774 /* 775 * Set the send/recv timeouts. 776 */ 777 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, 778 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED()); 779 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, 780 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED()); 781 782 /* 783 * Connect to the smbd auth. service. 784 * 785 * Would like to set the connect timeout too, but there's 786 * apparently no easy way to do that for AF_UNIX. 787 */ 788 mutex_enter(&sr->sr_mutex); 789 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 790 mutex_exit(&sr->sr_mutex); 791 status = NT_STATUS_CANCELLED; 792 goto errout; 793 } 794 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 795 sr->cancel_method = smb_authsock_cancel; 796 sr->cancel_arg2 = user; 797 mutex_exit(&sr->sr_mutex); 798 799 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname, 800 sizeof (smbauth_sockname), CRED()); 801 if (rc != 0) { 802 DTRACE_PROBE1(error, int, rc); 803 status = NT_STATUS_NETLOGON_NOT_STARTED; 804 } 805 806 mutex_enter(&sr->sr_mutex); 807 sr->cancel_method = NULL; 808 sr->cancel_arg2 = NULL; 809 switch (sr->sr_state) { 810 case SMB_REQ_STATE_WAITING_AUTH: 811 sr->sr_state = SMB_REQ_STATE_ACTIVE; 812 break; 813 case SMB_REQ_STATE_CANCEL_PENDING: 814 sr->sr_state = SMB_REQ_STATE_CANCELLED; 815 status = NT_STATUS_CANCELLED; 816 break; 817 default: 818 status = NT_STATUS_INTERNAL_ERROR; 819 break; 820 } 821 mutex_exit(&sr->sr_mutex); 822 823 errout: 824 return (status); 825 } 826 827 static int 828 smb_authsock_send(ksocket_t so, void *buf, size_t len) 829 { 830 int rc; 831 size_t iocnt = 0; 832 833 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED()); 834 if (rc == 0 && iocnt != len) { 835 DTRACE_PROBE1(short, size_t, iocnt); 836 rc = EIO; 837 } 838 if (rc != 0) { 839 DTRACE_PROBE1(error, int, rc); 840 } 841 842 return (rc); 843 } 844 845 static int 846 smb_authsock_recv(ksocket_t so, void *buf, size_t len) 847 { 848 int rc; 849 size_t iocnt = 0; 850 851 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED()); 852 if (rc == 0) { 853 if (iocnt == 0) { 854 DTRACE_PROBE1(discon, struct sonode *, so); 855 rc = ENOTCONN; 856 } else if (iocnt != len) { 857 /* Should not happen with MSG_WAITALL */ 858 DTRACE_PROBE1(short, size_t, iocnt); 859 rc = EIO; 860 } 861 } 862 if (rc != 0) { 863 DTRACE_PROBE1(error, int, rc); 864 } 865 866 return (rc); 867 } 868 869 /* 870 * Caller has cleared user->u_authsock, passing the last ref 871 * as the 2nd arg here. This can block, so it's called 872 * after exiting u_mutex. 873 */ 874 void 875 smb_authsock_close(smb_user_t *user, ksocket_t so) 876 { 877 878 (void) ksocket_shutdown(so, SHUT_RDWR, CRED()); 879 (void) ksocket_close(so, CRED()); 880 smb_threshold_exit(&user->u_server->sv_ssetup_ct); 881 } 882