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, 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 if (user == NULL) 581 return; 582 ASSERT(user == sr->uid_user); 583 584 /* 585 * Check user state, and get a hold on the auth socket. 586 */ 587 mutex_enter(&user->u_mutex); 588 if (user->u_state == SMB_USER_STATE_LOGGING_ON) { 589 if ((authsock = user->u_authsock) != NULL) 590 ksocket_hold(authsock); 591 } 592 mutex_exit(&user->u_mutex); 593 594 if (authsock != NULL) { 595 (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr); 596 ksocket_rele(authsock); 597 } 598 } 599 600 /* 601 * Send/recv a request/reply sequence on the auth socket. 602 * Returns zero or an NT status. 603 * 604 * Errors here mean we can't communicate with the smbd_authsvc. 605 * With limited authsock instances, this should be rare. 606 */ 607 static uint32_t 608 smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr, 609 void *sndbuf, void **recvbuf) 610 { 611 smb_user_t *user = sr->uid_user; 612 ksocket_t so; 613 uint32_t status; 614 int rc; 615 616 /* 617 * Get a hold on the auth socket. 618 */ 619 mutex_enter(&user->u_mutex); 620 so = user->u_authsock; 621 if (so == NULL) { 622 mutex_exit(&user->u_mutex); 623 return (NT_STATUS_INTERNAL_ERROR); 624 } 625 ksocket_hold(so); 626 mutex_exit(&user->u_mutex); 627 628 mutex_enter(&sr->sr_mutex); 629 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 630 mutex_exit(&sr->sr_mutex); 631 status = NT_STATUS_CANCELLED; 632 goto out; 633 } 634 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 635 sr->cancel_method = smb_authsock_cancel; 636 sr->cancel_arg2 = user; 637 mutex_exit(&sr->sr_mutex); 638 639 rc = smb_authsock_send(so, hdr, sizeof (*hdr)); 640 if (rc == 0 && hdr->lmh_msglen != 0) { 641 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen); 642 } 643 if (rc == 0) 644 rc = smb_authsock_recv(so, hdr, sizeof (*hdr)); 645 if (rc == 0 && hdr->lmh_msglen != 0) { 646 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP); 647 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen); 648 } 649 650 switch (rc) { 651 case 0: 652 status = 0; 653 break; 654 case EIO: 655 status = RPC_NT_COMM_FAILURE; 656 break; 657 case ENOTCONN: 658 status = RPC_NT_PIPE_CLOSED; 659 break; 660 default: 661 status = RPC_NT_CALL_FAILED; 662 break; 663 } 664 665 mutex_enter(&sr->sr_mutex); 666 sr->cancel_method = NULL; 667 sr->cancel_arg2 = NULL; 668 switch (sr->sr_state) { 669 case SMB_REQ_STATE_WAITING_AUTH: 670 sr->sr_state = SMB_REQ_STATE_ACTIVE; 671 break; 672 case SMB_REQ_STATE_CANCEL_PENDING: 673 sr->sr_state = SMB_REQ_STATE_CANCELLED; 674 status = NT_STATUS_CANCELLED; 675 break; 676 default: 677 status = NT_STATUS_INTERNAL_ERROR; 678 break; 679 } 680 mutex_exit(&sr->sr_mutex); 681 682 out: 683 ksocket_rele(so); 684 685 if (status != 0 && *recvbuf != NULL) { 686 kmem_free(*recvbuf, hdr->lmh_msglen); 687 *recvbuf = NULL; 688 } 689 return (status); 690 } 691 692 /* 693 * Hope this is interpreted per-zone... 694 */ 695 static struct sockaddr_un smbauth_sockname = { 696 AF_UNIX, SMB_AUTHSVC_SOCKNAME }; 697 698 /* 699 * Limit how long smb_authsock_sendrecv() will wait for a 700 * response from the local authentication service. 701 */ 702 struct timeval smb_auth_recv_tmo = { 45, 0 }; 703 704 /* 705 * Also limit the time smb_authsock_sendrecv() will wait 706 * trying to send a request to the authentication service. 707 */ 708 struct timeval smb_auth_send_tmo = { 15, 0 }; 709 710 /* 711 * Maximum time a user object may stay in state LOGGING_ON 712 */ 713 int smb_auth_total_tmo = 45; /* seconds */ 714 715 static uint32_t 716 smb_authsock_open(smb_request_t *sr) 717 { 718 smb_user_t *user = sr->uid_user; 719 smb_server_t *sv = sr->sr_server; 720 ksocket_t so = NULL; 721 uint32_t status = 0; 722 int rc; 723 724 /* 725 * If the auth. service is busy, wait our turn. This threshold 726 * limits the number of auth sockets we might have trying to 727 * communicate with the auth. service up in smbd. Until we've 728 * set u_authsock, we need to "exit this threshold" in any 729 * error code paths after this "enter". 730 * 731 * Failure to "enter" may be frequent, so don't log. 732 */ 733 if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0) 734 return (NT_STATUS_NO_LOGON_SERVERS); 735 736 rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0, 737 KSOCKET_SLEEP, CRED()); 738 if (rc != 0) { 739 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc); 740 smb_threshold_exit(&sv->sv_ssetup_ct); 741 status = NT_STATUS_INSUFF_SERVER_RESOURCES; 742 goto errout; 743 } 744 745 /* 746 * This (new) user object now gets an authsocket. 747 * Note: u_authsock cleanup in smb_user_logoff. 748 * After we've set u_authsock, smb_threshold_exit 749 * is done in smb_authsock_close(). If we somehow 750 * already have an authsock, close the new one and 751 * error out. 752 */ 753 mutex_enter(&user->u_mutex); 754 if (user->u_authsock != NULL) { 755 mutex_exit(&user->u_mutex); 756 smb_authsock_close(user, so); 757 status = NT_STATUS_INTERNAL_ERROR; 758 goto errout; 759 } 760 user->u_authsock = so; 761 if (smb_auth_total_tmo != 0) { 762 user->u_auth_tmo = timeout(smb_user_auth_tmo, user, 763 SEC_TO_TICK(smb_auth_total_tmo)); 764 } 765 mutex_exit(&user->u_mutex); 766 767 /* 768 * Set the send/recv timeouts. 769 */ 770 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, 771 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED()); 772 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, 773 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED()); 774 775 /* 776 * Connect to the smbd auth. service. 777 * 778 * Would like to set the connect timeout too, but there's 779 * apparently no easy way to do that for AF_UNIX. 780 */ 781 mutex_enter(&sr->sr_mutex); 782 if (sr->sr_state != SMB_REQ_STATE_ACTIVE) { 783 mutex_exit(&sr->sr_mutex); 784 status = NT_STATUS_CANCELLED; 785 goto errout; 786 } 787 sr->sr_state = SMB_REQ_STATE_WAITING_AUTH; 788 sr->cancel_method = smb_authsock_cancel; 789 sr->cancel_arg2 = user; 790 mutex_exit(&sr->sr_mutex); 791 792 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname, 793 sizeof (smbauth_sockname), CRED()); 794 if (rc != 0) { 795 DTRACE_PROBE1(error, int, rc); 796 status = NT_STATUS_NETLOGON_NOT_STARTED; 797 } 798 799 mutex_enter(&sr->sr_mutex); 800 sr->cancel_method = NULL; 801 sr->cancel_arg2 = NULL; 802 switch (sr->sr_state) { 803 case SMB_REQ_STATE_WAITING_AUTH: 804 sr->sr_state = SMB_REQ_STATE_ACTIVE; 805 break; 806 case SMB_REQ_STATE_CANCEL_PENDING: 807 sr->sr_state = SMB_REQ_STATE_CANCELLED; 808 status = NT_STATUS_CANCELLED; 809 break; 810 default: 811 status = NT_STATUS_INTERNAL_ERROR; 812 break; 813 } 814 mutex_exit(&sr->sr_mutex); 815 816 errout: 817 return (status); 818 } 819 820 static int 821 smb_authsock_send(ksocket_t so, void *buf, size_t len) 822 { 823 int rc; 824 size_t iocnt = 0; 825 826 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED()); 827 if (rc == 0 && iocnt != len) { 828 DTRACE_PROBE1(short, size_t, iocnt); 829 rc = EIO; 830 } 831 if (rc != 0) { 832 DTRACE_PROBE1(error, int, rc); 833 } 834 835 return (rc); 836 } 837 838 static int 839 smb_authsock_recv(ksocket_t so, void *buf, size_t len) 840 { 841 int rc; 842 size_t iocnt = 0; 843 844 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED()); 845 if (rc == 0) { 846 if (iocnt == 0) { 847 DTRACE_PROBE1(discon, struct sonode *, so); 848 rc = ENOTCONN; 849 } else if (iocnt != len) { 850 /* Should not happen with MSG_WAITALL */ 851 DTRACE_PROBE1(short, size_t, iocnt); 852 rc = EIO; 853 } 854 } 855 if (rc != 0) { 856 DTRACE_PROBE1(error, int, rc); 857 } 858 859 return (rc); 860 } 861 862 /* 863 * Caller has cleared user->u_authsock, passing the last ref 864 * as the 2nd arg here. This can block, so it's called 865 * after exiting u_mutex. 866 */ 867 void 868 smb_authsock_close(smb_user_t *user, ksocket_t so) 869 { 870 871 (void) ksocket_shutdown(so, SHUT_RDWR, CRED()); 872 (void) ksocket_close(so, CRED()); 873 smb_threshold_exit(&user->u_server->sv_ssetup_ct); 874 } 875