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 2018 Nexenta Systems, Inc. All rights reserved. 24 * Copyright (c) 2016 by Delphix. All rights reserved. 25 */ 26 27 /* 28 * General Structures Layout 29 * ------------------------- 30 * 31 * This is a simplified diagram showing the relationship between most of the 32 * main structures. 33 * 34 * +-------------------+ 35 * | SMB_INFO | 36 * +-------------------+ 37 * | 38 * | 39 * v 40 * +-------------------+ +-------------------+ +-------------------+ 41 * | SESSION |<----->| SESSION |......| SESSION | 42 * +-------------------+ +-------------------+ +-------------------+ 43 * | | 44 * | | 45 * | v 46 * | +-------------------+ +-------------------+ +-------------------+ 47 * | | USER |<--->| USER |...| USER | 48 * | +-------------------+ +-------------------+ +-------------------+ 49 * | 50 * | 51 * v 52 * +-------------------+ +-------------------+ +-------------------+ 53 * | TREE |<----->| TREE |......| TREE | 54 * +-------------------+ +-------------------+ +-------------------+ 55 * | | 56 * | | 57 * | v 58 * | +-------+ +-------+ +-------+ 59 * | | OFILE |<----->| OFILE |......| OFILE | 60 * | +-------+ +-------+ +-------+ 61 * | 62 * | 63 * v 64 * +-------+ +------+ +------+ 65 * | ODIR |<----->| ODIR |......| ODIR | 66 * +-------+ +------+ +------+ 67 * 68 * 69 * User State Machine 70 * ------------------ 71 * 72 * 73 * | T0: Creation/Allocation 74 * | (1st session setup) 75 * v 76 * +-----------------------------+ 77 * | SMB_USER_STATE_LOGGING_ON |<----------+ 78 * +-----------------------------+ addl. session setup 79 * | | (more proc. required) 80 * | T2 | ^ 81 * | | | T1: (cont.) 82 * | +------->-------? 83 * v | T3: (fail) 84 * +-----------------------------+ v 85 * | SMB_USER_STATE_LOGGED_ON | (logged off) 86 * +-----------------------------+ 87 * | 88 * | T4 89 * | 90 * v 91 * +-----------------------------+ 92 * | SMB_USER_STATE_LOGGING_OFF | 93 * +-----------------------------+ 94 * | 95 * | T5 96 * | 97 * v 98 * +-----------------------------+ T6 99 * | SMB_USER_STATE_LOGGED_OFF |----------> Deletion/Free 100 * +-----------------------------+ 101 * 102 * SMB_USER_STATE_LOGGING_ON 103 * 104 * While in this state: 105 * - The user is in the list of users for their session. 106 * - References will be given out ONLY for session setup. 107 * - This user can not access anything yet. 108 * 109 * SMB_USER_STATE_LOGGED_ON 110 * 111 * While in this state: 112 * - The user is in the list of users for their session. 113 * - References will be given out if the user is looked up. 114 * - The user can access files and pipes. 115 * 116 * SMB_USER_STATE_LOGGING_OFF 117 * 118 * While in this state: 119 * - The user is in the list of users for their session. 120 * - References will not be given out if the user is looked up. 121 * - The trees the user connected are being disconnected. 122 * - The resources associated with the user remain. 123 * 124 * SMB_USER_STATE_LOGGED_OFF 125 * 126 * While in this state: 127 * - The user is queued in the list of users of their session. 128 * - References will not be given out if the user is looked up. 129 * - The user has no more trees connected. 130 * - The resources associated with the user remain. 131 * 132 * Transition T0 133 * 134 * First request in an SMB Session Setup sequence creates a 135 * new user object and adds it to the list of users for 136 * this session. User UID is assigned and returned. 137 * 138 * Transition T1 139 * 140 * Subsequent SMB Session Setup requests (on the same UID 141 * assigned in T0) update the state of this user object, 142 * communicating with smbd for the crypto work. 143 * 144 * Transition T2 145 * 146 * If the SMB Session Setup sequence is successful, T2 147 * makes the new user object available for requests. 148 * 149 * Transition T3 150 * 151 * If an Session Setup request gets an error other than 152 * the expected "more processing required", then T3 153 * leads to state "LOGGED_OFF" and then tear-down of the 154 * partially constructed user. 155 * 156 * Transition T4 157 * 158 * Normal SMB User Logoff request, or session tear-down. 159 * 160 * Transition T5 161 * 162 * This transition occurs in smb_user_release(). The resources associated 163 * with the user are deleted as well as the user. For the transition to 164 * occur, the user must be in the SMB_USER_STATE_LOGGED_OFF state and the 165 * reference count be zero. 166 * 167 * Comments 168 * -------- 169 * 170 * The state machine of the user structures is controlled by 3 elements: 171 * - The list of users of the session they belong to. 172 * - The mutex embedded in the structure itself. 173 * - The reference count. 174 * 175 * There's a mutex embedded in the user structure used to protect its fields 176 * and there's a lock embedded in the list of users of a session. To 177 * increment or to decrement the reference count the mutex must be entered. 178 * To insert the user into the list of users of the session and to remove 179 * the user from it, the lock must be entered in RW_WRITER mode. 180 * 181 * Rules of access to a user structure: 182 * 183 * 1) In order to avoid deadlocks, when both (mutex and lock of the session 184 * list) have to be entered, the lock must be entered first. 185 * 186 * 2) All actions applied to a user require a reference count. 187 * 188 * 3) There are 2 ways of getting a reference count. One is when the user 189 * logs in. The other when the user is looked up. 190 * 191 * It should be noted that the reference count of a user registers the 192 * number of references to the user in other structures (such as an smb 193 * request). The reference count is not incremented in these 2 instances: 194 * 195 * 1) The user is logged in. An user is anchored by their state. If there's 196 * no activity involving a user currently logged in, the reference 197 * count of that user is zero. 198 * 199 * 2) The user is queued in the list of users of the session. The fact of 200 * being queued in that list is NOT registered by incrementing the 201 * reference count. 202 */ 203 #include <sys/types.h> 204 #include <sys/sid.h> 205 #include <sys/priv_names.h> 206 #include <smbsrv/smb_kproto.h> 207 #include <smbsrv/smb_door.h> 208 209 #define ADMINISTRATORS_SID "S-1-5-32-544" 210 211 static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *); 212 static void smb_user_auth_logoff(smb_user_t *); 213 static void smb_user_logoff_tq(void *); 214 215 216 /* 217 * Create a new user. 218 */ 219 smb_user_t * 220 smb_user_new(smb_session_t *session) 221 { 222 smb_user_t *user; 223 224 ASSERT(session); 225 ASSERT(session->s_magic == SMB_SESSION_MAGIC); 226 227 user = kmem_cache_alloc(smb_cache_user, KM_SLEEP); 228 bzero(user, sizeof (smb_user_t)); 229 230 user->u_refcnt = 1; 231 user->u_session = session; 232 user->u_server = session->s_server; 233 user->u_logon_time = gethrestime_sec(); 234 235 if (smb_idpool_alloc(&session->s_uid_pool, &user->u_uid)) 236 goto errout; 237 238 mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL); 239 user->u_state = SMB_USER_STATE_LOGGING_ON; 240 user->u_magic = SMB_USER_MAGIC; 241 242 smb_llist_enter(&session->s_user_list, RW_WRITER); 243 smb_llist_insert_tail(&session->s_user_list, user); 244 smb_llist_exit(&session->s_user_list); 245 smb_server_inc_users(session->s_server); 246 247 return (user); 248 249 errout: 250 if (user->u_uid != 0) 251 smb_idpool_free(&session->s_uid_pool, user->u_uid); 252 kmem_cache_free(smb_cache_user, user); 253 return (NULL); 254 } 255 256 /* 257 * Fill in the details of a user, meaning a transition 258 * from state LOGGING_ON to state LOGGED_ON. 259 */ 260 int 261 smb_user_logon( 262 smb_user_t *user, 263 cred_t *cr, 264 char *domain_name, 265 char *account_name, 266 uint32_t flags, 267 uint32_t privileges, 268 uint32_t audit_sid) 269 { 270 ksocket_t authsock = NULL; 271 timeout_id_t tmo = NULL; 272 273 ASSERT(user->u_magic == SMB_USER_MAGIC); 274 ASSERT(cr); 275 ASSERT(account_name); 276 ASSERT(domain_name); 277 278 mutex_enter(&user->u_mutex); 279 280 if (user->u_state != SMB_USER_STATE_LOGGING_ON) { 281 mutex_exit(&user->u_mutex); 282 return (-1); 283 } 284 285 /* 286 * In the transition from LOGGING_ON to LOGGED_ON, 287 * we always have an auth. socket to close. 288 */ 289 authsock = user->u_authsock; 290 ASSERT(authsock != NULL); 291 user->u_authsock = NULL; 292 tmo = user->u_auth_tmo; 293 user->u_auth_tmo = NULL; 294 295 user->u_state = SMB_USER_STATE_LOGGED_ON; 296 user->u_flags = flags; 297 user->u_name_len = strlen(account_name) + 1; 298 user->u_domain_len = strlen(domain_name) + 1; 299 user->u_name = smb_mem_strdup(account_name); 300 user->u_domain = smb_mem_strdup(domain_name); 301 user->u_audit_sid = audit_sid; 302 303 smb_user_setcred(user, cr, privileges); 304 305 mutex_exit(&user->u_mutex); 306 307 /* Timeout callback takes u_mutex. See untimeout(9f) */ 308 if (tmo != NULL) 309 (void) untimeout(tmo); 310 311 /* This close can block, so not under the mutex. */ 312 smb_authsock_close(user, authsock); 313 314 return (0); 315 } 316 317 /* 318 * smb_user_logoff 319 * 320 * Change the user state and disconnect trees. 321 * The user list must not be entered or modified here. 322 */ 323 void 324 smb_user_logoff( 325 smb_user_t *user) 326 { 327 ksocket_t authsock = NULL; 328 timeout_id_t tmo = NULL; 329 330 ASSERT(user->u_magic == SMB_USER_MAGIC); 331 332 mutex_enter(&user->u_mutex); 333 ASSERT(user->u_refcnt); 334 switch (user->u_state) { 335 case SMB_USER_STATE_LOGGING_ON: 336 authsock = user->u_authsock; 337 user->u_authsock = NULL; 338 tmo = user->u_auth_tmo; 339 user->u_auth_tmo = NULL; 340 user->u_state = SMB_USER_STATE_LOGGED_OFF; 341 smb_server_dec_users(user->u_server); 342 break; 343 344 case SMB_USER_STATE_LOGGED_ON: 345 /* 346 * The user is moved into a state indicating that the log off 347 * process has started. 348 */ 349 user->u_state = SMB_USER_STATE_LOGGING_OFF; 350 mutex_exit(&user->u_mutex); 351 smb_session_disconnect_owned_trees(user->u_session, user); 352 smb_user_auth_logoff(user); 353 mutex_enter(&user->u_mutex); 354 user->u_state = SMB_USER_STATE_LOGGED_OFF; 355 smb_server_dec_users(user->u_server); 356 break; 357 358 case SMB_USER_STATE_LOGGED_OFF: 359 case SMB_USER_STATE_LOGGING_OFF: 360 break; 361 362 default: 363 ASSERT(0); 364 break; 365 } 366 mutex_exit(&user->u_mutex); 367 368 /* Timeout callback takes u_mutex. See untimeout(9f) */ 369 if (tmo != NULL) 370 (void) untimeout(tmo); 371 372 /* This close can block, so not under the mutex. */ 373 if (authsock != NULL) { 374 smb_authsock_close(user, authsock); 375 } 376 } 377 378 /* 379 * Take a reference on a user. Do not return a reference unless the user is in 380 * the logged-in state. 381 */ 382 boolean_t 383 smb_user_hold(smb_user_t *user) 384 { 385 SMB_USER_VALID(user); 386 387 mutex_enter(&user->u_mutex); 388 389 if (user->u_state == SMB_USER_STATE_LOGGED_ON) { 390 user->u_refcnt++; 391 mutex_exit(&user->u_mutex); 392 return (B_TRUE); 393 } 394 395 mutex_exit(&user->u_mutex); 396 return (B_FALSE); 397 } 398 399 /* 400 * Unconditionally take a reference on a user. 401 */ 402 void 403 smb_user_hold_internal(smb_user_t *user) 404 { 405 SMB_USER_VALID(user); 406 407 mutex_enter(&user->u_mutex); 408 user->u_refcnt++; 409 mutex_exit(&user->u_mutex); 410 } 411 412 /* 413 * Release a reference on a user. If the reference count falls to 414 * zero and the user has logged off, post the object for deletion. 415 * Object deletion is deferred to avoid modifying a list while an 416 * iteration may be in progress. 417 */ 418 void 419 smb_user_release( 420 smb_user_t *user) 421 { 422 ASSERT(user->u_magic == SMB_USER_MAGIC); 423 424 mutex_enter(&user->u_mutex); 425 ASSERT(user->u_refcnt); 426 user->u_refcnt--; 427 428 switch (user->u_state) { 429 case SMB_USER_STATE_LOGGED_OFF: 430 if (user->u_refcnt == 0) 431 smb_session_post_user(user->u_session, user); 432 break; 433 434 case SMB_USER_STATE_LOGGING_ON: 435 case SMB_USER_STATE_LOGGED_ON: 436 case SMB_USER_STATE_LOGGING_OFF: 437 break; 438 439 default: 440 ASSERT(0); 441 break; 442 } 443 mutex_exit(&user->u_mutex); 444 } 445 446 /* 447 * Timeout handler for user logons that stay too long in 448 * state SMB_USER_STATE_LOGGING_ON. This is setup by a 449 * timeout call in smb_authsock_open, and called in a 450 * callout thread, so schedule a taskq job to do the 451 * real work of logging off this user. 452 */ 453 void 454 smb_user_auth_tmo(void *arg) 455 { 456 smb_user_t *user = arg; 457 smb_request_t *sr; 458 459 SMB_USER_VALID(user); 460 461 /* 462 * If we can't allocate a request, it means the 463 * session is being torn down, so nothing to do. 464 */ 465 sr = smb_request_alloc(user->u_session, 0); 466 if (sr == NULL) 467 return; 468 469 /* 470 * Check user state, and take a hold if it's 471 * still logging on. If not, we're done. 472 */ 473 mutex_enter(&user->u_mutex); 474 if (user->u_state != SMB_USER_STATE_LOGGING_ON) { 475 mutex_exit(&user->u_mutex); 476 smb_request_free(sr); 477 return; 478 } 479 /* smb_user_hold_internal */ 480 user->u_refcnt++; 481 mutex_exit(&user->u_mutex); 482 483 /* 484 * The user hold is given to the SR, and released in 485 * smb_user_logoff_tq / smb_request_free 486 */ 487 sr->uid_user = user; 488 sr->user_cr = user->u_cred; 489 sr->sr_state = SMB_REQ_STATE_SUBMITTED; 490 491 (void) taskq_dispatch( 492 user->u_server->sv_worker_pool, 493 smb_user_logoff_tq, sr, TQ_SLEEP); 494 } 495 496 /* 497 * Helper for smb_user_auth_tmo() 498 */ 499 static void 500 smb_user_logoff_tq(void *arg) 501 { 502 smb_request_t *sr = arg; 503 504 SMB_REQ_VALID(sr); 505 506 mutex_enter(&sr->sr_mutex); 507 sr->sr_worker = curthread; 508 sr->sr_state = SMB_REQ_STATE_ACTIVE; 509 mutex_exit(&sr->sr_mutex); 510 511 smb_user_logoff(sr->uid_user); 512 513 sr->sr_state = SMB_REQ_STATE_COMPLETED; 514 smb_request_free(sr); 515 } 516 517 /* 518 * Determine whether or not the user is an administrator. 519 * Members of the administrators group have administrative rights. 520 */ 521 boolean_t 522 smb_user_is_admin(smb_user_t *user) 523 { 524 #ifdef _KERNEL 525 char sidstr[SMB_SID_STRSZ]; 526 ksidlist_t *ksidlist; 527 ksid_t ksid1; 528 ksid_t *ksid2; 529 int i; 530 #endif /* _KERNEL */ 531 boolean_t rc = B_FALSE; 532 533 ASSERT(user); 534 ASSERT(user->u_cred); 535 536 if (SMB_USER_IS_ADMIN(user)) 537 return (B_TRUE); 538 539 #ifdef _KERNEL 540 bzero(&ksid1, sizeof (ksid_t)); 541 (void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ); 542 ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0); 543 ksid1.ks_domain = ksid_lookupdomain(sidstr); 544 545 ksidlist = crgetsidlist(user->u_cred); 546 ASSERT(ksidlist); 547 ASSERT(ksid1.ks_domain); 548 ASSERT(ksid1.ks_domain->kd_name); 549 550 i = 0; 551 ksid2 = crgetsid(user->u_cred, KSID_USER); 552 do { 553 ASSERT(ksid2->ks_domain); 554 ASSERT(ksid2->ks_domain->kd_name); 555 556 if (strcmp(ksid1.ks_domain->kd_name, 557 ksid2->ks_domain->kd_name) == 0 && 558 ksid1.ks_rid == ksid2->ks_rid) { 559 user->u_flags |= SMB_USER_FLAG_ADMIN; 560 rc = B_TRUE; 561 break; 562 } 563 564 ksid2 = &ksidlist->ksl_sids[i]; 565 } while (i++ < ksidlist->ksl_nsid); 566 567 ksid_rele(&ksid1); 568 #endif /* _KERNEL */ 569 return (rc); 570 } 571 572 /* 573 * This function should be called with a hold on the user. 574 */ 575 boolean_t 576 smb_user_namecmp(smb_user_t *user, const char *name) 577 { 578 char *fq_name; 579 boolean_t match; 580 581 if (smb_strcasecmp(name, user->u_name, 0) == 0) 582 return (B_TRUE); 583 584 fq_name = kmem_alloc(MAXNAMELEN, KM_SLEEP); 585 586 (void) snprintf(fq_name, MAXNAMELEN, "%s\\%s", 587 user->u_domain, user->u_name); 588 589 match = (smb_strcasecmp(name, fq_name, 0) == 0); 590 if (!match) { 591 (void) snprintf(fq_name, MAXNAMELEN, "%s@%s", 592 user->u_name, user->u_domain); 593 594 match = (smb_strcasecmp(name, fq_name, 0) == 0); 595 } 596 597 kmem_free(fq_name, MAXNAMELEN); 598 return (match); 599 } 600 601 /* 602 * If the enumeration request is for user data, handle the request 603 * here. Otherwise, pass it on to the trees. 604 * 605 * This function should be called with a hold on the user. 606 */ 607 int 608 smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum) 609 { 610 int rc = 0; 611 612 ASSERT(user); 613 ASSERT(user->u_magic == SMB_USER_MAGIC); 614 615 if (svcenum->se_type == SMB_SVCENUM_TYPE_USER) 616 return (smb_user_enum_private(user, svcenum)); 617 618 return (rc); 619 } 620 621 /* *************************** Static Functions ***************************** */ 622 623 /* 624 * Delete a user. The tree list should be empty. 625 * 626 * Remove the user from the session's user list before freeing resources 627 * associated with the user. 628 */ 629 void 630 smb_user_delete(void *arg) 631 { 632 smb_session_t *session; 633 smb_user_t *user = (smb_user_t *)arg; 634 635 SMB_USER_VALID(user); 636 ASSERT(user->u_refcnt == 0); 637 ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF); 638 ASSERT(user->u_authsock == NULL); 639 ASSERT(user->u_auth_tmo == NULL); 640 641 session = user->u_session; 642 smb_llist_enter(&session->s_user_list, RW_WRITER); 643 smb_llist_remove(&session->s_user_list, user); 644 smb_idpool_free(&session->s_uid_pool, user->u_uid); 645 smb_llist_exit(&session->s_user_list); 646 647 mutex_enter(&user->u_mutex); 648 mutex_exit(&user->u_mutex); 649 650 user->u_magic = (uint32_t)~SMB_USER_MAGIC; 651 mutex_destroy(&user->u_mutex); 652 if (user->u_cred) 653 crfree(user->u_cred); 654 if (user->u_privcred) 655 crfree(user->u_privcred); 656 smb_mem_free(user->u_name); 657 smb_mem_free(user->u_domain); 658 kmem_cache_free(smb_cache_user, user); 659 } 660 661 cred_t * 662 smb_user_getcred(smb_user_t *user) 663 { 664 return (user->u_cred); 665 } 666 667 cred_t * 668 smb_user_getprivcred(smb_user_t *user) 669 { 670 return ((user->u_privcred)? user->u_privcred : user->u_cred); 671 } 672 673 #ifdef _KERNEL 674 /* 675 * Assign the user cred and privileges. 676 * 677 * If the user has backup and/or restore privleges, dup the cred 678 * and add those privileges to this new privileged cred. 679 */ 680 void 681 smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges) 682 { 683 cred_t *privcred = NULL; 684 685 ASSERT(cr); 686 crhold(cr); 687 688 if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE)) 689 privcred = crdup(cr); 690 691 if (privcred != NULL) { 692 if (privileges & SMB_USER_PRIV_BACKUP) { 693 (void) crsetpriv(privcred, PRIV_FILE_DAC_READ, 694 PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL); 695 } 696 697 if (privileges & SMB_USER_PRIV_RESTORE) { 698 (void) crsetpriv(privcred, PRIV_FILE_DAC_WRITE, 699 PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF, 700 PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY, 701 PRIV_FILE_OWNER, PRIV_FILE_SETID, 702 PRIV_SYS_LINKDIR, PRIV_SYS_MOUNT, NULL); 703 } 704 } 705 706 user->u_cred = cr; 707 user->u_privcred = privcred; 708 user->u_privileges = privileges; 709 } 710 #endif /* _KERNEL */ 711 712 /* 713 * Private function to support smb_user_enum. 714 */ 715 static int 716 smb_user_enum_private(smb_user_t *user, smb_svcenum_t *svcenum) 717 { 718 uint8_t *pb; 719 uint_t nbytes; 720 int rc; 721 722 if (svcenum->se_nskip > 0) { 723 svcenum->se_nskip--; 724 return (0); 725 } 726 727 if (svcenum->se_nitems >= svcenum->se_nlimit) { 728 svcenum->se_nitems = svcenum->se_nlimit; 729 return (0); 730 } 731 732 pb = &svcenum->se_buf[svcenum->se_bused]; 733 rc = smb_user_netinfo_encode(user, pb, svcenum->se_bavail, &nbytes); 734 if (rc == 0) { 735 svcenum->se_bavail -= nbytes; 736 svcenum->se_bused += nbytes; 737 svcenum->se_nitems++; 738 } 739 740 return (rc); 741 } 742 743 /* 744 * Encode the NetInfo for a user into a buffer. NetInfo contains 745 * information that is often needed in user space to support RPC 746 * requests. 747 */ 748 int 749 smb_user_netinfo_encode(smb_user_t *user, uint8_t *buf, size_t buflen, 750 uint32_t *nbytes) 751 { 752 smb_netuserinfo_t info; 753 int rc; 754 755 smb_user_netinfo_init(user, &info); 756 rc = smb_netuserinfo_encode(&info, buf, buflen, nbytes); 757 smb_user_netinfo_fini(&info); 758 759 return (rc); 760 } 761 762 void 763 smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info) 764 { 765 smb_session_t *session; 766 char *buf; 767 768 ASSERT(user); 769 ASSERT(user->u_domain); 770 ASSERT(user->u_name); 771 772 session = user->u_session; 773 ASSERT(session); 774 ASSERT(session->workstation); 775 776 info->ui_session_id = session->s_kid; 777 info->ui_native_os = session->native_os; 778 info->ui_ipaddr = session->ipaddr; 779 info->ui_numopens = session->s_file_cnt; 780 info->ui_smb_uid = user->u_uid; 781 info->ui_logon_time = user->u_logon_time; 782 info->ui_flags = user->u_flags; 783 info->ui_posix_uid = crgetuid(user->u_cred); 784 785 info->ui_domain_len = user->u_domain_len; 786 info->ui_domain = smb_mem_strdup(user->u_domain); 787 788 info->ui_account_len = user->u_name_len; 789 info->ui_account = smb_mem_strdup(user->u_name); 790 791 buf = kmem_alloc(MAXNAMELEN, KM_SLEEP); 792 smb_session_getclient(session, buf, MAXNAMELEN); 793 info->ui_workstation_len = strlen(buf) + 1; 794 info->ui_workstation = smb_mem_strdup(buf); 795 kmem_free(buf, MAXNAMELEN); 796 } 797 798 void 799 smb_user_netinfo_fini(smb_netuserinfo_t *info) 800 { 801 if (info == NULL) 802 return; 803 804 if (info->ui_domain) 805 smb_mem_free(info->ui_domain); 806 if (info->ui_account) 807 smb_mem_free(info->ui_account); 808 if (info->ui_workstation) 809 smb_mem_free(info->ui_workstation); 810 811 bzero(info, sizeof (smb_netuserinfo_t)); 812 } 813 814 static void 815 smb_user_auth_logoff(smb_user_t *user) 816 { 817 uint32_t audit_sid = user->u_audit_sid; 818 819 (void) smb_kdoor_upcall(user->u_server, SMB_DR_USER_AUTH_LOGOFF, 820 &audit_sid, xdr_uint32_t, NULL, NULL); 821 } 822