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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * General Structures Layout 28 * ------------------------- 29 * 30 * This is a simplified diagram showing the relationship between most of the 31 * main structures. 32 * 33 * +-------------------+ 34 * | SMB_INFO | 35 * +-------------------+ 36 * | 37 * | 38 * v 39 * +-------------------+ +-------------------+ +-------------------+ 40 * | SESSION |<----->| SESSION |......| SESSION | 41 * +-------------------+ +-------------------+ +-------------------+ 42 * | 43 * | 44 * v 45 * +-------------------+ +-------------------+ +-------------------+ 46 * | USER |<----->| USER |......| USER | 47 * +-------------------+ +-------------------+ +-------------------+ 48 * | 49 * | 50 * v 51 * +-------------------+ +-------------------+ +-------------------+ 52 * | TREE |<----->| TREE |......| TREE | 53 * +-------------------+ +-------------------+ +-------------------+ 54 * | | 55 * | | 56 * | v 57 * | +-------+ +-------+ +-------+ 58 * | | OFILE |<----->| OFILE |......| OFILE | 59 * | +-------+ +-------+ +-------+ 60 * | 61 * | 62 * v 63 * +-------+ +------+ +------+ 64 * | ODIR |<----->| ODIR |......| ODIR | 65 * +-------+ +------+ +------+ 66 * 67 * 68 * Tree State Machine 69 * ------------------ 70 * 71 * +-----------------------------+ T0 72 * | SMB_TREE_STATE_CONNECTED |<----------- Creation/Allocation 73 * +-----------------------------+ 74 * | 75 * | T1 76 * | 77 * v 78 * +------------------------------+ 79 * | SMB_TREE_STATE_DISCONNECTING | 80 * +------------------------------+ 81 * | 82 * | T2 83 * | 84 * v 85 * +-----------------------------+ T3 86 * | SMB_TREE_STATE_DISCONNECTED |----------> Deletion/Free 87 * +-----------------------------+ 88 * 89 * SMB_TREE_STATE_CONNECTED 90 * 91 * While in this state: 92 * - The tree is queued in the list of trees of its user. 93 * - References will be given out if the tree is looked up. 94 * - Files under that tree can be accessed. 95 * 96 * SMB_TREE_STATE_DISCONNECTING 97 * 98 * While in this state: 99 * - The tree is queued in the list of trees of its user. 100 * - References will not be given out if the tree is looked up. 101 * - The files and directories open under the tree are being closed. 102 * - The resources associated with the tree remain. 103 * 104 * SMB_TREE_STATE_DISCONNECTED 105 * 106 * While in this state: 107 * - The tree is queued in the list of trees of its user. 108 * - References will not be given out if the tree is looked up. 109 * - The tree has no more files and directories opened. 110 * - The resources associated with the tree remain. 111 * 112 * Transition T0 113 * 114 * This transition occurs in smb_tree_connect(). A new tree is created and 115 * added to the list of trees of a user. 116 * 117 * Transition T1 118 * 119 * This transition occurs in smb_tree_disconnect(). 120 * 121 * Transition T2 122 * 123 * This transition occurs in smb_tree_release(). The resources associated 124 * with the tree are freed as well as the tree structure. For the transition 125 * to occur, the tree must be in the SMB_TREE_STATE_DISCONNECTED state and 126 * the reference count be zero. 127 * 128 * Comments 129 * -------- 130 * 131 * The state machine of the tree structures is controlled by 3 elements: 132 * - The list of trees of the user it belongs to. 133 * - The mutex embedded in the structure itself. 134 * - The reference count. 135 * 136 * There's a mutex embedded in the tree structure used to protect its fields 137 * and there's a lock embedded in the list of trees of a user. To 138 * increment or to decrement the reference count the mutex must be entered. 139 * To insert the tree into the list of trees of the user and to remove 140 * the tree from it, the lock must be entered in RW_WRITER mode. 141 * 142 * Rules of access to a tree structure: 143 * 144 * 1) In order to avoid deadlocks, when both (mutex and lock of the user 145 * list) have to be entered, the lock must be entered first. 146 * 147 * 2) All actions applied to a tree require a reference count. 148 * 149 * 3) There are 2 ways of getting a reference count: when a tree is 150 * connected and when a tree is looked up. 151 * 152 * It should be noted that the reference count of a tree registers the 153 * number of references to the tree in other structures (such as an smb 154 * request). The reference count is not incremented in these 2 instances: 155 * 156 * 1) The tree is connected. An tree is anchored by his state. If there's 157 * no activity involving a tree currently connected, the reference 158 * count of that tree is zero. 159 * 160 * 2) The tree is queued in the list of trees of the user. The fact of 161 * being queued in that list is NOT registered by incrementing the 162 * reference count. 163 */ 164 #include <sys/types.h> 165 #include <sys/refstr_impl.h> 166 #include <sys/feature_tests.h> 167 #include <sys/sunddi.h> 168 #include <sys/fsid.h> 169 #include <sys/vfs.h> 170 #include <sys/stat.h> 171 #include <sys/varargs.h> 172 #include <sys/cred.h> 173 #include <smbsrv/smb_kproto.h> 174 #include <smbsrv/lmerr.h> 175 #include <smbsrv/smb_fsops.h> 176 #include <smbsrv/smb_door_svc.h> 177 #include <smbsrv/smb_share.h> 178 #include <sys/pathname.h> 179 180 int smb_tcon_mute = 0; 181 182 static smb_tree_t *smb_tree_connect_disk(smb_request_t *, const char *); 183 static smb_tree_t *smb_tree_connect_ipc(smb_request_t *, const char *); 184 static smb_tree_t *smb_tree_alloc(smb_user_t *, const smb_share_t *, 185 int32_t, smb_node_t *, uint32_t); 186 static void smb_tree_dealloc(smb_tree_t *); 187 static boolean_t smb_tree_is_connected_locked(smb_tree_t *); 188 static boolean_t smb_tree_is_disconnected(smb_tree_t *); 189 static const char *smb_tree_get_sharename(const char *); 190 static int smb_tree_get_stype(const char *, const char *, int32_t *); 191 static int smb_tree_getattr(const smb_share_t *, 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_share_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 *, uint16_t); 196 static smb_ofile_t *smb_tree_get_ofile(smb_tree_t *, smb_ofile_t *); 197 static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *); 198 static void smb_tree_set_execsub_info(smb_tree_t *, smb_execsub_info_t *); 199 static int smb_tree_enum_private(smb_tree_t *, smb_svcenum_t *); 200 static int smb_tree_netinfo_encode(smb_tree_t *, uint8_t *, size_t, uint32_t *); 201 static void smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *); 202 static void smb_tree_netinfo_fini(smb_netconnectinfo_t *); 203 204 /* 205 * Extract the share name and share type and connect as appropriate. 206 * Share names are case insensitive so we map the share name to 207 * lower-case as a convenience for internal processing. 208 */ 209 smb_tree_t * 210 smb_tree_connect(smb_request_t *sr) 211 { 212 char *unc_path = sr->arg.tcon.path; 213 char *service = sr->arg.tcon.service; 214 smb_tree_t *tree = NULL; 215 const char *name; 216 int32_t stype; 217 218 (void) smb_strlwr(unc_path); 219 220 if ((name = smb_tree_get_sharename(unc_path)) == NULL) { 221 smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 222 return (NULL); 223 } 224 225 if (smb_tree_get_stype(name, service, &stype) != 0) { 226 smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 227 ERRDOS, ERROR_BAD_DEV_TYPE); 228 return (NULL); 229 } 230 231 switch (stype & STYPE_MASK) { 232 case STYPE_DISKTREE: 233 tree = smb_tree_connect_disk(sr, name); 234 break; 235 236 case STYPE_IPC: 237 tree = smb_tree_connect_ipc(sr, name); 238 break; 239 240 default: 241 smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, 242 ERRDOS, ERROR_BAD_DEV_TYPE); 243 break; 244 } 245 246 return (tree); 247 } 248 249 /* 250 * Disconnect a tree. 251 */ 252 void 253 smb_tree_disconnect(smb_tree_t *tree, boolean_t do_exec) 254 { 255 smb_execsub_info_t subs; 256 257 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 258 259 mutex_enter(&tree->t_mutex); 260 ASSERT(tree->t_refcnt); 261 262 if (smb_tree_is_connected_locked(tree)) { 263 /* 264 * Indicate that the disconnect process has started. 265 */ 266 tree->t_state = SMB_TREE_STATE_DISCONNECTING; 267 mutex_exit(&tree->t_mutex); 268 atomic_dec_32(&tree->t_server->sv_open_trees); 269 270 if (do_exec) { 271 /* 272 * The files opened under this tree are closed. 273 */ 274 smb_ofile_close_all(tree); 275 /* 276 * The directories opened under this tree are closed. 277 */ 278 smb_tree_close_odirs(tree, 0); 279 } 280 281 mutex_enter(&tree->t_mutex); 282 tree->t_state = SMB_TREE_STATE_DISCONNECTED; 283 } 284 285 mutex_exit(&tree->t_mutex); 286 287 if (do_exec && tree->t_state == SMB_TREE_STATE_DISCONNECTED && 288 tree->t_shr_flags & SMB_SHRF_UNMAP) { 289 290 (void) smb_tree_set_execsub_info(tree, &subs); 291 292 (void) smb_kshare_exec(tree->t_server->sv_lmshrd, 293 (char *)tree->t_sharename, &subs, SMB_SHR_UNMAP); 294 } 295 } 296 297 /* 298 * Take a reference on a tree. 299 */ 300 boolean_t 301 smb_tree_hold( 302 smb_tree_t *tree) 303 { 304 ASSERT(tree); 305 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 306 307 mutex_enter(&tree->t_mutex); 308 309 if (smb_tree_is_connected_locked(tree)) { 310 tree->t_refcnt++; 311 mutex_exit(&tree->t_mutex); 312 return (B_TRUE); 313 } 314 315 mutex_exit(&tree->t_mutex); 316 return (B_FALSE); 317 } 318 319 /* 320 * Release a reference on a tree. If the tree is disconnected and the 321 * reference count falls to zero, the tree will be deallocated. 322 */ 323 void 324 smb_tree_release( 325 smb_tree_t *tree) 326 { 327 ASSERT(tree); 328 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 329 330 mutex_enter(&tree->t_mutex); 331 ASSERT(tree->t_refcnt); 332 tree->t_refcnt--; 333 334 if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0)) { 335 mutex_exit(&tree->t_mutex); 336 smb_tree_dealloc(tree); 337 return; 338 } 339 340 mutex_exit(&tree->t_mutex); 341 } 342 343 /* 344 * Close ofiles and odirs that match pid. 345 */ 346 void 347 smb_tree_close_pid( 348 smb_tree_t *tree, 349 uint16_t pid) 350 { 351 ASSERT(tree); 352 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 353 354 smb_ofile_close_all_by_pid(tree, pid); 355 smb_tree_close_odirs(tree, pid); 356 } 357 358 /* 359 * Check whether or not a tree supports the features identified by flags. 360 */ 361 boolean_t 362 smb_tree_has_feature(smb_tree_t *tree, uint32_t flags) 363 { 364 ASSERT(tree); 365 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 366 367 return ((tree->t_flags & flags) == flags); 368 } 369 370 /* 371 * If the enumeration request is for tree data, handle the request 372 * here. Otherwise, pass it on to the ofiles. 373 * 374 * This function should be called with a hold on the tree. 375 */ 376 int 377 smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum) 378 { 379 smb_ofile_t *of; 380 smb_ofile_t *next; 381 int rc; 382 383 ASSERT(tree); 384 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 385 386 if (svcenum->se_type == SMB_SVCENUM_TYPE_TREE) 387 return (smb_tree_enum_private(tree, svcenum)); 388 389 of = smb_tree_get_ofile(tree, NULL); 390 while (of) { 391 ASSERT(of->f_tree == tree); 392 393 rc = smb_ofile_enum(of, svcenum); 394 if (rc != 0) { 395 smb_ofile_release(of); 396 break; 397 } 398 399 next = smb_tree_get_ofile(tree, of); 400 smb_ofile_release(of); 401 of = next; 402 } 403 404 return (rc); 405 } 406 407 /* 408 * Close a file by its unique id. 409 */ 410 int 411 smb_tree_fclose(smb_tree_t *tree, uint32_t uniqid) 412 { 413 smb_ofile_t *of; 414 415 ASSERT(tree); 416 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 417 418 if ((of = smb_ofile_lookup_by_uniqid(tree, uniqid)) == NULL) 419 return (ENOENT); 420 421 if (smb_ofile_disallow_fclose(of)) { 422 smb_ofile_release(of); 423 return (EACCES); 424 } 425 426 smb_ofile_close(of, 0); 427 smb_ofile_release(of); 428 return (0); 429 } 430 431 /* *************************** Static Functions ***************************** */ 432 433 #define SHARES_DIR ".zfs/shares/" 434 static void 435 smb_tree_acl_access(cred_t *cred, const char *sharename, vnode_t *pathvp, 436 uint32_t *access) 437 { 438 int rc; 439 vfs_t *vfsp; 440 vnode_t *root = NULL; 441 vnode_t *sharevp = NULL; 442 char *sharepath; 443 struct pathname pnp; 444 size_t size; 445 446 *access = ACE_ALL_PERMS; /* default to full "UNIX" access */ 447 448 /* 449 * Using the vnode of the share path, we then find the root 450 * directory of the mounted file system. We will then look to 451 * see if there is a .zfs/shares directory and if there is, 452 * get the access information from the ACL/ACES values and 453 * check against the cred. 454 */ 455 vfsp = pathvp->v_vfsp; 456 if (vfsp != NULL) 457 rc = VFS_ROOT(vfsp, &root); 458 else 459 rc = ENOENT; 460 461 if (rc != 0) 462 return; 463 464 465 /* 466 * Find the share object, if there is one. Need to construct 467 * the path to the .zfs/shares/<sharename> object and look it 468 * up. root is called held but will be released by 469 * lookuppnvp(). 470 */ 471 472 size = sizeof (SHARES_DIR) + strlen(sharename) + 1; 473 sharepath = kmem_alloc(size, KM_SLEEP); 474 (void) sprintf(sharepath, "%s%s", SHARES_DIR, sharename); 475 476 pn_alloc(&pnp); 477 (void) pn_set(&pnp, sharepath); 478 rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, 479 &sharevp, rootdir, root, kcred); 480 pn_free(&pnp); 481 482 kmem_free(sharepath, size); 483 484 /* 485 * Now get the effective access value based on cred and ACL 486 * values. 487 */ 488 489 if (rc == 0) { 490 smb_vop_eaccess(sharevp, (int *)access, V_ACE_MASK, NULL, cred); 491 VN_RELE(sharevp); 492 } 493 } 494 495 /* 496 * Connect a share for use with files and directories. 497 */ 498 499 static smb_tree_t * 500 smb_tree_connect_disk(smb_request_t *sr, const char *sharename) 501 { 502 smb_user_t *user = sr->uid_user; 503 smb_node_t *dnode = NULL; 504 smb_node_t *snode = NULL; 505 char last_component[MAXNAMELEN]; 506 smb_tree_t *tree; 507 smb_share_t *si; 508 cred_t *u_cred; 509 int rc; 510 uint32_t access = 0; /* read/write is assumed */ 511 uint32_t hostaccess = ACE_ALL_PERMS; 512 uint32_t aclaccess; 513 smb_execsub_info_t subs; 514 515 ASSERT(user); 516 u_cred = user->u_cred; 517 ASSERT(u_cred); 518 519 if (user->u_flags & SMB_USER_FLAG_IPC) { 520 smb_tree_log(sr, sharename, "access denied: IPC only"); 521 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 522 return (NULL); 523 } 524 525 si = kmem_zalloc(sizeof (smb_share_t), KM_SLEEP); 526 527 if (smb_kshare_getinfo(sr->sr_server->sv_lmshrd, (char *)sharename, si, 528 &sr->session->ipaddr) != NERR_Success) { 529 smb_tree_log(sr, sharename, "share not found"); 530 smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 531 kmem_free(si, sizeof (smb_share_t)); 532 return (NULL); 533 } 534 535 if (user->u_flags & SMB_USER_FLAG_GUEST) { 536 if ((si->shr_flags & SMB_SHRF_GUEST_OK) == 0) { 537 smb_tree_log(sr, sharename, 538 "access denied: guest disabled"); 539 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, 540 ERRaccess); 541 kmem_free(si, sizeof (smb_share_t)); 542 return (NULL); 543 } 544 } 545 546 /* 547 * Handle the default administration shares: C$, D$ etc. 548 * Only a user with admin rights is allowed to map these 549 * shares. 550 */ 551 if (si->shr_flags & SMB_SHRF_ADMIN) { 552 if (!smb_user_is_admin(user)) { 553 smb_tree_log(sr, sharename, "access denied: not admin"); 554 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 555 ERRSRV, ERRaccess); 556 kmem_free(si, sizeof (smb_share_t)); 557 return (NULL); 558 } 559 } 560 561 /* 562 * Set up the OptionalSupport for this share. 563 */ 564 sr->arg.tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; 565 566 switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 567 case SMB_SHRF_CSC_DISABLED: 568 sr->arg.tcon.optional_support |= SMB_CSC_CACHE_NONE; 569 break; 570 case SMB_SHRF_CSC_AUTO: 571 sr->arg.tcon.optional_support |= SMB_CSC_CACHE_AUTO_REINT; 572 break; 573 case SMB_SHRF_CSC_VDO: 574 sr->arg.tcon.optional_support |= SMB_CSC_CACHE_VDO; 575 break; 576 case SMB_SHRF_CSC_MANUAL: 577 default: 578 /* 579 * Default to SMB_CSC_CACHE_MANUAL_REINT. 580 */ 581 break; 582 } 583 584 /* ABE support */ 585 if (si->shr_flags & SMB_SHRF_ABE) 586 sr->arg.tcon.optional_support |= 587 SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM; 588 589 access = si->shr_access_value & SMB_SHRF_ACC_ALL; 590 591 if (access == SMB_SHRF_ACC_RO) { 592 hostaccess &= ~ACE_ALL_WRITE_PERMS; 593 } else if (access == SMB_SHRF_ACC_NONE) { 594 kmem_free(si, sizeof (smb_share_t)); 595 smb_tree_log(sr, sharename, "access denied: host access"); 596 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 597 return (NULL); 598 } 599 600 /* 601 * Check that the shared directory exists. 602 */ 603 rc = smb_pathname_reduce(sr, u_cred, si->shr_path, 0, 0, &dnode, 604 last_component); 605 606 if (rc == 0) { 607 rc = smb_fsop_lookup(sr, u_cred, SMB_FOLLOW_LINKS, 608 sr->sr_server->si_root_smb_node, dnode, last_component, 609 &snode); 610 611 smb_node_release(dnode); 612 } 613 614 if (rc) { 615 if (snode) 616 smb_node_release(snode); 617 618 smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 619 smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 620 kmem_free(si, sizeof (smb_share_t)); 621 return (NULL); 622 } 623 624 /* 625 * Find share level ACL if it exists in the designated 626 * location. Needs to be done after finding a valid path but 627 * before the tree is allocated. 628 */ 629 smb_tree_acl_access(u_cred, sharename, snode->vp, &aclaccess); 630 if ((aclaccess & ACE_ALL_PERMS) == 0) { 631 smb_tree_log(sr, sharename, "access denied: share ACL"); 632 smbsr_error(sr, 0, ERRSRV, ERRaccess); 633 kmem_free(si, sizeof (smb_share_t)); 634 smb_node_release(snode); 635 return (NULL); 636 } 637 638 /* 639 * Set tree ACL access to the minimum ACL permissions based on 640 * hostaccess (those allowed by host based access) and 641 * aclaccess (those from the ACL object for the share). This 642 * is done during the alloc. 643 */ 644 645 (void) strlcpy(si->shr_name, sharename, MAXNAMELEN); 646 tree = smb_tree_alloc(user, si, STYPE_DISKTREE, snode, 647 hostaccess & aclaccess); 648 649 smb_node_release(snode); 650 651 if (tree == NULL) 652 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 653 else { 654 655 tree->t_shr_flags = si->shr_flags; 656 657 if (tree->t_shr_flags & SMB_SHRF_MAP) { 658 (void) smb_tree_set_execsub_info(tree, &subs); 659 660 rc = smb_kshare_exec(sr->sr_server->sv_lmshrd, 661 (char *)sharename, &subs, SMB_SHR_MAP); 662 663 if (rc != 0 && tree->t_shr_flags & SMB_SHRF_DISP_TERM) { 664 smb_tree_disconnect(tree, B_FALSE); 665 smb_tree_release(tree); 666 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, 667 ERRaccess); 668 kmem_free(si, sizeof (smb_share_t)); 669 return (NULL); 670 } 671 } 672 } 673 674 kmem_free(si, sizeof (smb_share_t)); 675 676 return (tree); 677 } 678 679 /* 680 * Connect an IPC share for use with named pipes. 681 */ 682 static smb_tree_t * 683 smb_tree_connect_ipc(smb_request_t *sr, const char *name) 684 { 685 smb_user_t *user = sr->uid_user; 686 smb_tree_t *tree; 687 smb_share_t *si; 688 689 ASSERT(user); 690 691 if ((user->u_flags & SMB_USER_FLAG_IPC) && 692 sr->sr_cfg->skc_restrict_anon) { 693 smb_tree_log(sr, name, "access denied: restrict anonymous"); 694 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 695 return (NULL); 696 } 697 698 sr->arg.tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; 699 700 si = kmem_zalloc(sizeof (smb_share_t), KM_SLEEP); 701 (void) strlcpy(si->shr_name, name, MAXNAMELEN); 702 (void) strlcpy(si->shr_path, name, MAXPATHLEN); 703 si->shr_type = STYPE_IPC | STYPE_SPECIAL; 704 705 tree = smb_tree_alloc(user, si, STYPE_IPC, NULL, ACE_ALL_PERMS); 706 if (tree == NULL) { 707 smb_tree_log(sr, name, "access denied"); 708 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 709 } 710 711 kmem_free(si, sizeof (smb_share_t)); 712 return (tree); 713 } 714 715 /* 716 * Allocate a tree. 717 */ 718 static smb_tree_t * 719 smb_tree_alloc( 720 smb_user_t *user, 721 const smb_share_t *si, 722 int32_t stype, 723 smb_node_t *snode, 724 uint32_t access) 725 { 726 smb_tree_t *tree; 727 uint16_t tid; 728 729 if (smb_idpool_alloc(&user->u_tid_pool, &tid)) 730 return (NULL); 731 732 tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP); 733 bzero(tree, sizeof (smb_tree_t)); 734 735 if (STYPE_ISDSK(stype)) { 736 if (smb_tree_getattr(si, snode, tree) != 0) { 737 smb_idpool_free(&user->u_tid_pool, tid); 738 kmem_cache_free(user->u_server->si_cache_tree, tree); 739 return (NULL); 740 } 741 } 742 743 if (smb_idpool_constructor(&tree->t_fid_pool)) { 744 smb_idpool_free(&user->u_tid_pool, tid); 745 kmem_cache_free(user->u_server->si_cache_tree, tree); 746 return (NULL); 747 } 748 749 if (smb_idpool_constructor(&tree->t_odid_pool)) { 750 smb_idpool_destructor(&tree->t_fid_pool); 751 smb_idpool_free(&user->u_tid_pool, tid); 752 kmem_cache_free(user->u_server->si_cache_tree, tree); 753 return (NULL); 754 } 755 756 smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t), 757 offsetof(smb_ofile_t, f_lnd)); 758 759 smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t), 760 offsetof(smb_odir_t, d_lnd)); 761 762 (void) strlcpy(tree->t_sharename, si->shr_name, 763 sizeof (tree->t_sharename)); 764 (void) strlcpy(tree->t_resource, si->shr_path, 765 sizeof (tree->t_resource)); 766 767 mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL); 768 769 tree->t_user = user; 770 tree->t_session = user->u_session; 771 tree->t_server = user->u_server; 772 tree->t_refcnt = 1; 773 tree->t_tid = tid; 774 tree->t_res_type = stype; 775 tree->t_state = SMB_TREE_STATE_CONNECTED; 776 tree->t_magic = SMB_TREE_MAGIC; 777 tree->t_access = access; 778 tree->t_connect_time = gethrestime_sec(); 779 780 /* if FS is readonly, enforce that here */ 781 if (tree->t_flags & SMB_TREE_READONLY) 782 tree->t_access &= ~ACE_ALL_WRITE_PERMS; 783 784 if (STYPE_ISDSK(stype)) { 785 smb_node_ref(snode); 786 tree->t_snode = snode; 787 tree->t_acltype = smb_fsop_acltype(snode); 788 } 789 790 smb_llist_enter(&user->u_tree_list, RW_WRITER); 791 smb_llist_insert_head(&user->u_tree_list, tree); 792 smb_llist_exit(&user->u_tree_list); 793 atomic_inc_32(&user->u_session->s_tree_cnt); 794 atomic_inc_32(&user->u_server->sv_open_trees); 795 796 return (tree); 797 } 798 799 /* 800 * Deallocate a tree: release all resources associated with a tree and 801 * remove the tree from the user's tree list. 802 * 803 * The tree being destroyed must be in the "destroying" state and the 804 * reference count must be zero. This function assumes it's single threaded 805 * i.e. only one thread will attempt to destroy a specific tree, which 806 * should be the case if the tree is in disconnected and has a reference 807 * count of zero. 808 */ 809 static void 810 smb_tree_dealloc(smb_tree_t *tree) 811 { 812 ASSERT(tree); 813 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 814 ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); 815 ASSERT(tree->t_refcnt == 0); 816 817 /* 818 * Remove the tree from the user's tree list. This must be done 819 * before any resources associated with the tree are released. 820 */ 821 smb_llist_enter(&tree->t_user->u_tree_list, RW_WRITER); 822 smb_llist_remove(&tree->t_user->u_tree_list, tree); 823 smb_llist_exit(&tree->t_user->u_tree_list); 824 825 tree->t_magic = (uint32_t)~SMB_TREE_MAGIC; 826 smb_idpool_free(&tree->t_user->u_tid_pool, tree->t_tid); 827 atomic_dec_32(&tree->t_session->s_tree_cnt); 828 829 if (tree->t_snode) 830 smb_node_release(tree->t_snode); 831 832 mutex_destroy(&tree->t_mutex); 833 834 /* 835 * The list of open files and open directories should be empty. 836 */ 837 smb_llist_destructor(&tree->t_ofile_list); 838 smb_llist_destructor(&tree->t_odir_list); 839 smb_idpool_destructor(&tree->t_fid_pool); 840 smb_idpool_destructor(&tree->t_odid_pool); 841 kmem_cache_free(tree->t_server->si_cache_tree, tree); 842 } 843 844 /* 845 * Determine whether or not a tree is connected. 846 * This function must be called with the tree mutex held. 847 */ 848 static boolean_t 849 smb_tree_is_connected_locked(smb_tree_t *tree) 850 { 851 switch (tree->t_state) { 852 case SMB_TREE_STATE_CONNECTED: 853 return (B_TRUE); 854 855 case SMB_TREE_STATE_DISCONNECTING: 856 case SMB_TREE_STATE_DISCONNECTED: 857 /* 858 * The tree exists but being diconnected or destroyed. 859 */ 860 return (B_FALSE); 861 862 default: 863 ASSERT(0); 864 return (B_FALSE); 865 } 866 } 867 868 /* 869 * Determine whether or not a tree is disconnected. 870 * This function must be called with the tree mutex held. 871 */ 872 static boolean_t 873 smb_tree_is_disconnected(smb_tree_t *tree) 874 { 875 switch (tree->t_state) { 876 case SMB_TREE_STATE_DISCONNECTED: 877 return (B_TRUE); 878 879 case SMB_TREE_STATE_CONNECTED: 880 case SMB_TREE_STATE_DISCONNECTING: 881 return (B_FALSE); 882 883 default: 884 ASSERT(0); 885 return (B_FALSE); 886 } 887 } 888 889 /* 890 * Return a pointer to the share name within a share resource path. 891 * 892 * The share path may be a Uniform Naming Convention (UNC) string 893 * (\\server\share) or simply the share name. We validate the UNC 894 * format but we don't look at the server name. 895 */ 896 static const char * 897 smb_tree_get_sharename(const char *unc_path) 898 { 899 const char *sharename = unc_path; 900 901 if (sharename[0] == '\\') { 902 /* 903 * Looks like a UNC path, validate the format. 904 */ 905 if (sharename[1] != '\\') 906 return (NULL); 907 908 if ((sharename = strchr(sharename+2, '\\')) == NULL) 909 return (NULL); 910 911 ++sharename; 912 } else if (strchr(sharename, '\\') != NULL) { 913 /* 914 * This should be a share name (no embedded \'s). 915 */ 916 return (NULL); 917 } 918 919 return (sharename); 920 } 921 922 /* 923 * Map the service to a resource type. Valid values for service are: 924 * 925 * A: Disk share 926 * LPT1: Printer 927 * IPC Named pipe 928 * COMM Communications device 929 * ????? Any type of device (wildcard) 930 * 931 * We support IPC and disk shares; anything else is currently treated 932 * as an error. IPC$ is reserved as the named pipe share. 933 */ 934 static int 935 smb_tree_get_stype(const char *sharename, const char *service, 936 int32_t *stype_ret) 937 { 938 const char *any = "?????"; 939 940 if ((strcmp(service, any) == 0) || (strcasecmp(service, "IPC") == 0)) { 941 if (strcasecmp(sharename, "IPC$") == 0) { 942 *stype_ret = STYPE_IPC; 943 return (0); 944 } 945 } 946 947 if ((strcmp(service, any) == 0) || (strcasecmp(service, "A:") == 0)) { 948 if (strcasecmp(sharename, "IPC$") == 0) 949 return (-1); 950 951 *stype_ret = STYPE_DISKTREE; 952 return (0); 953 } 954 955 return (-1); 956 } 957 958 /* 959 * Obtain the tree attributes: volume name, typename and flags. 960 */ 961 static int 962 smb_tree_getattr(const smb_share_t *si, smb_node_t *node, smb_tree_t *tree) 963 { 964 vfs_t *vfsp = SMB_NODE_VFS(node); 965 966 ASSERT(vfsp); 967 968 if (getvfs(&vfsp->vfs_fsid) != vfsp) 969 return (ESTALE); 970 971 smb_tree_get_volname(vfsp, tree); 972 smb_tree_get_flags(si, vfsp, tree); 973 974 VFS_RELE(vfsp); 975 return (0); 976 } 977 978 /* 979 * Extract the volume name. 980 */ 981 static void 982 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree) 983 { 984 refstr_t *vfs_mntpoint; 985 const char *s; 986 char *name; 987 988 vfs_mntpoint = vfs_getmntpoint(vfsp); 989 990 s = vfs_mntpoint->rs_string; 991 s += strspn(s, "/"); 992 (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN); 993 994 refstr_rele(vfs_mntpoint); 995 996 name = tree->t_volume; 997 (void) strsep((char **)&name, "/"); 998 } 999 1000 /* 1001 * Always set ACL support because the VFS will fake ACLs for file systems 1002 * that don't support them. 1003 * 1004 * Some flags are dependent on the typename, which is also set up here. 1005 * File system types are hardcoded in uts/common/os/vfs_conf.c. 1006 */ 1007 static void 1008 smb_tree_get_flags(const smb_share_t *si, vfs_t *vfsp, smb_tree_t *tree) 1009 { 1010 typedef struct smb_mtype { 1011 char *mt_name; 1012 size_t mt_namelen; 1013 uint32_t mt_flags; 1014 } smb_mtype_t; 1015 1016 static smb_mtype_t smb_mtype[] = { 1017 { "zfs", 3, SMB_TREE_UNICODE_ON_DISK }, 1018 { "ufs", 3, SMB_TREE_UNICODE_ON_DISK }, 1019 { "nfs", 3, SMB_TREE_NFS_MOUNTED }, 1020 { "tmpfs", 5, SMB_TREE_NO_EXPORT } 1021 }; 1022 smb_mtype_t *mtype; 1023 char *name; 1024 uint32_t flags = SMB_TREE_SUPPORTS_ACLS; 1025 int i; 1026 1027 if (si->shr_flags & SMB_SHRF_CATIA) 1028 flags |= SMB_TREE_CATIA; 1029 1030 if (si->shr_flags & SMB_SHRF_ABE) 1031 flags |= SMB_TREE_ABE; 1032 1033 if (vfsp->vfs_flag & VFS_RDONLY) 1034 flags |= SMB_TREE_READONLY; 1035 1036 if (vfsp->vfs_flag & VFS_XATTR) 1037 flags |= SMB_TREE_STREAMS; 1038 1039 if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) 1040 flags |= SMB_TREE_NO_ATIME; 1041 1042 name = vfssw[vfsp->vfs_fstype].vsw_name; 1043 1044 for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) { 1045 mtype = &smb_mtype[i]; 1046 if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0) 1047 flags |= mtype->mt_flags; 1048 } 1049 1050 (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN); 1051 (void) smb_strupr((char *)tree->t_typename); 1052 1053 if (vfs_has_feature(vfsp, VFSFT_XVATTR)) 1054 flags |= SMB_TREE_XVATTR; 1055 1056 if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE)) 1057 flags |= SMB_TREE_CASEINSENSITIVE; 1058 1059 if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE)) 1060 flags |= SMB_TREE_NO_CASESENSITIVE; 1061 1062 if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS)) 1063 flags |= SMB_TREE_DIRENTFLAGS; 1064 1065 if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE)) 1066 flags |= SMB_TREE_ACLONCREATE; 1067 1068 if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS)) 1069 flags |= SMB_TREE_ACEMASKONACCESS; 1070 1071 DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name); 1072 1073 1074 tree->t_flags = flags; 1075 } 1076 1077 /* 1078 * Report share access result to syslog. 1079 */ 1080 static void 1081 smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...) 1082 { 1083 va_list ap; 1084 char buf[128]; 1085 smb_user_t *user = sr->uid_user; 1086 1087 ASSERT(user); 1088 1089 if (smb_tcon_mute) 1090 return; 1091 1092 if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) { 1093 /* 1094 * Only report normal users, i.e. ignore W2K misuse 1095 * of the IPC connection by filtering out internal 1096 * names such as nobody and root. 1097 */ 1098 if ((strcmp(user->u_name, "root") == 0) || 1099 (strcmp(user->u_name, "nobody") == 0)) { 1100 return; 1101 } 1102 } 1103 1104 va_start(ap, fmt); 1105 (void) vsnprintf(buf, 128, fmt, ap); 1106 va_end(ap); 1107 1108 cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s", 1109 user->u_domain, user->u_name, sharename, buf); 1110 } 1111 1112 /* 1113 * smb_tree_lookup_odir 1114 * 1115 * Find the specified odir in the tree's list of odirs, and 1116 * attempt to obtain a hold on the odir. 1117 * 1118 * Returns NULL if odir not found or a hold cannot be obtained. 1119 */ 1120 smb_odir_t * 1121 smb_tree_lookup_odir(smb_tree_t *tree, uint16_t odid) 1122 { 1123 smb_odir_t *od; 1124 smb_llist_t *od_list; 1125 1126 ASSERT(tree); 1127 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1128 1129 od_list = &tree->t_odir_list; 1130 smb_llist_enter(od_list, RW_READER); 1131 1132 od = smb_llist_head(od_list); 1133 while (od) { 1134 if (od->d_odid == odid) { 1135 if (!smb_odir_hold(od)) 1136 od = NULL; 1137 break; 1138 } 1139 od = smb_llist_next(od_list, od); 1140 } 1141 1142 smb_llist_exit(od_list); 1143 return (od); 1144 } 1145 1146 boolean_t 1147 smb_tree_is_connected(smb_tree_t *tree) 1148 { 1149 boolean_t rb; 1150 1151 mutex_enter(&tree->t_mutex); 1152 rb = smb_tree_is_connected_locked(tree); 1153 mutex_exit(&tree->t_mutex); 1154 return (rb); 1155 } 1156 1157 /* 1158 * Get the next open ofile in the list. A reference is taken on 1159 * the ofile, which can be released later with smb_ofile_release(). 1160 * 1161 * If the specified ofile is NULL, search from the beginning of the 1162 * list. Otherwise, the search starts just after that ofile. 1163 * 1164 * Returns NULL if there are no open files in the list. 1165 */ 1166 static smb_ofile_t * 1167 smb_tree_get_ofile(smb_tree_t *tree, smb_ofile_t *of) 1168 { 1169 smb_llist_t *ofile_list; 1170 1171 ASSERT(tree); 1172 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1173 1174 ofile_list = &tree->t_ofile_list; 1175 smb_llist_enter(ofile_list, RW_READER); 1176 1177 if (of) { 1178 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 1179 of = smb_llist_next(ofile_list, of); 1180 } else { 1181 of = smb_llist_head(ofile_list); 1182 } 1183 1184 while (of) { 1185 if (smb_ofile_hold(of)) 1186 break; 1187 1188 of = smb_llist_next(ofile_list, of); 1189 } 1190 1191 smb_llist_exit(ofile_list); 1192 return (of); 1193 } 1194 1195 /* 1196 * smb_tree_get_odir 1197 * 1198 * Find the next odir in the tree's list of odirs, and obtain a 1199 * hold on it. 1200 * If the specified odir is NULL the search starts at the beginning 1201 * of the tree's odir list, otherwise the search starts after the 1202 * specified odir. 1203 */ 1204 static smb_odir_t * 1205 smb_tree_get_odir(smb_tree_t *tree, smb_odir_t *od) 1206 { 1207 smb_llist_t *od_list; 1208 1209 ASSERT(tree); 1210 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1211 1212 od_list = &tree->t_odir_list; 1213 smb_llist_enter(od_list, RW_READER); 1214 1215 if (od) { 1216 ASSERT(od->d_magic == SMB_ODIR_MAGIC); 1217 od = smb_llist_next(od_list, od); 1218 } else { 1219 od = smb_llist_head(od_list); 1220 } 1221 1222 while (od) { 1223 ASSERT(od->d_magic == SMB_ODIR_MAGIC); 1224 1225 if (smb_odir_hold(od)) 1226 break; 1227 od = smb_llist_next(od_list, od); 1228 } 1229 1230 smb_llist_exit(od_list); 1231 return (od); 1232 } 1233 1234 /* 1235 * smb_tree_close_odirs 1236 * 1237 * Close all open odirs in the tree's list which were opened by 1238 * the process identified by pid. 1239 * If pid is zero, close all open odirs in the tree's list. 1240 */ 1241 static void 1242 smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid) 1243 { 1244 smb_odir_t *od, *next_od; 1245 1246 ASSERT(tree); 1247 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1248 1249 od = smb_tree_get_odir(tree, NULL); 1250 while (od) { 1251 ASSERT(od->d_magic == SMB_ODIR_MAGIC); 1252 ASSERT(od->d_tree == tree); 1253 1254 next_od = smb_tree_get_odir(tree, od); 1255 if ((pid == 0) || (od->d_opened_by_pid == pid)) 1256 smb_odir_close(od); 1257 smb_odir_release(od); 1258 1259 od = next_od; 1260 } 1261 } 1262 1263 static void 1264 smb_tree_set_execsub_info(smb_tree_t *tree, smb_execsub_info_t *subs) 1265 { 1266 subs->e_winname = tree->t_user->u_name; 1267 subs->e_userdom = tree->t_user->u_domain; 1268 subs->e_srv_ipaddr = tree->t_session->local_ipaddr; 1269 subs->e_cli_ipaddr = tree->t_session->ipaddr; 1270 subs->e_cli_netbiosname = tree->t_session->workstation; 1271 subs->e_uid = crgetuid(tree->t_user->u_cred); 1272 } 1273 1274 /* 1275 * Private function to support smb_tree_enum. 1276 */ 1277 static int 1278 smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum) 1279 { 1280 uint8_t *pb; 1281 uint_t nbytes; 1282 int rc; 1283 1284 if (svcenum->se_nskip > 0) { 1285 svcenum->se_nskip--; 1286 return (0); 1287 } 1288 1289 if (svcenum->se_nitems >= svcenum->se_nlimit) { 1290 svcenum->se_nitems = svcenum->se_nlimit; 1291 return (0); 1292 } 1293 1294 pb = &svcenum->se_buf[svcenum->se_bused]; 1295 rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes); 1296 if (rc == 0) { 1297 svcenum->se_bavail -= nbytes; 1298 svcenum->se_bused += nbytes; 1299 svcenum->se_nitems++; 1300 } 1301 1302 return (rc); 1303 } 1304 1305 /* 1306 * Encode connection information into a buffer: connection information 1307 * needed in user space to support RPC requests. 1308 */ 1309 static int 1310 smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen, 1311 uint32_t *nbytes) 1312 { 1313 smb_netconnectinfo_t info; 1314 int rc; 1315 1316 smb_tree_netinfo_init(tree, &info); 1317 rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes); 1318 smb_tree_netinfo_fini(&info); 1319 1320 return (rc); 1321 } 1322 1323 /* 1324 * Note: ci_numusers should be the number of users connected to 1325 * the share rather than the number of references on the tree but 1326 * we don't have a mechanism to track users/share in smbsrv yet. 1327 */ 1328 static void 1329 smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info) 1330 { 1331 smb_user_t *user; 1332 1333 ASSERT(tree); 1334 1335 info->ci_id = tree->t_tid; 1336 info->ci_type = tree->t_res_type; 1337 info->ci_numopens = tree->t_open_files; 1338 info->ci_numusers = tree->t_refcnt; 1339 info->ci_time = gethrestime_sec() - tree->t_connect_time; 1340 1341 info->ci_sharelen = strlen(tree->t_sharename) + 1; 1342 info->ci_share = smb_strdup(tree->t_sharename); 1343 1344 user = tree->t_user; 1345 ASSERT(user); 1346 1347 info->ci_namelen = user->u_domain_len + user->u_name_len + 2; 1348 info->ci_username = kmem_alloc(info->ci_namelen, KM_SLEEP); 1349 (void) snprintf(info->ci_username, info->ci_namelen, "%s\\%s", 1350 user->u_domain, user->u_name); 1351 } 1352 1353 static void 1354 smb_tree_netinfo_fini(smb_netconnectinfo_t *info) 1355 { 1356 if (info == NULL) 1357 return; 1358 1359 if (info->ci_username) 1360 kmem_free(info->ci_username, info->ci_namelen); 1361 if (info->ci_share) 1362 smb_mfree(info->ci_share); 1363 1364 bzero(info, sizeof (smb_netconnectinfo_t)); 1365 } 1366