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 /* 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2016 by Delphix. All rights reserved. 25 * Copyright 2021 Tintri by DDN, Inc. All rights reserved. 26 */ 27 28 /* 29 * General Structures Layout 30 * ------------------------- 31 * 32 * This is a simplified diagram showing the relationship between most of the 33 * main structures. 34 * 35 * +-------------------+ 36 * | SMB_INFO | 37 * +-------------------+ 38 * | 39 * | 40 * v 41 * +-------------------+ +-------------------+ +-------------------+ 42 * | SESSION |<----->| SESSION |......| SESSION | 43 * +-------------------+ +-------------------+ +-------------------+ 44 * | | 45 * | | 46 * | v 47 * | +-------------------+ +-------------------+ +-------------------+ 48 * | | USER |<--->| USER |...| USER | 49 * | +-------------------+ +-------------------+ +-------------------+ 50 * | 51 * | 52 * v 53 * +-------------------+ +-------------------+ +-------------------+ 54 * | TREE |<----->| TREE |......| TREE | 55 * +-------------------+ +-------------------+ +-------------------+ 56 * | | 57 * | | 58 * | v 59 * | +-------+ +-------+ +-------+ 60 * | | OFILE |<----->| OFILE |......| OFILE | 61 * | +-------+ +-------+ +-------+ 62 * | 63 * | 64 * v 65 * +-------+ +------+ +------+ 66 * | ODIR |<----->| ODIR |......| ODIR | 67 * +-------+ +------+ +------+ 68 * 69 * 70 * Tree State Machine 71 * ------------------ 72 * 73 * +-----------------------------+ T0 74 * | SMB_TREE_STATE_CONNECTED |<----------- Creation/Allocation 75 * +-----------------------------+ 76 * | 77 * | T1 78 * | 79 * v 80 * +------------------------------+ 81 * | SMB_TREE_STATE_DISCONNECTING | 82 * +------------------------------+ 83 * | 84 * | T2 85 * | 86 * v 87 * +-----------------------------+ T3 88 * | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free 89 * +-----------------------------+ 90 * 91 * SMB_TREE_STATE_CONNECTED 92 * 93 * While in this state: 94 * - The tree is queued in the list of trees of its user. 95 * - References will be given out if the tree is looked up. 96 * - Files under that tree can be accessed. 97 * 98 * SMB_TREE_STATE_DISCONNECTING 99 * 100 * While in this state: 101 * - The tree is queued in the list of trees of its user. 102 * - References will not be given out if the tree is looked up. 103 * - The files and directories open under the tree are being closed. 104 * - The resources associated with the tree remain. 105 * 106 * SMB_TREE_STATE_DISCONNECTED 107 * 108 * While in this state: 109 * - The tree is queued in the list of trees of its user. 110 * - References will not be given out if the tree is looked up. 111 * - The tree has no more files and directories opened. 112 * - The resources associated with the tree remain. 113 * 114 * Transition T0 115 * 116 * This transition occurs in smb_tree_connect(). A new tree is created and 117 * added to the list of trees of a user. 118 * 119 * Transition T1 120 * 121 * This transition occurs in smb_tree_disconnect(). 122 * 123 * Transition T2 124 * 125 * This transition occurs in smb_tree_disconnect() 126 * 127 * Transition T3 128 * 129 * This transition occurs in smb_tree_release(). The resources associated 130 * with the tree are freed as well as the tree structure. For the transition 131 * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED and the 132 * reference count must be zero. 133 * 134 * Comments 135 * -------- 136 * 137 * The state machine of the tree structures is controlled by 3 elements: 138 * - The list of trees of the user it belongs to. 139 * - The mutex embedded in the structure itself. 140 * - The reference count. 141 * 142 * There's a mutex embedded in the tree structure used to protect its fields 143 * and there's a lock embedded in the list of trees of a user. To 144 * increment or to decrement the reference count the mutex must be entered. 145 * To insert the tree into the list of trees of the user and to remove 146 * the tree from it, the lock must be entered in RW_WRITER mode. 147 * 148 * Rules of access to a tree structure: 149 * 150 * 1) In order to avoid deadlocks, when both (mutex and lock of the user 151 * list) have to be entered, the lock must be entered first. Additionally, 152 * when both the (mutex and lock of the ofile list) have to be entered, 153 * the mutex must be entered first. However, the ofile list lock must NOT 154 * be dropped while the mutex is held in such a way that the ofile deleteq 155 * is flushed. 156 * 157 * 2) All actions applied to a tree require a reference count. 158 * 159 * 3) There are 2 ways of getting a reference count: when a tree is 160 * connected and when a tree is looked up. 161 * 162 * It should be noted that the reference count of a tree registers the 163 * number of references to the tree in other structures (such as an smb 164 * request). The reference count is not incremented in these 2 instances: 165 * 166 * 1) The tree is connected. An tree is anchored by its state. If there's 167 * no activity involving a tree currently connected, the reference 168 * count of that tree is zero. 169 * 170 * 2) The tree is queued in the list of trees of the user. The fact of 171 * being queued in that list is NOT registered by incrementing the 172 * reference count. 173 */ 174 175 #include <sys/refstr_impl.h> 176 #include <smbsrv/smb_kproto.h> 177 #include <smbsrv/smb_ktypes.h> 178 #include <smbsrv/smb_fsops.h> 179 #include <smbsrv/smb_share.h> 180 181 int smb_tcon_mute = 0; 182 183 uint32_t smb_tree_connect_core(smb_request_t *); 184 uint32_t smb_tree_connect_disk(smb_request_t *, smb_arg_tcon_t *); 185 uint32_t smb_tree_connect_printq(smb_request_t *, smb_arg_tcon_t *); 186 uint32_t smb_tree_connect_ipc(smb_request_t *, smb_arg_tcon_t *); 187 static void smb_tree_dealloc(void *); 188 static boolean_t smb_tree_is_connected_locked(smb_tree_t *); 189 static char *smb_tree_get_sharename(char *); 190 static int smb_tree_getattr(const smb_kshare_t *, smb_node_t *, smb_tree_t *); 191 static void smb_tree_get_creation(smb_node_t *, smb_tree_t *); 192 static void smb_tree_get_volname(vfs_t *, smb_tree_t *); 193 static void smb_tree_get_flags(const smb_kshare_t *, vfs_t *, smb_tree_t *); 194 static void smb_tree_log(smb_request_t *, const char *, const char *, ...); 195 static void smb_tree_close_odirs(smb_tree_t *, uint32_t); 196 static void smb_tree_set_execinfo(smb_tree_t *, smb_shr_execinfo_t *, int); 197 static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *); 198 static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *); 199 static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *); 200 static void smb_tree_netinfo_fini(smb_netconnectinfo_t *); 201 202 uint32_t 203 smb_tree_connect(smb_request_t *sr) 204 { 205 smb_server_t *sv = sr->sr_server; 206 uint32_t status; 207 208 if (smb_threshold_enter(&sv->sv_tcon_ct) != 0) { 209 return (NT_STATUS_INSUFF_SERVER_RESOURCES); 210 } 211 212 status = smb_tree_connect_core(sr); 213 smb_threshold_exit(&sv->sv_tcon_ct); 214 return (status); 215 } 216 217 /* 218 * Lookup the share name dispatch the appropriate stype handler. 219 * Share names are case insensitive so we map the share name to 220 * lower-case as a convenience for internal processing. 221 * 222 * Valid service values are: 223 * A: Disk share 224 * LPT1: Printer 225 * IPC Named pipe (IPC$ is reserved as the named pipe share). 226 * COMM Communications device 227 * ????? Any type of device (wildcard) 228 */ 229 uint32_t 230 smb_tree_connect_core(smb_request_t *sr) 231 { 232 smb_arg_tcon_t *tcon = &sr->sr_tcon; 233 smb_kshare_t *si; 234 char *name; 235 uint32_t status; 236 237 (void) smb_strlwr(tcon->path); 238 239 if ((name = smb_tree_get_sharename(tcon->path)) == NULL) { 240 smb_tree_log(sr, tcon->path, "invalid UNC path"); 241 return (NT_STATUS_BAD_NETWORK_NAME); 242 } 243 244 si = smb_kshare_lookup(sr->sr_server, name); 245 if (si == NULL) { 246 smb_tree_log(sr, name, "share not found"); 247 return (NT_STATUS_BAD_NETWORK_NAME); 248 } 249 250 if (!strcasecmp(SMB_SHARE_PRINT, name)) { 251 smb_kshare_release(sr->sr_server, si); 252 smb_tree_log(sr, name, "access not permitted"); 253 return (NT_STATUS_ACCESS_DENIED); 254 } 255 256 /* NB: name points into tcon->path - don't free it. */ 257 tcon->name = name; 258 sr->sr_tcon.si = si; 259 260 /* 261 * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request 262 * 263 * If we support 3.x, RejectUnencryptedAccess is TRUE, 264 * if Tcon.EncryptData is TRUE or global EncryptData is TRUE, 265 * and the connection doesn't support encryption, 266 * return ACCESS_DENIED. 267 * 268 * If RejectUnencryptedAccess is TRUE, we force max_protocol 269 * to at least 3.0. Additionally, if the tree requires encryption, 270 * we don't care what we support, we still enforce encryption. 271 */ 272 if ((sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED || 273 si->shr_encrypt == SMB_CONFIG_REQUIRED) && 274 (sr->session->srv_cap & SMB2_CAP_ENCRYPTION) == 0) { 275 status = NT_STATUS_ACCESS_DENIED; 276 goto out; 277 } 278 279 switch (si->shr_type & STYPE_MASK) { 280 case STYPE_DISKTREE: 281 status = smb_tree_connect_disk(sr, &sr->sr_tcon); 282 break; 283 case STYPE_IPC: 284 status = smb_tree_connect_ipc(sr, &sr->sr_tcon); 285 break; 286 case STYPE_PRINTQ: 287 status = smb_tree_connect_printq(sr, &sr->sr_tcon); 288 break; 289 default: 290 status = NT_STATUS_BAD_DEVICE_TYPE; 291 break; 292 } 293 294 out: 295 smb_kshare_release(sr->sr_server, si); 296 sr->sr_tcon.si = NULL; 297 298 return (status); 299 } 300 301 /* 302 * Disconnect a tree. 303 * 304 * The "do_exec" arg is obsolete and ignored. 305 */ 306 void 307 smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec) 308 { 309 _NOTE(ARGUNUSED(do_exec)) 310 smb_shr_execinfo_t execinfo; 311 312 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 313 314 mutex_enter(&tree->t_mutex); 315 ASSERT(tree->t_refcnt); 316 317 if (!smb_tree_is_connected_locked(tree)) { 318 mutex_exit(&tree->t_mutex); 319 return; 320 } 321 322 /* 323 * Indicate that the disconnect process has started. 324 */ 325 tree->t_state = SMB_TREE_STATE_DISCONNECTING; 326 mutex_exit(&tree->t_mutex); 327 328 /* 329 * The files opened under this tree are closed. 330 */ 331 smb_ofile_close_all(tree, 0); 332 /* 333 * The directories opened under this tree are closed. 334 */ 335 smb_tree_close_odirs(tree, 0); 336 337 if ((tree->t_execflags & SMB_EXEC_UNMAP) != 0) { 338 smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_UNMAP); 339 (void) smb_kshare_exec(tree->t_server, &execinfo); 340 } 341 } 342 343 /* 344 * Take a reference on a tree. 345 */ 346 boolean_t 347 smb_tree_hold( 348 smb_tree_t *tree) 349 { 350 SMB_TREE_VALID(tree); 351 352 mutex_enter(&tree->t_mutex); 353 354 if (smb_tree_is_connected_locked(tree)) { 355 tree->t_refcnt++; 356 mutex_exit(&tree->t_mutex); 357 return (B_TRUE); 358 } 359 360 mutex_exit(&tree->t_mutex); 361 return (B_FALSE); 362 } 363 364 /* 365 * Bump the hold count regardless of the tree state. This is used in 366 * some internal code paths where we've already checked that we had a 367 * valid tree connection, and don't want to deal with the possiblity 368 * that the tree state might have changed to disconnecting after our 369 * original hold was taken. It's correct to continue processing a 370 * request even when new requests cannot lookup that tree anymore. 371 */ 372 void 373 smb_tree_hold_internal( 374 smb_tree_t *tree) 375 { 376 SMB_TREE_VALID(tree); 377 378 mutex_enter(&tree->t_mutex); 379 tree->t_refcnt++; 380 mutex_exit(&tree->t_mutex); 381 } 382 383 /* 384 * Release a reference on a tree. If the tree is disconnected and the 385 * reference count falls to zero, post the object for deletion. 386 * Object deletion is deferred to avoid modifying a list while an 387 * iteration may be in progress. 388 */ 389 void 390 smb_tree_release( 391 smb_tree_t *tree) 392 { 393 SMB_TREE_VALID(tree); 394 395 /* flush the ofile and odir lists' delete queues */ 396 smb_llist_flush(&tree->t_ofile_list); 397 smb_llist_flush(&tree->t_odir_list); 398 399 mutex_enter(&tree->t_mutex); 400 ASSERT(tree->t_refcnt); 401 tree->t_refcnt--; 402 403 switch (tree->t_state) { 404 case SMB_TREE_STATE_DISCONNECTING: 405 if (tree->t_refcnt == 0) { 406 smb_session_t *ssn = tree->t_session; 407 tree->t_state = SMB_TREE_STATE_DISCONNECTED; 408 smb_llist_post(&ssn->s_tree_list, tree, 409 smb_tree_dealloc); 410 } 411 break; 412 case SMB_TREE_STATE_CONNECTED: 413 break; 414 default: 415 ASSERT(0); 416 break; 417 } 418 419 mutex_exit(&tree->t_mutex); 420 } 421 422 /* 423 * Close ofiles and odirs that match pid. 424 */ 425 void 426 smb_tree_close_pid( 427 smb_tree_t *tree, 428 uint32_t pid) 429 { 430 ASSERT(tree); 431 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 432 433 smb_ofile_close_all(tree, pid); 434 smb_tree_close_odirs(tree, pid); 435 } 436 437 /* 438 * Check whether or not a tree supports the features identified by flags. 439 */ 440 boolean_t 441 smb_tree_has_feature(smb_tree_t *tree, uint32_t flags) 442 { 443 ASSERT(tree); 444 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 445 446 return ((tree->t_flags & flags) == flags); 447 } 448 449 /* 450 * If the enumeration request is for tree data, handle the request 451 * here. Otherwise, pass it on to the ofiles. 452 * 453 * This function should be called with a hold on the tree. 454 */ 455 int 456 smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum) 457 { 458 smb_llist_t *of_list; 459 smb_ofile_t *of; 460 int rc = 0; 461 462 if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE) 463 return (smb_tree_enum_private(tree, svcenum)); 464 465 of_list = &tree->t_ofile_list; 466 smb_llist_enter(of_list, RW_READER); 467 468 of = smb_llist_head(of_list); 469 while (of) { 470 if (smb_ofile_hold(of)) { 471 rc = smb_ofile_enum(of, svcenum); 472 smb_ofile_release(of); 473 } 474 if (rc != 0) 475 break; 476 of = smb_llist_next(of_list, of); 477 } 478 479 smb_llist_exit(of_list); 480 481 return (rc); 482 } 483 484 /* 485 * Close a file by its unique id. 486 */ 487 int 488 smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid) 489 { 490 smb_ofile_t *of; 491 492 ASSERT(tree); 493 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 494 495 /* 496 * Note that ORPHANED ofiles aren't fclosable, as they have 497 * no session, user, or tree by which they might be found. 498 * They will eventually expire. 499 */ 500 if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL) 501 return (ENOENT); 502 503 if (smb_ofile_disallow_fclose(of)) { 504 smb_ofile_release(of); 505 return (EACCES); 506 } 507 508 smb_ofile_close(of, 0); 509 smb_ofile_release(of); 510 return (0); 511 } 512 513 /* *************************** Static Functions ***************************** */ 514 515 #define SHARES_DIR ".zfs/shares/" 516 517 /* 518 * Calculates permissions given by the share's ACL to the 519 * user in the passed request. The default is full access. 520 * If any error occurs, full access is granted. 521 * 522 * Using the vnode of the share path find the root directory 523 * of the mounted file system. Then look to see if there is a 524 * .zfs/shares directory and if there is, lookup the file with 525 * the same name as the share name in it. The ACL set for this 526 * file is the share's ACL which is used for access check here. 527 */ 528 static uint32_t 529 smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp) 530 { 531 smb_user_t *user; 532 cred_t *cred; 533 int rc; 534 vfs_t *vfsp; 535 vnode_t *root = NULL; 536 vnode_t *sharevp = NULL; 537 char *sharepath; 538 struct pathname pnp; 539 size_t size; 540 uint32_t access; 541 542 user = sr->uid_user; 543 cred = user->u_cred; 544 access = ACE_ALL_PERMS; 545 546 if (si->shr_flags & SMB_SHRF_AUTOHOME) { 547 /* 548 * An autohome share owner gets full access to the share. 549 * Everyone else is denied access. 550 */ 551 if (si->shr_uid != crgetuid(cred)) 552 access = 0; 553 554 return (access); 555 } 556 557 /* 558 * The hold on 'root' is released by the lookuppnvp() that follows 559 */ 560 vfsp = pathvp->v_vfsp; 561 if (vfsp != NULL) 562 rc = VFS_ROOT(vfsp, &root); 563 else 564 rc = ENOENT; 565 566 if (rc != 0) 567 return (access); 568 569 570 size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1; 571 sharepath = smb_srm_alloc(sr, size); 572 (void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name); 573 574 pn_alloc(&pnp); 575 (void) pn_set(&pnp, sharepath); 576 rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, &sharevp, rootdir, root, 577 zone_kcred()); 578 pn_free(&pnp); 579 580 /* 581 * Now get the effective access value based on cred and ACL values. 582 */ 583 if (rc == 0) { 584 smb_vop_eaccess(sharevp, (int *)&access, V_ACE_MASK, NULL, 585 cred); 586 VN_RELE(sharevp); 587 } 588 589 return (access); 590 } 591 592 /* 593 * Performs the following access checks for a disk share: 594 * 595 * - No IPC/anonymous user is allowed 596 * 597 * - If user is Guest, guestok property of the share should be 598 * enabled 599 * 600 * - If this is an Admin share, the user should have administrative 601 * privileges 602 * 603 * - Host based access control lists 604 * 605 * - Share ACL 606 * 607 * Returns the access allowed or 0 if access is denied. 608 */ 609 static uint32_t 610 smb_tree_chkaccess(smb_request_t *sr, smb_kshare_t *shr, vnode_t *vp) 611 { 612 smb_user_t *user = sr->uid_user; 613 char *sharename = shr->shr_name; 614 uint32_t host_access; 615 uint32_t acl_access; 616 uint32_t access; 617 618 if (user->u_flags & SMB_USER_FLAG_ANON) { 619 smb_tree_log(sr, sharename, "access denied: IPC only"); 620 return (0); 621 } 622 623 if ((user->u_flags & SMB_USER_FLAG_GUEST) && 624 ((shr->shr_flags & SMB_SHRF_GUEST_OK) == 0)) { 625 smb_tree_log(sr, sharename, "access denied: guest disabled"); 626 return (0); 627 } 628 629 if ((shr->shr_flags & SMB_SHRF_ADMIN) && !smb_user_is_admin(user)) { 630 smb_tree_log(sr, sharename, "access denied: not admin"); 631 return (0); 632 } 633 634 host_access = smb_kshare_hostaccess(shr, sr->session); 635 if ((host_access & ACE_ALL_PERMS) == 0) { 636 smb_tree_log(sr, sharename, "access denied: host access"); 637 return (0); 638 } 639 640 acl_access = smb_tree_acl_access(sr, shr, vp); 641 if ((acl_access & ACE_ALL_PERMS) == 0) { 642 smb_tree_log(sr, sharename, "access denied: share ACL"); 643 return (0); 644 } 645 646 access = host_access & acl_access; 647 if ((access & ACE_ALL_PERMS) == 0) { 648 smb_tree_log(sr, sharename, "access denied"); 649 return (0); 650 } 651 652 return (access); 653 } 654 655 /* How long should tree connect wait for DH import to complete? */ 656 int smb_tcon_import_wait = 20; /* sec. */ 657 658 /* 659 * Connect a share for use with files and directories. 660 */ 661 uint32_t 662 smb_tree_connect_disk(smb_request_t *sr, smb_arg_tcon_t *tcon) 663 { 664 char *sharename = tcon->path; 665 const char *any = "?????"; 666 smb_user_t *user = sr->uid_user; 667 smb_node_t *snode = NULL; 668 smb_kshare_t *si = tcon->si; 669 char *service = tcon->service; 670 smb_tree_t *tree; 671 int rc; 672 uint32_t access; 673 smb_shr_execinfo_t execinfo; 674 clock_t time; 675 676 ASSERT(user); 677 ASSERT(user->u_cred); 678 679 if (service != NULL && 680 strcmp(service, any) != 0 && 681 strcasecmp(service, "A:") != 0) { 682 smb_tree_log(sr, sharename, "invalid service (%s)", service); 683 return (NT_STATUS_BAD_DEVICE_TYPE); 684 } 685 686 /* 687 * Check that the shared directory exists. 688 */ 689 snode = si->shr_root_node; 690 if (snode == NULL) { 691 smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 692 return (NT_STATUS_BAD_NETWORK_NAME); 693 } 694 695 if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) { 696 return (NT_STATUS_ACCESS_DENIED); 697 } 698 699 /* 700 * Wait for DH import of persistent handles to finish. 701 * If we timeout, it's not clear what status to return, 702 * but as the share is not really available yet, let's 703 * return the status for "no such share". 704 */ 705 time = SEC_TO_TICK(smb_tcon_import_wait) + ddi_get_lbolt(); 706 mutex_enter(&si->shr_mutex); 707 while (si->shr_import_busy != NULL) { 708 if (cv_timedwait(&si->shr_cv, &si->shr_mutex, time) < 0) { 709 mutex_exit(&si->shr_mutex); 710 return (NT_STATUS_BAD_NETWORK_NAME); 711 } 712 } 713 mutex_exit(&si->shr_mutex); 714 715 /* 716 * Set up the OptionalSupport for this share. 717 */ 718 tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 719 720 switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 721 case SMB_SHRF_CSC_DISABLED: 722 tcon->optional_support |= SMB_CSC_CACHE_NONE; 723 break; 724 case SMB_SHRF_CSC_AUTO: 725 tcon->optional_support |= SMB_CSC_CACHE_AUTO_REINT; 726 break; 727 case SMB_SHRF_CSC_VDO: 728 tcon->optional_support |= SMB_CSC_CACHE_VDO; 729 break; 730 case SMB_SHRF_CSC_MANUAL: 731 default: 732 /* 733 * Default to SMB_CSC_CACHE_MANUAL_REINT. 734 */ 735 break; 736 } 737 738 /* ABE support */ 739 if (si->shr_flags & SMB_SHRF_ABE) 740 tcon->optional_support |= 741 SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM; 742 743 if (si->shr_flags & SMB_SHRF_DFSROOT) 744 tcon->optional_support |= SMB_SHARE_IS_IN_DFS; 745 746 /* if 'smb' zfs property: shortnames=disabled */ 747 if (!smb_shortnames) 748 sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME; 749 750 tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); 751 752 if (tree == NULL) 753 return (NT_STATUS_INSUFF_SERVER_RESOURCES); 754 755 if (tree->t_execflags & SMB_EXEC_MAP) { 756 smb_tree_set_execinfo(tree, &execinfo, SMB_EXEC_MAP); 757 758 rc = smb_kshare_exec(tree->t_server, &execinfo); 759 760 if ((rc != 0) && (tree->t_execflags & SMB_EXEC_TERM)) { 761 /* 762 * Inline parts of: smb_tree_disconnect() 763 * Not using smb_tree_disconnect() for cleanup 764 * here because: we don't want an exec up-call, 765 * and there can't be any opens as we never 766 * returned this TID to the client. 767 */ 768 mutex_enter(&tree->t_mutex); 769 tree->t_state = SMB_TREE_STATE_DISCONNECTING; 770 mutex_exit(&tree->t_mutex); 771 772 smb_tree_release(tree); 773 return (NT_STATUS_ACCESS_DENIED); 774 } 775 } 776 777 sr->tid_tree = tree; 778 sr->smb_tid = tree->t_tid; 779 780 return (0); 781 } 782 783 /* 784 * Shares have both a share and host based access control. The access 785 * granted will be minimum permissions based on both hostaccess 786 * (permissions allowed by host based access) and aclaccess (from the 787 * share ACL). 788 */ 789 uint32_t 790 smb_tree_connect_printq(smb_request_t *sr, smb_arg_tcon_t *tcon) 791 { 792 char *sharename = tcon->path; 793 const char *any = "?????"; 794 smb_user_t *user = sr->uid_user; 795 smb_node_t *dnode = NULL; 796 smb_node_t *snode = NULL; 797 smb_kshare_t *si = tcon->si; 798 char *service = tcon->service; 799 char last_component[MAXNAMELEN]; 800 smb_tree_t *tree; 801 int rc; 802 uint32_t access; 803 804 ASSERT(user); 805 ASSERT(user->u_cred); 806 807 if (sr->sr_server->sv_cfg.skc_print_enable == 0) { 808 smb_tree_log(sr, sharename, "printing disabled"); 809 return (NT_STATUS_BAD_NETWORK_NAME); 810 } 811 812 if (service != NULL && 813 strcmp(service, any) != 0 && 814 strcasecmp(service, "LPT1:") != 0) { 815 smb_tree_log(sr, sharename, "invalid service (%s)", service); 816 return (NT_STATUS_BAD_DEVICE_TYPE); 817 } 818 819 /* 820 * Check that the shared directory exists. 821 */ 822 rc = smb_pathname_reduce(sr, user->u_cred, si->shr_path, 0, 0, &dnode, 823 last_component); 824 if (rc == 0) { 825 rc = smb_fsop_lookup(sr, user->u_cred, SMB_FOLLOW_LINKS, 826 sr->sr_server->si_root_smb_node, dnode, last_component, 827 &snode); 828 829 smb_node_release(dnode); 830 } 831 832 if (rc) { 833 if (snode) 834 smb_node_release(snode); 835 836 smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 837 return (NT_STATUS_BAD_NETWORK_NAME); 838 } 839 840 if ((access = smb_tree_chkaccess(sr, si, snode->vp)) == 0) { 841 smb_node_release(snode); 842 return (NT_STATUS_ACCESS_DENIED); 843 } 844 845 tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 846 847 tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags); 848 849 smb_node_release(snode); 850 851 if (tree == NULL) 852 return (NT_STATUS_INSUFF_SERVER_RESOURCES); 853 854 sr->tid_tree = tree; 855 sr->smb_tid = tree->t_tid; 856 857 return (0); 858 } 859 860 /* 861 * Connect an IPC share for use with named pipes. 862 */ 863 uint32_t 864 smb_tree_connect_ipc(smb_request_t *sr, smb_arg_tcon_t *tcon) 865 { 866 char *name = tcon->path; 867 const char *any = "?????"; 868 smb_user_t *user = sr->uid_user; 869 smb_tree_t *tree; 870 smb_kshare_t *si = tcon->si; 871 char *service = tcon->service; 872 873 ASSERT(user); 874 875 if (service != NULL && 876 strcmp(service, any) != 0 && 877 strcasecmp(service, "IPC") != 0) { 878 smb_tree_log(sr, name, "invalid service (%s)", service); 879 return (NT_STATUS_BAD_DEVICE_TYPE); 880 } 881 882 if ((user->u_flags & SMB_USER_FLAG_ANON) && 883 sr->sr_cfg->skc_restrict_anon) { 884 smb_tree_log(sr, name, "access denied: restrict anonymous"); 885 return (NT_STATUS_ACCESS_DENIED); 886 } 887 888 tcon->optional_support = SMB_SUPPORT_SEARCH_BITS; 889 890 tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0); 891 if (tree == NULL) 892 return (NT_STATUS_INSUFF_SERVER_RESOURCES); 893 894 sr->tid_tree = tree; 895 sr->smb_tid = tree->t_tid; 896 897 return (0); 898 } 899 900 /* 901 * Allocate a tree. 902 */ 903 smb_tree_t * 904 smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si, 905 smb_node_t *snode, uint32_t access, uint32_t execflags) 906 { 907 smb_session_t *session = sr->session; 908 smb_tree_t *tree; 909 uint32_t stype = si->shr_type; 910 uint16_t tid; 911 912 if (smb_idpool_alloc(&session->s_tid_pool, &tid)) 913 return (NULL); 914 915 tree = kmem_cache_alloc(smb_cache_tree, KM_SLEEP); 916 bzero(tree, sizeof (smb_tree_t)); 917 918 tree->t_session = session; 919 tree->t_server = session->s_server; 920 921 if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { 922 if (smb_tree_getattr(si, snode, tree) != 0) { 923 smb_idpool_free(&session->s_tid_pool, tid); 924 kmem_cache_free(smb_cache_tree, tree); 925 return (NULL); 926 } 927 } 928 929 if (smb_idpool_constructor(&tree->t_fid_pool)) { 930 smb_idpool_free(&session->s_tid_pool, tid); 931 kmem_cache_free(smb_cache_tree, tree); 932 return (NULL); 933 } 934 935 if (smb_idpool_constructor(&tree->t_odid_pool)) { 936 smb_idpool_destructor(&tree->t_fid_pool); 937 smb_idpool_free(&session->s_tid_pool, tid); 938 kmem_cache_free(smb_cache_tree, tree); 939 return (NULL); 940 } 941 942 smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t), 943 offsetof(smb_ofile_t, f_tree_lnd)); 944 945 smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t), 946 offsetof(smb_odir_t, d_lnd)); 947 948 (void) strlcpy(tree->t_sharename, si->shr_name, 949 sizeof (tree->t_sharename)); 950 (void) strlcpy(tree->t_resource, si->shr_path, 951 sizeof (tree->t_resource)); 952 953 mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL); 954 955 tree->t_refcnt = 1; 956 tree->t_tid = tid; 957 tree->t_res_type = stype; 958 tree->t_state = SMB_TREE_STATE_CONNECTED; 959 tree->t_magic = SMB_TREE_MAGIC; 960 tree->t_access = access; 961 tree->t_connect_time = gethrestime_sec(); 962 tree->t_execflags = execflags; 963 964 /* grab a ref for tree->t_owner */ 965 smb_user_hold_internal(sr->uid_user); 966 smb_user_inc_trees(sr->uid_user); 967 tree->t_owner = sr->uid_user; 968 969 /* if FS is readonly, enforce that here */ 970 if (tree->t_flags & SMB_TREE_READONLY) 971 tree->t_access &= ~ACE_ALL_WRITE_PERMS; 972 973 if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) { 974 smb_node_ref(snode); 975 tree->t_snode = snode; 976 tree->t_acltype = smb_fsop_acltype(snode); 977 } 978 979 smb_llist_enter(&session->s_tree_list, RW_WRITER); 980 smb_llist_insert_head(&session->s_tree_list, tree); 981 smb_llist_exit(&session->s_tree_list); 982 atomic_inc_32(&session->s_tree_cnt); 983 smb_server_inc_trees(session->s_server); 984 return (tree); 985 } 986 987 /* 988 * Deallocate a tree. The open file and open directory lists should be 989 * empty. 990 * 991 * Remove the tree from the user's tree list before freeing resources 992 * associated with the tree. 993 */ 994 static void 995 smb_tree_dealloc(void *arg) 996 { 997 smb_session_t *session; 998 smb_tree_t *tree = (smb_tree_t *)arg; 999 1000 SMB_TREE_VALID(tree); 1001 ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); 1002 ASSERT(tree->t_refcnt == 0); 1003 1004 smb_server_dec_trees(tree->t_server); 1005 1006 session = tree->t_session; 1007 smb_llist_enter(&session->s_tree_list, RW_WRITER); 1008 smb_llist_remove(&session->s_tree_list, tree); 1009 smb_idpool_free(&session->s_tid_pool, tree->t_tid); 1010 atomic_dec_32(&session->s_tree_cnt); 1011 smb_llist_exit(&session->s_tree_list); 1012 1013 /* 1014 * This tree is no longer on s_tree_list, however... 1015 * 1016 * This is called via smb_llist_post, which means it may run 1017 * BEFORE smb_tree_release drops t_mutex (if another thread 1018 * flushes the delete queue before we do). Synchronize. 1019 */ 1020 mutex_enter(&tree->t_mutex); 1021 mutex_exit(&tree->t_mutex); 1022 1023 tree->t_magic = (uint32_t)~SMB_TREE_MAGIC; 1024 1025 if (tree->t_snode) 1026 smb_node_release(tree->t_snode); 1027 1028 mutex_destroy(&tree->t_mutex); 1029 smb_llist_destructor(&tree->t_ofile_list); 1030 smb_llist_destructor(&tree->t_odir_list); 1031 smb_idpool_destructor(&tree->t_fid_pool); 1032 smb_idpool_destructor(&tree->t_odid_pool); 1033 1034 SMB_USER_VALID(tree->t_owner); 1035 smb_user_dec_trees(tree->t_owner); 1036 smb_user_release(tree->t_owner); 1037 1038 kmem_cache_free(smb_cache_tree, tree); 1039 } 1040 1041 /* 1042 * Determine whether or not a tree is connected. 1043 * This function must be called with the tree mutex held. 1044 */ 1045 static boolean_t 1046 smb_tree_is_connected_locked(smb_tree_t *tree) 1047 { 1048 switch (tree->t_state) { 1049 case SMB_TREE_STATE_CONNECTED: 1050 return (B_TRUE); 1051 1052 case SMB_TREE_STATE_DISCONNECTING: 1053 case SMB_TREE_STATE_DISCONNECTED: 1054 /* 1055 * The tree exists but is being disconnected or destroyed. 1056 */ 1057 return (B_FALSE); 1058 1059 default: 1060 ASSERT(0); 1061 return (B_FALSE); 1062 } 1063 } 1064 1065 /* 1066 * Return a pointer to the share name within a share resource path. 1067 * 1068 * The share path may be a Uniform Naming Convention (UNC) string 1069 * (\\server\share) or simply the share name. We validate the UNC 1070 * format but we don't look at the server name. 1071 */ 1072 static char * 1073 smb_tree_get_sharename(char *unc_path) 1074 { 1075 char *sharename = unc_path; 1076 1077 if (sharename[0] == '\\') { 1078 /* 1079 * Looks like a UNC path, validate the format. 1080 */ 1081 if (sharename[1] != '\\') 1082 return (NULL); 1083 1084 if ((sharename = strchr(sharename+2, '\\')) == NULL) 1085 return (NULL); 1086 1087 ++sharename; 1088 } else if (strchr(sharename, '\\') != NULL) { 1089 /* 1090 * This should be a share name (no embedded \'s). 1091 */ 1092 return (NULL); 1093 } 1094 1095 return (sharename); 1096 } 1097 1098 /* 1099 * Obtain the tree attributes: volume name, typename and flags. 1100 */ 1101 static int 1102 smb_tree_getattr(const smb_kshare_t *si, smb_node_t *node, smb_tree_t *tree) 1103 { 1104 vfs_t *vfsp = SMB_NODE_VFS(node); 1105 vfs_t *realvfsp; 1106 smb_cfg_val_t srv_encrypt; 1107 1108 ASSERT(vfsp); 1109 1110 smb_tree_get_creation(node, tree); 1111 smb_tree_get_volname(vfsp, tree); 1112 1113 /* 1114 * In the case of an lofs mount, we need to ask the (real) 1115 * underlying filesystem about capabilities, where the 1116 * passed in vfs_t will be from lofs. 1117 */ 1118 realvfsp = getvfs(&vfsp->vfs_fsid); 1119 if (realvfsp != NULL) { 1120 smb_tree_get_flags(si, realvfsp, tree); 1121 VFS_RELE(realvfsp); 1122 } else { 1123 cmn_err(CE_NOTE, "Failed getting info for share: %s", 1124 si->shr_name); 1125 /* do the best we can without realvfsp */ 1126 smb_tree_get_flags(si, vfsp, tree); 1127 } 1128 1129 srv_encrypt = tree->t_session->s_server->sv_cfg.skc_encrypt; 1130 if (tree->t_session->dialect >= SMB_VERS_3_0) { 1131 if (si->shr_encrypt == SMB_CONFIG_REQUIRED || 1132 srv_encrypt == SMB_CONFIG_REQUIRED) 1133 tree->t_encrypt = SMB_CONFIG_REQUIRED; 1134 else if (si->shr_encrypt == SMB_CONFIG_ENABLED || 1135 srv_encrypt == SMB_CONFIG_ENABLED) 1136 tree->t_encrypt = SMB_CONFIG_ENABLED; 1137 else 1138 tree->t_encrypt = SMB_CONFIG_DISABLED; 1139 } else 1140 tree->t_encrypt = SMB_CONFIG_DISABLED; 1141 1142 return (0); 1143 } 1144 1145 /* 1146 * File volume creation time 1147 */ 1148 static void 1149 smb_tree_get_creation(smb_node_t *node, smb_tree_t *tree) 1150 { 1151 smb_attr_t attr; 1152 cred_t *kcr = zone_kcred(); 1153 1154 bzero(&attr, sizeof (attr)); 1155 attr.sa_mask = SMB_AT_CRTIME; 1156 (void) smb_node_getattr(NULL, node, kcr, NULL, &attr); 1157 /* On failure we'll have time zero, which is OK */ 1158 1159 tree->t_create_time = attr.sa_crtime; 1160 } 1161 1162 /* 1163 * Extract the volume name. 1164 */ 1165 static void 1166 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree) 1167 { 1168 #ifdef _FAKE_KERNEL 1169 _NOTE(ARGUNUSED(vfsp)) 1170 (void) strlcpy(tree->t_volume, "fake", SMB_VOLNAMELEN); 1171 #else /* _FAKE_KERNEL */ 1172 refstr_t *vfs_mntpoint; 1173 const char *s; 1174 char *name; 1175 1176 vfs_mntpoint = vfs_getmntpoint(vfsp); 1177 1178 s = refstr_value(vfs_mntpoint); 1179 s += strspn(s, "/"); 1180 (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN); 1181 1182 refstr_rele(vfs_mntpoint); 1183 1184 name = tree->t_volume; 1185 (void) strsep((char **)&name, "/"); 1186 #endif /* _FAKE_KERNEL */ 1187 } 1188 1189 /* 1190 * Always set "unicode on disk" because we always use utf8 names locally. 1191 * Always set ACL support because the VFS will fake ACLs for file systems 1192 * that don't support them. 1193 * 1194 * Some flags are dependent on the typename, which is also set up here. 1195 * File system types are hardcoded in uts/common/os/vfs_conf.c. 1196 */ 1197 static void 1198 smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree) 1199 { 1200 smb_session_t *ssn = tree->t_session; 1201 struct vfssw *vswp; 1202 1203 typedef struct smb_mtype { 1204 char *mt_name; 1205 size_t mt_namelen; 1206 uint32_t mt_flags; 1207 } smb_mtype_t; 1208 1209 static smb_mtype_t smb_mtype[] = { 1210 #ifdef _FAKE_KERNEL 1211 /* See libfksmbsrv:fake_vfs.c */ 1212 { "fake", 3, SMB_TREE_SPARSE}, 1213 #endif /* _FAKE_KERNEL */ 1214 { "zfs", 3, SMB_TREE_QUOTA | SMB_TREE_SPARSE}, 1215 { "ufs", 3, 0 }, 1216 { "nfs", 3, SMB_TREE_NFS_MOUNTED }, 1217 { "tmpfs", 5, SMB_TREE_NO_EXPORT } 1218 }; 1219 smb_mtype_t *mtype; 1220 char *name; 1221 uint32_t flags = 1222 SMB_TREE_SUPPORTS_ACLS | 1223 SMB_TREE_UNICODE_ON_DISK; 1224 int i; 1225 1226 if (si->shr_flags & SMB_SHRF_DFSROOT) 1227 flags |= SMB_TREE_DFSROOT; 1228 1229 if (si->shr_flags & SMB_SHRF_CATIA) 1230 flags |= SMB_TREE_CATIA; 1231 1232 if (si->shr_flags & SMB_SHRF_ABE) 1233 flags |= SMB_TREE_ABE; 1234 1235 if (si->shr_flags & SMB_SHRF_CA) 1236 flags |= SMB_TREE_CA; 1237 1238 if (si->shr_flags & SMB_SHRF_FSO) 1239 flags |= SMB_TREE_FORCE_L2_OPLOCK; 1240 1241 if (ssn->s_cfg.skc_oplock_enable) { 1242 /* if 'smb' zfs property: oplocks=enabled */ 1243 flags |= SMB_TREE_OPLOCKS; 1244 } 1245 1246 /* Global config option for now. Later make per-share. */ 1247 if (ssn->s_cfg.skc_traverse_mounts) 1248 flags |= SMB_TREE_TRAVERSE_MOUNTS; 1249 1250 /* if 'smb' zfs property: shortnames=enabled */ 1251 if (smb_shortnames) 1252 flags |= SMB_TREE_SHORTNAMES; 1253 1254 if (vfsp->vfs_flag & VFS_RDONLY) 1255 flags |= SMB_TREE_READONLY; 1256 1257 if (vfsp->vfs_flag & VFS_XATTR) 1258 flags |= SMB_TREE_STREAMS; 1259 1260 vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp)); 1261 if (vswp != NULL) { 1262 name = vswp->vsw_name; 1263 vfs_unrefvfssw(vswp); 1264 } else { 1265 name = "?"; 1266 } 1267 1268 for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) { 1269 mtype = &smb_mtype[i]; 1270 if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0) 1271 flags |= mtype->mt_flags; 1272 } 1273 1274 /* 1275 * SMB_TREE_QUOTA will be on here if the FS is ZFS. We want to 1276 * turn it OFF when the share property says false. 1277 */ 1278 if ((si->shr_flags & SMB_SHRF_QUOTAS) == 0) 1279 flags &= ~SMB_TREE_QUOTA; 1280 1281 (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN); 1282 (void) smb_strupr((char *)tree->t_typename); 1283 1284 if (vfs_has_feature(vfsp, VFSFT_XVATTR)) 1285 flags |= SMB_TREE_XVATTR; 1286 1287 if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE)) 1288 flags |= SMB_TREE_CASEINSENSITIVE; 1289 1290 if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE)) 1291 flags |= SMB_TREE_NO_CASESENSITIVE; 1292 1293 if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS)) 1294 flags |= SMB_TREE_DIRENTFLAGS; 1295 1296 if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE)) 1297 flags |= SMB_TREE_ACLONCREATE; 1298 1299 if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS)) 1300 flags |= SMB_TREE_ACEMASKONACCESS; 1301 1302 DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name); 1303 1304 1305 tree->t_flags = flags; 1306 } 1307 1308 /* 1309 * Report share access result to syslog. 1310 */ 1311 static void 1312 smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...) 1313 { 1314 va_list ap; 1315 char buf[128]; 1316 smb_user_t *user = sr->uid_user; 1317 1318 ASSERT(user); 1319 1320 if (smb_tcon_mute) 1321 return; 1322 1323 if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) { 1324 /* 1325 * Only report normal users, i.e. ignore W2K misuse 1326 * of the IPC connection by filtering out internal 1327 * names such as nobody and root. 1328 */ 1329 if ((strcmp(user->u_name, "root") == 0) || 1330 (strcmp(user->u_name, "nobody") == 0)) { 1331 return; 1332 } 1333 } 1334 1335 va_start(ap, fmt); 1336 (void) vsnprintf(buf, 128, fmt, ap); 1337 va_end(ap); 1338 1339 cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s", 1340 user->u_domain, user->u_name, sharename, buf); 1341 } 1342 1343 /* 1344 * smb_tree_lookup_odir 1345 * 1346 * Find the specified odir in the tree's list of odirs, and 1347 * attempt to obtain a hold on the odir. 1348 * 1349 * Returns NULL if odir not found or a hold cannot be obtained. 1350 */ 1351 smb_odir_t * 1352 smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid) 1353 { 1354 smb_odir_t *od; 1355 smb_llist_t *od_list; 1356 smb_tree_t *tree = sr->tid_tree; 1357 1358 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1359 1360 od_list = &tree->t_odir_list; 1361 1362 smb_llist_enter(od_list, RW_READER); 1363 od = smb_llist_head(od_list); 1364 while (od) { 1365 if (od->d_odid == odid) 1366 break; 1367 od = smb_llist_next(od_list, od); 1368 } 1369 if (od == NULL) 1370 goto out; 1371 1372 /* 1373 * Only allow use of a given Search ID with the same UID that 1374 * was used to create it. MS-CIFS 3.3.5.14 1375 */ 1376 if (od->d_user != sr->uid_user) { 1377 od = NULL; 1378 goto out; 1379 } 1380 if (!smb_odir_hold(od)) 1381 od = NULL; 1382 1383 out: 1384 smb_llist_exit(od_list); 1385 return (od); 1386 } 1387 1388 boolean_t 1389 smb_tree_is_connected(smb_tree_t *tree) 1390 { 1391 boolean_t rb; 1392 1393 mutex_enter(&tree->t_mutex); 1394 rb = smb_tree_is_connected_locked(tree); 1395 mutex_exit(&tree->t_mutex); 1396 return (rb); 1397 } 1398 1399 /* 1400 * smb_tree_close_odirs 1401 * 1402 * Close all open odirs in the tree's list which were opened by 1403 * the process identified by pid. 1404 * If pid is zero, close all open odirs in the tree's list. 1405 */ 1406 static void 1407 smb_tree_close_odirs(smb_tree_t *tree, uint32_t pid) 1408 { 1409 smb_llist_t *od_list; 1410 smb_odir_t *od; 1411 1412 ASSERT(tree); 1413 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1414 1415 od_list = &tree->t_odir_list; 1416 smb_llist_enter(od_list, RW_READER); 1417 1418 for (od = smb_llist_head(od_list); 1419 od != NULL; 1420 od = smb_llist_next(od_list, od)) { 1421 1422 ASSERT(od->d_magic == SMB_ODIR_MAGIC); 1423 ASSERT(od->d_tree == tree); 1424 1425 if (pid != 0 && od->d_opened_by_pid != pid) 1426 continue; 1427 1428 if (smb_odir_hold(od)) { 1429 smb_odir_close(od); 1430 smb_odir_release(od); 1431 } 1432 } 1433 1434 smb_llist_exit(od_list); 1435 } 1436 1437 static void 1438 smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec, 1439 int exec_type) 1440 { 1441 exec->e_sharename = tree->t_sharename; 1442 exec->e_winname = tree->t_owner->u_name; 1443 exec->e_userdom = tree->t_owner->u_domain; 1444 exec->e_srv_ipaddr = tree->t_session->local_ipaddr; 1445 exec->e_cli_ipaddr = tree->t_session->ipaddr; 1446 exec->e_cli_netbiosname = tree->t_session->workstation; 1447 exec->e_uid = crgetuid(tree->t_owner->u_cred); 1448 exec->e_type = exec_type; 1449 } 1450 1451 /* 1452 * Private function to support smb_tree_enum. 1453 */ 1454 static int 1455 smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum) 1456 { 1457 uint8_t *pb; 1458 uint_t nbytes; 1459 int rc; 1460 1461 if (svcenum->se_nskip > 0) { 1462 svcenum->se_nskip--; 1463 return (0); 1464 } 1465 1466 if (svcenum->se_nitems >= svcenum->se_nlimit) { 1467 svcenum->se_nitems = svcenum->se_nlimit; 1468 return (0); 1469 } 1470 1471 pb = &svcenum->se_buf[svcenum->se_bused]; 1472 rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes); 1473 if (rc == 0) { 1474 svcenum->se_bavail -= nbytes; 1475 svcenum->se_bused += nbytes; 1476 svcenum->se_nitems++; 1477 } 1478 1479 return (rc); 1480 } 1481 1482 /* 1483 * Encode connection information into a buffer: connection information 1484 * needed in user space to support RPC requests. 1485 */ 1486 static int 1487 smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen, 1488 uint32_t *nbytes) 1489 { 1490 smb_netconnectinfo_t info; 1491 int rc; 1492 1493 smb_tree_netinfo_init(tree, &info); 1494 rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes); 1495 smb_tree_netinfo_fini(&info); 1496 1497 return (rc); 1498 } 1499 1500 static void 1501 smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen) 1502 { 1503 smb_user_t *user = tree->t_owner; 1504 1505 /* 1506 * u_domain_len and u_name_len include the '\0' in their 1507 * lengths, hence the sum of the two lengths gives us room 1508 * for both the '\\' and '\0' chars. 1509 */ 1510 ASSERT(namestr); 1511 ASSERT(namelen); 1512 ASSERT(user->u_domain_len > 0); 1513 ASSERT(user->u_name_len > 0); 1514 *namelen = user->u_domain_len + user->u_name_len; 1515 *namestr = kmem_alloc(*namelen, KM_SLEEP); 1516 (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain, 1517 user->u_name); 1518 } 1519 1520 /* 1521 * Note: ci_numusers should be the number of users connected to 1522 * the share rather than the number of references on the tree but 1523 * we don't have a mechanism to track users/share in smbsrv yet. 1524 */ 1525 static void 1526 smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info) 1527 { 1528 ASSERT(tree); 1529 1530 info->ci_id = tree->t_tid; 1531 info->ci_type = tree->t_res_type; 1532 info->ci_numopens = tree->t_open_files; 1533 info->ci_numusers = tree->t_refcnt; 1534 info->ci_time = gethrestime_sec() - tree->t_connect_time; 1535 1536 info->ci_sharelen = strlen(tree->t_sharename) + 1; 1537 info->ci_share = smb_mem_strdup(tree->t_sharename); 1538 1539 smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen); 1540 } 1541 1542 static void 1543 smb_tree_netinfo_fini(smb_netconnectinfo_t *info) 1544 { 1545 if (info == NULL) 1546 return; 1547 1548 if (info->ci_username) 1549 kmem_free(info->ci_username, info->ci_namelen); 1550 if (info->ci_share) 1551 smb_mem_free(info->ci_share); 1552 1553 bzero(info, sizeof (smb_netconnectinfo_t)); 1554 } 1555