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 */ 24 25 /* 26 * General Structures Layout 27 * ------------------------- 28 * 29 * This is a simplified diagram showing the relationship between most of the 30 * main structures. 31 * 32 * +-------------------+ 33 * | SMB_INFO | 34 * +-------------------+ 35 * | 36 * | 37 * v 38 * +-------------------+ +-------------------+ +-------------------+ 39 * | SESSION |<----->| SESSION |......| SESSION | 40 * +-------------------+ +-------------------+ +-------------------+ 41 * | 42 * | 43 * v 44 * +-------------------+ +-------------------+ +-------------------+ 45 * | USER |<----->| USER |......| USER | 46 * +-------------------+ +-------------------+ +-------------------+ 47 * | 48 * | 49 * v 50 * +-------------------+ +-------------------+ +-------------------+ 51 * | TREE |<----->| TREE |......| TREE | 52 * +-------------------+ +-------------------+ +-------------------+ 53 * | | 54 * | | 55 * | v 56 * | +-------+ +-------+ +-------+ 57 * | | OFILE |<----->| OFILE |......| OFILE | 58 * | +-------+ +-------+ +-------+ 59 * | 60 * | 61 * v 62 * +-------+ +------+ +------+ 63 * | ODIR |<----->| ODIR |......| ODIR | 64 * +-------+ +------+ +------+ 65 * 66 * 67 * User State Machine 68 * ------------------ 69 * 70 * +-----------------------------+ T0 71 * | SMB_USER_STATE_LOGGED_IN |<----------- Creation/Allocation 72 * +-----------------------------+ 73 * | 74 * | T1 75 * | 76 * v 77 * +-----------------------------+ 78 * | SMB_USER_STATE_LOGGING_OFF | 79 * +-----------------------------+ 80 * | 81 * | T2 82 * | 83 * v 84 * +-----------------------------+ T3 85 * | SMB_USER_STATE_LOGGED_OFF |----------> Deletion/Free 86 * +-----------------------------+ 87 * 88 * SMB_USER_STATE_LOGGED_IN 89 * 90 * While in this state: 91 * - The user is queued in the list of users of his session. 92 * - References will be given out if the user is looked up. 93 * - The user can access files and pipes. 94 * 95 * SMB_USER_STATE_LOGGING_OFF 96 * 97 * While in this state: 98 * - The user is queued in the list of users of his session. 99 * - References will not be given out if the user is looked up. 100 * - The trees the user connected are being disconnected. 101 * - The resources associated with the user remain. 102 * 103 * SMB_USER_STATE_LOGGING_OFF 104 * 105 * While in this state: 106 * - The user is queued in the list of users of his session. 107 * - References will not be given out if the user is looked up. 108 * - The user has no more trees connected. 109 * - The resources associated with the user remain. 110 * 111 * Transition T0 112 * 113 * This transition occurs in smb_user_login(). A new user is created and 114 * added to the list of users of a session. 115 * 116 * Transition T1 117 * 118 * This transition occurs in smb_user_logoff(). 119 * 120 * Transition T2 121 * 122 * This transition occurs in smb_user_release(). The resources associated 123 * with the user are deleted as well as the user. For the transition to 124 * occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the 125 * reference count be zero. 126 * 127 * Comments 128 * -------- 129 * 130 * The state machine of the user structures is controlled by 3 elements: 131 * - The list of users of the session he belongs to. 132 * - The mutex embedded in the structure itself. 133 * - The reference count. 134 * 135 * There's a mutex embedded in the user structure used to protect its fields 136 * and there's a lock embedded in the list of users of a session. To 137 * increment or to decrement the reference count the mutex must be entered. 138 * To insert the user into the list of users of the session and to remove 139 * the user from it, the lock must be entered in RW_WRITER mode. 140 * 141 * Rules of access to a user structure: 142 * 143 * 1) In order to avoid deadlocks, when both (mutex and lock of the session 144 * list) have to be entered, the lock must be entered first. 145 * 146 * 2) All actions applied to a user require a reference count. 147 * 148 * 3) There are 2 ways of getting a reference count. One is when the user 149 * logs in. The other when the user is looked up. 150 * 151 * It should be noted that the reference count of a user registers the 152 * number of references to the user in other structures (such as an smb 153 * request). The reference count is not incremented in these 2 instances: 154 * 155 * 1) The user is logged in. An user is anchored by his state. If there's 156 * no activity involving a user currently logged in, the reference 157 * count of that user is zero. 158 * 159 * 2) The user is queued in the list of users of the session. The fact of 160 * being queued in that list is NOT registered by incrementing the 161 * reference count. 162 */ 163 #include <smbsrv/smb_kproto.h> 164 #include <smbsrv/smb_door.h> 165 166 167 #define ADMINISTRATORS_SID "S-1-5-32-544" 168 169 static smb_sid_t *smb_admins_sid = NULL; 170 171 static boolean_t smb_user_is_logged_in(smb_user_t *); 172 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *); 173 static smb_tree_t *smb_user_get_tree(smb_llist_t *, smb_tree_t *); 174 static void smb_user_nonauth_logon(uint32_t); 175 static void smb_user_auth_logoff(uint32_t); 176 177 int 178 smb_user_init(void) 179 { 180 if (smb_admins_sid != NULL) 181 return (0); 182 183 if ((smb_admins_sid = smb_sid_fromstr(ADMINISTRATORS_SID)) == NULL) 184 return (-1); 185 186 return (0); 187 } 188 189 void 190 smb_user_fini(void) 191 { 192 if (smb_admins_sid != NULL) { 193 smb_sid_free(smb_admins_sid); 194 smb_admins_sid = NULL; 195 } 196 } 197 198 /* 199 * smb_user_login 200 * 201 * 202 */ 203 smb_user_t * 204 smb_user_login( 205 smb_session_t *session, 206 cred_t *cr, 207 char *domain_name, 208 char *account_name, 209 uint32_t flags, 210 uint32_t privileges, 211 uint32_t audit_sid) 212 { 213 smb_user_t *user; 214 215 ASSERT(session); 216 ASSERT(session->s_magic == SMB_SESSION_MAGIC); 217 ASSERT(cr); 218 ASSERT(account_name); 219 ASSERT(domain_name); 220 221 user = kmem_cache_alloc(session->s_server->si_cache_user, KM_SLEEP); 222 bzero(user, sizeof (smb_user_t)); 223 user->u_refcnt = 1; 224 user->u_session = session; 225 user->u_server = session->s_server; 226 user->u_logon_time = gethrestime_sec(); 227 user->u_flags = flags; 228 user->u_privileges = privileges; 229 user->u_name_len = strlen(account_name) + 1; 230 user->u_domain_len = strlen(domain_name) + 1; 231 user->u_name = smb_mem_strdup(account_name); 232 user->u_domain = smb_mem_strdup(domain_name); 233 user->u_cred = cr; 234 user->u_privcred = smb_cred_create_privs(cr, privileges); 235 user->u_audit_sid = audit_sid; 236 237 if (!smb_idpool_alloc(&session->s_uid_pool, &user->u_uid)) { 238 if (!smb_idpool_constructor(&user->u_tid_pool)) { 239 smb_llist_constructor(&user->u_tree_list, 240 sizeof (smb_tree_t), offsetof(smb_tree_t, t_lnd)); 241 mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL); 242 crhold(user->u_cred); 243 if (user->u_privcred) 244 crhold(user->u_privcred); 245 user->u_state = SMB_USER_STATE_LOGGED_IN; 246 user->u_magic = SMB_USER_MAGIC; 247 smb_llist_enter(&session->s_user_list, RW_WRITER); 248 smb_llist_insert_tail(&session->s_user_list, user); 249 smb_llist_exit(&session->s_user_list); 250 atomic_inc_32(&session->s_server->sv_open_users); 251 return (user); 252 } 253 smb_idpool_free(&session->s_uid_pool, user->u_uid); 254 } 255 smb_mem_free(user->u_name); 256 smb_mem_free(user->u_domain); 257 kmem_cache_free(session->s_server->si_cache_user, user); 258 return (NULL); 259 } 260 261 /* 262 * Create a new user based on an existing user, used to support 263 * additional SessionSetupX requests for a user on a session. 264 * 265 * Assumes the caller has a reference on the original user from 266 * a user_lookup_by_x call. 267 */ 268 smb_user_t * 269 smb_user_dup( 270 smb_user_t *orig_user) 271 { 272 smb_user_t *user; 273 274 ASSERT(orig_user->u_magic == SMB_USER_MAGIC); 275 ASSERT(orig_user->u_refcnt); 276 277 user = smb_user_login(orig_user->u_session, orig_user->u_cred, 278 orig_user->u_domain, orig_user->u_name, orig_user->u_flags, 279 orig_user->u_privileges, orig_user->u_audit_sid); 280 281 if (user) 282 smb_user_nonauth_logon(orig_user->u_audit_sid); 283 284 return (user); 285 } 286 287 /* 288 * smb_user_logoff 289 * 290 * Change the user state and disconnect trees. 291 * The user list must not be entered or modified here. 292 */ 293 void 294 smb_user_logoff( 295 smb_user_t *user) 296 { 297 ASSERT(user->u_magic == SMB_USER_MAGIC); 298 299 mutex_enter(&user->u_mutex); 300 ASSERT(user->u_refcnt); 301 switch (user->u_state) { 302 case SMB_USER_STATE_LOGGED_IN: { 303 /* 304 * The user is moved into a state indicating that the log off 305 * process has started. 306 */ 307 user->u_state = SMB_USER_STATE_LOGGING_OFF; 308 mutex_exit(&user->u_mutex); 309 atomic_dec_32(&user->u_server->sv_open_users); 310 /* 311 * All the trees hanging off of this user are disconnected. 312 */ 313 smb_user_disconnect_trees(user); 314 smb_user_auth_logoff(user->u_audit_sid); 315 mutex_enter(&user->u_mutex); 316 user->u_state = SMB_USER_STATE_LOGGED_OFF; 317 break; 318 } 319 case SMB_USER_STATE_LOGGED_OFF: 320 case SMB_USER_STATE_LOGGING_OFF: 321 break; 322 323 default: 324 ASSERT(0); 325 break; 326 } 327 mutex_exit(&user->u_mutex); 328 } 329 330 /* 331 * Take a reference on a user. 332 */ 333 boolean_t 334 smb_user_hold(smb_user_t *user) 335 { 336 ASSERT(user); 337 ASSERT(user->u_magic == SMB_USER_MAGIC); 338 339 mutex_enter(&user->u_mutex); 340 341 if (smb_user_is_logged_in(user)) { 342 user->u_refcnt++; 343 mutex_exit(&user->u_mutex); 344 return (B_TRUE); 345 } 346 347 mutex_exit(&user->u_mutex); 348 return (B_FALSE); 349 } 350 351 /* 352 * Release a reference on a user. If the reference count falls to 353 * zero and the user has logged off, post the object for deletion. 354 * Object deletion is deferred to avoid modifying a list while an 355 * iteration may be in progress. 356 */ 357 void 358 smb_user_release( 359 smb_user_t *user) 360 { 361 ASSERT(user->u_magic == SMB_USER_MAGIC); 362 363 mutex_enter(&user->u_mutex); 364 ASSERT(user->u_refcnt); 365 user->u_refcnt--; 366 367 /* flush the tree list's delete queue */ 368 smb_llist_flush(&user->u_tree_list); 369 370 switch (user->u_state) { 371 case SMB_USER_STATE_LOGGED_OFF: 372 if (user->u_refcnt == 0) 373 smb_session_post_user(user->u_session, user); 374 break; 375 376 case SMB_USER_STATE_LOGGED_IN: 377 case SMB_USER_STATE_LOGGING_OFF: 378 break; 379 380 default: 381 ASSERT(0); 382 break; 383 } 384 mutex_exit(&user->u_mutex); 385 } 386 387 void 388 smb_user_post_tree(smb_user_t *user, smb_tree_t *tree) 389 { 390 SMB_USER_VALID(user); 391 SMB_TREE_VALID(tree); 392 ASSERT(tree->t_refcnt == 0); 393 ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); 394 ASSERT(tree->t_user == user); 395 396 smb_llist_post(&user->u_tree_list, tree, smb_tree_dealloc); 397 } 398 399 400 /* 401 * Find a tree by tree-id. 402 */ 403 smb_tree_t * 404 smb_user_lookup_tree( 405 smb_user_t *user, 406 uint16_t tid) 407 408 { 409 smb_tree_t *tree; 410 411 ASSERT(user); 412 ASSERT(user->u_magic == SMB_USER_MAGIC); 413 414 smb_llist_enter(&user->u_tree_list, RW_READER); 415 tree = smb_llist_head(&user->u_tree_list); 416 417 while (tree) { 418 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 419 ASSERT(tree->t_user == user); 420 421 if (tree->t_tid == tid) { 422 if (smb_tree_hold(tree)) { 423 smb_llist_exit(&user->u_tree_list); 424 return (tree); 425 } else { 426 smb_llist_exit(&user->u_tree_list); 427 return (NULL); 428 } 429 } 430 431 tree = smb_llist_next(&user->u_tree_list, tree); 432 } 433 434 smb_llist_exit(&user->u_tree_list); 435 return (NULL); 436 } 437 438 /* 439 * Find the first connected tree that matches the specified sharename. 440 * If the specified tree is NULL the search starts from the beginning of 441 * the user's tree list. If a tree is provided the search starts just 442 * after that tree. 443 */ 444 smb_tree_t * 445 smb_user_lookup_share( 446 smb_user_t *user, 447 const char *sharename, 448 smb_tree_t *tree) 449 { 450 ASSERT(user); 451 ASSERT(user->u_magic == SMB_USER_MAGIC); 452 ASSERT(sharename); 453 454 smb_llist_enter(&user->u_tree_list, RW_READER); 455 456 if (tree) { 457 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 458 ASSERT(tree->t_user == user); 459 tree = smb_llist_next(&user->u_tree_list, tree); 460 } else { 461 tree = smb_llist_head(&user->u_tree_list); 462 } 463 464 while (tree) { 465 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 466 ASSERT(tree->t_user == user); 467 if (smb_strcasecmp(tree->t_sharename, sharename, 0) == 0) { 468 if (smb_tree_hold(tree)) { 469 smb_llist_exit(&user->u_tree_list); 470 return (tree); 471 } 472 } 473 tree = smb_llist_next(&user->u_tree_list, tree); 474 } 475 476 smb_llist_exit(&user->u_tree_list); 477 return (NULL); 478 } 479 480 /* 481 * Find the first connected tree that matches the specified volume name. 482 * If the specified tree is NULL the search starts from the beginning of 483 * the user's tree list. If a tree is provided the search starts just 484 * after that tree. 485 */ 486 smb_tree_t * 487 smb_user_lookup_volume( 488 smb_user_t *user, 489 const char *name, 490 smb_tree_t *tree) 491 { 492 ASSERT(user); 493 ASSERT(user->u_magic == SMB_USER_MAGIC); 494 ASSERT(name); 495 496 smb_llist_enter(&user->u_tree_list, RW_READER); 497 498 if (tree) { 499 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 500 ASSERT(tree->t_user == user); 501 tree = smb_llist_next(&user->u_tree_list, tree); 502 } else { 503 tree = smb_llist_head(&user->u_tree_list); 504 } 505 506 while (tree) { 507 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 508 ASSERT(tree->t_user == user); 509 510 if (smb_strcasecmp(tree->t_volume, name, 0) == 0) { 511 if (smb_tree_hold(tree)) { 512 smb_llist_exit(&user->u_tree_list); 513 return (tree); 514 } 515 } 516 517 tree = smb_llist_next(&user->u_tree_list, tree); 518 } 519 520 smb_llist_exit(&user->u_tree_list); 521 return (NULL); 522 } 523 524 /* 525 * Disconnect all trees that match the specified client process-id. 526 */ 527 void 528 smb_user_close_pid( 529 smb_user_t *user, 530 uint16_t pid) 531 { 532 smb_tree_t *tree; 533 534 ASSERT(user); 535 ASSERT(user->u_magic == SMB_USER_MAGIC); 536 537 tree = smb_user_get_tree(&user->u_tree_list, NULL); 538 while (tree) { 539 smb_tree_t *next; 540 ASSERT(tree->t_user == user); 541 smb_tree_close_pid(tree, pid); 542 next = smb_user_get_tree(&user->u_tree_list, tree); 543 smb_tree_release(tree); 544 tree = next; 545 } 546 } 547 548 /* 549 * Disconnect all trees that this user has connected. 550 */ 551 void 552 smb_user_disconnect_trees( 553 smb_user_t *user) 554 { 555 smb_tree_t *tree; 556 557 ASSERT(user); 558 ASSERT(user->u_magic == SMB_USER_MAGIC); 559 560 tree = smb_user_get_tree(&user->u_tree_list, NULL); 561 while (tree) { 562 ASSERT(tree->t_user == user); 563 smb_tree_disconnect(tree, B_TRUE); 564 smb_tree_release(tree); 565 tree = smb_user_get_tree(&user->u_tree_list, NULL); 566 } 567 } 568 569 /* 570 * Disconnect all trees that match the specified share name. 571 */ 572 void 573 smb_user_disconnect_share( 574 smb_user_t *user, 575 const char *sharename) 576 { 577 smb_tree_t *tree; 578 smb_tree_t *next; 579 580 ASSERT(user); 581 ASSERT(user->u_magic == SMB_USER_MAGIC); 582 ASSERT(user->u_refcnt); 583 584 tree = smb_user_lookup_share(user, sharename, NULL); 585 while (tree) { 586 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 587 smb_session_cancel_requests(user->u_session, tree, NULL); 588 smb_tree_disconnect(tree, B_TRUE); 589 next = smb_user_lookup_share(user, sharename, tree); 590 smb_tree_release(tree); 591 tree = next; 592 } 593 } 594 595 /* 596 * Close a file by its unique id. 597 */ 598 int 599 smb_user_fclose(smb_user_t *user, uint32_t uniqid) 600 { 601 smb_llist_t *tree_list; 602 smb_tree_t *tree; 603 int rc = ENOENT; 604 605 ASSERT(user); 606 ASSERT(user->u_magic == SMB_USER_MAGIC); 607 608 tree_list = &user->u_tree_list; 609 ASSERT(tree_list); 610 611 smb_llist_enter(tree_list, RW_READER); 612 tree = smb_llist_head(tree_list); 613 614 while ((tree != NULL) && (rc == ENOENT)) { 615 ASSERT(tree->t_user == user); 616 617 if (smb_tree_hold(tree)) { 618 rc = smb_tree_fclose(tree, uniqid); 619 smb_tree_release(tree); 620 } 621 622 tree = smb_llist_next(tree_list, tree); 623 } 624 625 smb_llist_exit(tree_list); 626 return (rc); 627 } 628 629 /* 630 * Determine whether or not the user is an administrator. 631 * Members of the administrators group have administrative rights. 632 */ 633 boolean_t 634 smb_user_is_admin( 635 smb_user_t *user) 636 { 637 cred_t *u_cred; 638 639 ASSERT(user); 640 u_cred = user->u_cred; 641 ASSERT(u_cred); 642 643 if (smb_admins_sid == NULL) 644 return (B_FALSE); 645 646 if (smb_cred_is_member(u_cred, smb_admins_sid)) 647 return (B_TRUE); 648 649 return (B_FALSE); 650 } 651 652 /* 653 * This function should be called with a hold on the user. 654 */ 655 boolean_t 656 smb_user_namecmp(smb_user_t *user, const char *name) 657 { 658 char *fq_name; 659 boolean_t match; 660 661 if (smb_strcasecmp(name, user->u_name, 0) == 0) 662 return (B_TRUE); 663 664 fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP); 665 666 (void) snprintf(fq_name, MAXNAMELEN, "%s\\%s", 667 user->u_domain, user->u_name); 668 669 match = (smb_strcasecmp(name, fq_name, 0) == 0); 670 if (!match) { 671 (void) snprintf(fq_name, MAXNAMELEN, "%s@%s", 672 user->u_name, user->u_domain); 673 674 match = (smb_strcasecmp(name, fq_name, 0) == 0); 675 } 676 677 kmem_free(fq_name, MAXNAMELEN); 678 return (match); 679 } 680 681 /* 682 * If the enumeration request is for user data, handle the request 683 * here. Otherwise, pass it on to the trees. 684 * 685 * This function should be called with a hold on the user. 686 */ 687 int 688 smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum) 689 { 690 smb_tree_t *tree; 691 smb_tree_t *next; 692 int rc; 693 694 ASSERT(user); 695 ASSERT(user->u_magic == SMB_USER_MAGIC); 696 697 if (svcenum->se_type == SMB_SVCENUM_TYPE_USER) 698 return (smb_user_enum_private(user, svcenum)); 699 700 tree = smb_user_get_tree(&user->u_tree_list, NULL); 701 while (tree) { 702 ASSERT(tree->t_user == user); 703 704 rc = smb_tree_enum(tree, svcenum); 705 if (rc != 0) { 706 smb_tree_release(tree); 707 break; 708 } 709 710 next = smb_user_get_tree(&user->u_tree_list, tree); 711 smb_tree_release(tree); 712 tree = next; 713 } 714 715 return (rc); 716 } 717 718 /* *************************** Static Functions ***************************** */ 719 720 /* 721 * Determine whether or not a user is logged in. 722 * Typically, a reference can only be taken on a logged-in user. 723 * 724 * This is a private function and must be called with the user 725 * mutex held. 726 */ 727 static boolean_t 728 smb_user_is_logged_in(smb_user_t *user) 729 { 730 switch (user->u_state) { 731 case SMB_USER_STATE_LOGGED_IN: 732 return (B_TRUE); 733 734 case SMB_USER_STATE_LOGGING_OFF: 735 case SMB_USER_STATE_LOGGED_OFF: 736 return (B_FALSE); 737 738 default: 739 ASSERT(0); 740 return (B_FALSE); 741 } 742 } 743 744 /* 745 * Delete a user. The tree list should be empty. 746 * 747 * Remove the user from the session's user list before freeing resources 748 * associated with the user. 749 */ 750 void 751 smb_user_delete(void *arg) 752 { 753 smb_session_t *session; 754 smb_user_t *user = (smb_user_t *)arg; 755 756 SMB_USER_VALID(user); 757 ASSERT(user->u_refcnt == 0); 758 ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF); 759 760 session = user->u_session; 761 smb_llist_enter(&session->s_user_list, RW_WRITER); 762 smb_llist_remove(&session->s_user_list, user); 763 smb_idpool_free(&session->s_uid_pool, user->u_uid); 764 smb_llist_exit(&session->s_user_list); 765 766 mutex_enter(&user->u_mutex); 767 mutex_exit(&user->u_mutex); 768 769 user->u_magic = (uint32_t)~SMB_USER_MAGIC; 770 mutex_destroy(&user->u_mutex); 771 smb_llist_destructor(&user->u_tree_list); 772 smb_idpool_destructor(&user->u_tid_pool); 773 crfree(user->u_cred); 774 if (user->u_privcred) 775 crfree(user->u_privcred); 776 smb_mem_free(user->u_name); 777 smb_mem_free(user->u_domain); 778 kmem_cache_free(user->u_server->si_cache_user, user); 779 } 780 781 /* 782 * Get the next connected tree in the list. A reference is taken on 783 * the tree, which can be released later with smb_tree_release(). 784 * 785 * If the specified tree is NULL the search starts from the beginning of 786 * the tree list. If a tree is provided the search starts just after 787 * that tree. 788 * 789 * Returns NULL if there are no connected trees in the list. 790 */ 791 static smb_tree_t * 792 smb_user_get_tree( 793 smb_llist_t *tree_list, 794 smb_tree_t *tree) 795 { 796 ASSERT(tree_list); 797 798 smb_llist_enter(tree_list, RW_READER); 799 800 if (tree) { 801 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 802 tree = smb_llist_next(tree_list, tree); 803 } else { 804 tree = smb_llist_head(tree_list); 805 } 806 807 while (tree) { 808 if (smb_tree_hold(tree)) 809 break; 810 811 tree = smb_llist_next(tree_list, tree); 812 } 813 814 smb_llist_exit(tree_list); 815 return (tree); 816 } 817 818 cred_t * 819 smb_user_getcred(smb_user_t *user) 820 { 821 return (user->u_cred); 822 } 823 824 cred_t * 825 smb_user_getprivcred(smb_user_t *user) 826 { 827 return ((user->u_privcred)? user->u_privcred : user->u_cred); 828 } 829 830 /* 831 * Private function to support smb_user_enum. 832 */ 833 static int 834 smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum) 835 { 836 uint8_t *pb; 837 uint_t nbytes; 838 int rc; 839 840 if (svcenum->se_nskip > 0) { 841 svcenum->se_nskip--; 842 return (0); 843 } 844 845 if (svcenum->se_nitems >= svcenum->se_nlimit) { 846 svcenum->se_nitems = svcenum->se_nlimit; 847 return (0); 848 } 849 850 pb = &svcenum->se_buf[svcenum->se_bused]; 851 rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes); 852 if (rc == 0) { 853 svcenum->se_bavail -= nbytes; 854 svcenum->se_bused += nbytes; 855 svcenum->se_nitems++; 856 } 857 858 return (rc); 859 } 860 861 /* 862 * Encode the NetInfo for a user into a buffer. NetInfo contains 863 * information that is often needed in user space to support RPC 864 * requests. 865 */ 866 int 867 smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen, 868 uint32_t *nbytes) 869 { 870 smb_netuserinfo_t info; 871 int rc; 872 873 smb_user_netinfo_init(user, &info); 874 rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes); 875 smb_user_netinfo_fini(&info); 876 877 return (rc); 878 } 879 880 void 881 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info) 882 { 883 smb_session_t *session; 884 char *buf; 885 886 ASSERT(user); 887 ASSERT(user->u_domain); 888 ASSERT(user->u_name); 889 890 session = user->u_session; 891 ASSERT(session); 892 ASSERT(session->workstation); 893 894 info->ui_session_id = session->s_kid; 895 info->ui_native_os = session->native_os; 896 info->ui_ipaddr = session->ipaddr; 897 info->ui_numopens = session->s_file_cnt; 898 info->ui_smb_uid = user->u_uid; 899 info->ui_logon_time = user->u_logon_time; 900 info->ui_flags = user->u_flags; 901 info->ui_posix_uid = crgetuid(user->u_cred); 902 903 info->ui_domain_len = user->u_domain_len; 904 info->ui_domain = smb_mem_strdup(user->u_domain); 905 906 info->ui_account_len = user->u_name_len; 907 info->ui_account = smb_mem_strdup(user->u_name); 908 909 buf = kmem_alloc(MAXNAMELEN, KM_SLEEP); 910 smb_session_getclient(session, buf, MAXNAMELEN); 911 info->ui_workstation_len = strlen(buf) + 1; 912 info->ui_workstation = smb_mem_strdup(buf); 913 kmem_free(buf, MAXNAMELEN); 914 } 915 916 void 917 smb_user_netinfo_fini(smb_netuserinfo_t *info) 918 { 919 if (info == NULL) 920 return; 921 922 if (info->ui_domain) 923 smb_mem_free(info->ui_domain); 924 if (info->ui_account) 925 smb_mem_free(info->ui_account); 926 if (info->ui_workstation) 927 smb_mem_free(info->ui_workstation); 928 929 bzero(info, sizeof (smb_netuserinfo_t)); 930 } 931 932 static void 933 smb_user_nonauth_logon(uint32_t audit_sid) 934 { 935 (void) smb_kdoor_upcall(SMB_DR_USER_NONAUTH_LOGON, 936 &audit_sid, xdr_uint32_t, NULL, NULL); 937 } 938 939 static void 940 smb_user_auth_logoff(uint32_t audit_sid) 941 { 942 (void) smb_kdoor_upcall(SMB_DR_USER_AUTH_LOGOFF, 943 &audit_sid, xdr_uint32_t, NULL, NULL); 944 } 945 946 smb_token_t * 947 smb_get_token(smb_logon_t *user_info) 948 { 949 smb_token_t *token; 950 int rc; 951 952 token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP); 953 954 rc = smb_kdoor_upcall(SMB_DR_USER_AUTH_LOGON, 955 user_info, smb_logon_xdr, token, smb_token_xdr); 956 957 if (rc != 0) { 958 kmem_free(token, sizeof (smb_token_t)); 959 return (NULL); 960 } 961 962 if (!smb_token_valid(token)) { 963 smb_token_free(token); 964 return (NULL); 965 } 966 967 return (token); 968 } 969