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