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