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(smb_request_t *sr, const smb_share_t *si, vnode_t *pathvp, 436 uint32_t *access) 437 { 438 smb_user_t *user; 439 cred_t *cred; 440 int rc; 441 vfs_t *vfsp; 442 vnode_t *root = NULL; 443 vnode_t *sharevp = NULL; 444 char *sharepath; 445 struct pathname pnp; 446 size_t size; 447 448 user = sr->uid_user; 449 cred = user->u_cred; 450 *access = ACE_ALL_PERMS; /* default to full "UNIX" access */ 451 452 if (si->shr_flags & SMB_SHRF_AUTOHOME) { 453 /* 454 * An autohome share owner gets full access to the share. 455 * Everyone else is denied access. 456 */ 457 if (smb_strcasecmp(si->shr_name, user->u_name, 0) != 0) 458 *access = 0; 459 return; 460 } 461 462 /* 463 * Using the vnode of the share path, we then find the root 464 * directory of the mounted file system. We will then look to 465 * see if there is a .zfs/shares directory and if there is, 466 * get the access information from the ACL/ACES values and 467 * check against the cred. 468 */ 469 vfsp = pathvp->v_vfsp; 470 if (vfsp != NULL) 471 rc = VFS_ROOT(vfsp, &root); 472 else 473 rc = ENOENT; 474 475 if (rc != 0) 476 return; 477 478 479 /* 480 * Find the share object, if there is one. Need to construct 481 * the path to the .zfs/shares/<sharename> object and look it 482 * up. root is called held but will be released by 483 * lookuppnvp(). 484 */ 485 486 size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1; 487 sharepath = kmem_alloc(size, KM_SLEEP); 488 (void) sprintf(sharepath, "%s%s", SHARES_DIR, si->shr_name); 489 490 pn_alloc(&pnp); 491 (void) pn_set(&pnp, sharepath); 492 rc = lookuppnvp(&pnp, NULL, NO_FOLLOW, NULL, 493 &sharevp, rootdir, root, kcred); 494 pn_free(&pnp); 495 496 kmem_free(sharepath, size); 497 498 /* 499 * Now get the effective access value based on cred and ACL 500 * values. 501 */ 502 503 if (rc == 0) { 504 smb_vop_eaccess(sharevp, (int *)access, V_ACE_MASK, NULL, cred); 505 VN_RELE(sharevp); 506 } 507 } 508 509 /* 510 * Connect a share for use with files and directories. 511 */ 512 513 static smb_tree_t * 514 smb_tree_connect_disk(smb_request_t *sr, const char *sharename) 515 { 516 smb_user_t *user = sr->uid_user; 517 smb_node_t *dnode = NULL; 518 smb_node_t *snode = NULL; 519 char last_component[MAXNAMELEN]; 520 smb_tree_t *tree; 521 smb_share_t *si; 522 cred_t *u_cred; 523 int rc; 524 uint32_t access = 0; /* read/write is assumed */ 525 uint32_t hostaccess = ACE_ALL_PERMS; 526 uint32_t aclaccess; 527 smb_execsub_info_t subs; 528 529 ASSERT(user); 530 u_cred = user->u_cred; 531 ASSERT(u_cred); 532 533 if (user->u_flags & SMB_USER_FLAG_IPC) { 534 smb_tree_log(sr, sharename, "access denied: IPC only"); 535 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 536 return (NULL); 537 } 538 539 si = kmem_zalloc(sizeof (smb_share_t), KM_SLEEP); 540 541 if (smb_kshare_getinfo(sr->sr_server->sv_lmshrd, (char *)sharename, si, 542 &sr->session->ipaddr) != NERR_Success) { 543 smb_tree_log(sr, sharename, "share not found"); 544 smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 545 kmem_free(si, sizeof (smb_share_t)); 546 return (NULL); 547 } 548 549 if (user->u_flags & SMB_USER_FLAG_GUEST) { 550 if ((si->shr_flags & SMB_SHRF_GUEST_OK) == 0) { 551 smb_tree_log(sr, sharename, 552 "access denied: guest disabled"); 553 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, 554 ERRaccess); 555 kmem_free(si, sizeof (smb_share_t)); 556 return (NULL); 557 } 558 } 559 560 /* 561 * Handle the default administration shares: C$, D$ etc. 562 * Only a user with admin rights is allowed to map these 563 * shares. 564 */ 565 if (si->shr_flags & SMB_SHRF_ADMIN) { 566 if (!smb_user_is_admin(user)) { 567 smb_tree_log(sr, sharename, "access denied: not admin"); 568 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 569 ERRSRV, ERRaccess); 570 kmem_free(si, sizeof (smb_share_t)); 571 return (NULL); 572 } 573 } 574 575 /* 576 * Set up the OptionalSupport for this share. 577 */ 578 sr->arg.tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; 579 580 switch (si->shr_flags & SMB_SHRF_CSC_MASK) { 581 case SMB_SHRF_CSC_DISABLED: 582 sr->arg.tcon.optional_support |= SMB_CSC_CACHE_NONE; 583 break; 584 case SMB_SHRF_CSC_AUTO: 585 sr->arg.tcon.optional_support |= SMB_CSC_CACHE_AUTO_REINT; 586 break; 587 case SMB_SHRF_CSC_VDO: 588 sr->arg.tcon.optional_support |= SMB_CSC_CACHE_VDO; 589 break; 590 case SMB_SHRF_CSC_MANUAL: 591 default: 592 /* 593 * Default to SMB_CSC_CACHE_MANUAL_REINT. 594 */ 595 break; 596 } 597 598 /* ABE support */ 599 if (si->shr_flags & SMB_SHRF_ABE) 600 sr->arg.tcon.optional_support |= 601 SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM; 602 603 access = si->shr_access_value & SMB_SHRF_ACC_ALL; 604 605 if (access == SMB_SHRF_ACC_RO) { 606 hostaccess &= ~ACE_ALL_WRITE_PERMS; 607 } else if (access == SMB_SHRF_ACC_NONE) { 608 kmem_free(si, sizeof (smb_share_t)); 609 smb_tree_log(sr, sharename, "access denied: host access"); 610 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 611 return (NULL); 612 } 613 614 /* 615 * Check that the shared directory exists. 616 */ 617 rc = smb_pathname_reduce(sr, u_cred, si->shr_path, 0, 0, &dnode, 618 last_component); 619 620 if (rc == 0) { 621 rc = smb_fsop_lookup(sr, u_cred, SMB_FOLLOW_LINKS, 622 sr->sr_server->si_root_smb_node, dnode, last_component, 623 &snode); 624 625 smb_node_release(dnode); 626 } 627 628 if (rc) { 629 if (snode) 630 smb_node_release(snode); 631 632 smb_tree_log(sr, sharename, "bad path: %s", si->shr_path); 633 smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 634 kmem_free(si, sizeof (smb_share_t)); 635 return (NULL); 636 } 637 638 /* 639 * Find share level ACL if it exists in the designated 640 * location. Needs to be done after finding a valid path but 641 * before the tree is allocated. 642 */ 643 smb_tree_acl_access(sr, si, snode->vp, &aclaccess); 644 if ((aclaccess & ACE_ALL_PERMS) == 0) { 645 smb_tree_log(sr, sharename, "access denied: share ACL"); 646 smbsr_error(sr, 0, ERRSRV, ERRaccess); 647 kmem_free(si, sizeof (smb_share_t)); 648 smb_node_release(snode); 649 return (NULL); 650 } 651 652 /* 653 * Set tree ACL access to the minimum ACL permissions based on 654 * hostaccess (those allowed by host based access) and 655 * aclaccess (those from the ACL object for the share). This 656 * is done during the alloc. 657 */ 658 659 (void) strlcpy(si->shr_name, sharename, MAXNAMELEN); 660 tree = smb_tree_alloc(user, si, STYPE_DISKTREE, snode, 661 hostaccess & aclaccess); 662 663 smb_node_release(snode); 664 665 if (tree == NULL) 666 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 667 else { 668 669 tree->t_shr_flags = si->shr_flags; 670 671 if (tree->t_shr_flags & SMB_SHRF_MAP) { 672 (void) smb_tree_set_execsub_info(tree, &subs); 673 674 rc = smb_kshare_exec(sr->sr_server->sv_lmshrd, 675 (char *)sharename, &subs, SMB_SHR_MAP); 676 677 if (rc != 0 && tree->t_shr_flags & SMB_SHRF_DISP_TERM) { 678 smb_tree_disconnect(tree, B_FALSE); 679 smb_tree_release(tree); 680 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, 681 ERRaccess); 682 kmem_free(si, sizeof (smb_share_t)); 683 return (NULL); 684 } 685 } 686 } 687 688 kmem_free(si, sizeof (smb_share_t)); 689 690 return (tree); 691 } 692 693 /* 694 * Connect an IPC share for use with named pipes. 695 */ 696 static smb_tree_t * 697 smb_tree_connect_ipc(smb_request_t *sr, const char *name) 698 { 699 smb_user_t *user = sr->uid_user; 700 smb_tree_t *tree; 701 smb_share_t *si; 702 703 ASSERT(user); 704 705 if ((user->u_flags & SMB_USER_FLAG_IPC) && 706 sr->sr_cfg->skc_restrict_anon) { 707 smb_tree_log(sr, name, "access denied: restrict anonymous"); 708 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 709 return (NULL); 710 } 711 712 sr->arg.tcon.optional_support = SMB_SUPPORT_SEARCH_BITS; 713 714 si = kmem_zalloc(sizeof (smb_share_t), KM_SLEEP); 715 (void) strlcpy(si->shr_name, name, MAXNAMELEN); 716 (void) strlcpy(si->shr_path, name, MAXPATHLEN); 717 si->shr_type = STYPE_IPC | STYPE_SPECIAL; 718 719 tree = smb_tree_alloc(user, si, STYPE_IPC, NULL, ACE_ALL_PERMS); 720 if (tree == NULL) { 721 smb_tree_log(sr, name, "access denied"); 722 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess); 723 } 724 725 kmem_free(si, sizeof (smb_share_t)); 726 return (tree); 727 } 728 729 /* 730 * Allocate a tree. 731 */ 732 static smb_tree_t * 733 smb_tree_alloc( 734 smb_user_t *user, 735 const smb_share_t *si, 736 int32_t stype, 737 smb_node_t *snode, 738 uint32_t access) 739 { 740 smb_tree_t *tree; 741 uint16_t tid; 742 743 if (smb_idpool_alloc(&user->u_tid_pool, &tid)) 744 return (NULL); 745 746 tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP); 747 bzero(tree, sizeof (smb_tree_t)); 748 749 if (STYPE_ISDSK(stype)) { 750 if (smb_tree_getattr(si, snode, tree) != 0) { 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 757 if (smb_idpool_constructor(&tree->t_fid_pool)) { 758 smb_idpool_free(&user->u_tid_pool, tid); 759 kmem_cache_free(user->u_server->si_cache_tree, tree); 760 return (NULL); 761 } 762 763 if (smb_idpool_constructor(&tree->t_odid_pool)) { 764 smb_idpool_destructor(&tree->t_fid_pool); 765 smb_idpool_free(&user->u_tid_pool, tid); 766 kmem_cache_free(user->u_server->si_cache_tree, tree); 767 return (NULL); 768 } 769 770 smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t), 771 offsetof(smb_ofile_t, f_lnd)); 772 773 smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t), 774 offsetof(smb_odir_t, d_lnd)); 775 776 (void) strlcpy(tree->t_sharename, si->shr_name, 777 sizeof (tree->t_sharename)); 778 (void) strlcpy(tree->t_resource, si->shr_path, 779 sizeof (tree->t_resource)); 780 781 mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL); 782 783 tree->t_user = user; 784 tree->t_session = user->u_session; 785 tree->t_server = user->u_server; 786 tree->t_refcnt = 1; 787 tree->t_tid = tid; 788 tree->t_res_type = stype; 789 tree->t_state = SMB_TREE_STATE_CONNECTED; 790 tree->t_magic = SMB_TREE_MAGIC; 791 tree->t_access = access; 792 tree->t_connect_time = gethrestime_sec(); 793 794 /* if FS is readonly, enforce that here */ 795 if (tree->t_flags & SMB_TREE_READONLY) 796 tree->t_access &= ~ACE_ALL_WRITE_PERMS; 797 798 if (STYPE_ISDSK(stype)) { 799 smb_node_ref(snode); 800 tree->t_snode = snode; 801 tree->t_acltype = smb_fsop_acltype(snode); 802 } 803 804 smb_llist_enter(&user->u_tree_list, RW_WRITER); 805 smb_llist_insert_head(&user->u_tree_list, tree); 806 smb_llist_exit(&user->u_tree_list); 807 atomic_inc_32(&user->u_session->s_tree_cnt); 808 atomic_inc_32(&user->u_server->sv_open_trees); 809 810 return (tree); 811 } 812 813 /* 814 * Deallocate a tree: release all resources associated with a tree and 815 * remove the tree from the user's tree list. 816 * 817 * The tree being destroyed must be in the "destroying" state and the 818 * reference count must be zero. This function assumes it's single threaded 819 * i.e. only one thread will attempt to destroy a specific tree, which 820 * should be the case if the tree is in disconnected and has a reference 821 * count of zero. 822 */ 823 static void 824 smb_tree_dealloc(smb_tree_t *tree) 825 { 826 ASSERT(tree); 827 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 828 ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED); 829 ASSERT(tree->t_refcnt == 0); 830 831 /* 832 * Remove the tree from the user's tree list. This must be done 833 * before any resources associated with the tree are released. 834 */ 835 smb_llist_enter(&tree->t_user->u_tree_list, RW_WRITER); 836 smb_llist_remove(&tree->t_user->u_tree_list, tree); 837 smb_llist_exit(&tree->t_user->u_tree_list); 838 839 tree->t_magic = (uint32_t)~SMB_TREE_MAGIC; 840 smb_idpool_free(&tree->t_user->u_tid_pool, tree->t_tid); 841 atomic_dec_32(&tree->t_session->s_tree_cnt); 842 843 if (tree->t_snode) 844 smb_node_release(tree->t_snode); 845 846 mutex_destroy(&tree->t_mutex); 847 848 /* 849 * The list of open files and open directories should be empty. 850 */ 851 smb_llist_destructor(&tree->t_ofile_list); 852 smb_llist_destructor(&tree->t_odir_list); 853 smb_idpool_destructor(&tree->t_fid_pool); 854 smb_idpool_destructor(&tree->t_odid_pool); 855 kmem_cache_free(tree->t_server->si_cache_tree, tree); 856 } 857 858 /* 859 * Determine whether or not a tree is connected. 860 * This function must be called with the tree mutex held. 861 */ 862 static boolean_t 863 smb_tree_is_connected_locked(smb_tree_t *tree) 864 { 865 switch (tree->t_state) { 866 case SMB_TREE_STATE_CONNECTED: 867 return (B_TRUE); 868 869 case SMB_TREE_STATE_DISCONNECTING: 870 case SMB_TREE_STATE_DISCONNECTED: 871 /* 872 * The tree exists but being diconnected or destroyed. 873 */ 874 return (B_FALSE); 875 876 default: 877 ASSERT(0); 878 return (B_FALSE); 879 } 880 } 881 882 /* 883 * Determine whether or not a tree is disconnected. 884 * This function must be called with the tree mutex held. 885 */ 886 static boolean_t 887 smb_tree_is_disconnected(smb_tree_t *tree) 888 { 889 switch (tree->t_state) { 890 case SMB_TREE_STATE_DISCONNECTED: 891 return (B_TRUE); 892 893 case SMB_TREE_STATE_CONNECTED: 894 case SMB_TREE_STATE_DISCONNECTING: 895 return (B_FALSE); 896 897 default: 898 ASSERT(0); 899 return (B_FALSE); 900 } 901 } 902 903 /* 904 * Return a pointer to the share name within a share resource path. 905 * 906 * The share path may be a Uniform Naming Convention (UNC) string 907 * (\\server\share) or simply the share name. We validate the UNC 908 * format but we don't look at the server name. 909 */ 910 static const char * 911 smb_tree_get_sharename(const char *unc_path) 912 { 913 const char *sharename = unc_path; 914 915 if (sharename[0] == '\\') { 916 /* 917 * Looks like a UNC path, validate the format. 918 */ 919 if (sharename[1] != '\\') 920 return (NULL); 921 922 if ((sharename = strchr(sharename+2, '\\')) == NULL) 923 return (NULL); 924 925 ++sharename; 926 } else if (strchr(sharename, '\\') != NULL) { 927 /* 928 * This should be a share name (no embedded \'s). 929 */ 930 return (NULL); 931 } 932 933 return (sharename); 934 } 935 936 /* 937 * Map the service to a resource type. Valid values for service are: 938 * 939 * A: Disk share 940 * LPT1: Printer 941 * IPC Named pipe 942 * COMM Communications device 943 * ????? Any type of device (wildcard) 944 * 945 * We support IPC and disk shares; anything else is currently treated 946 * as an error. IPC$ is reserved as the named pipe share. 947 */ 948 static int 949 smb_tree_get_stype(const char *sharename, const char *service, 950 int32_t *stype_ret) 951 { 952 const char *any = "?????"; 953 954 if ((strcmp(service, any) == 0) || (strcasecmp(service, "IPC") == 0)) { 955 if (strcasecmp(sharename, "IPC$") == 0) { 956 *stype_ret = STYPE_IPC; 957 return (0); 958 } 959 } 960 961 if ((strcmp(service, any) == 0) || (strcasecmp(service, "A:") == 0)) { 962 if (strcasecmp(sharename, "IPC$") == 0) 963 return (-1); 964 965 *stype_ret = STYPE_DISKTREE; 966 return (0); 967 } 968 969 return (-1); 970 } 971 972 /* 973 * Obtain the tree attributes: volume name, typename and flags. 974 */ 975 static int 976 smb_tree_getattr(const smb_share_t *si, smb_node_t *node, smb_tree_t *tree) 977 { 978 vfs_t *vfsp = SMB_NODE_VFS(node); 979 980 ASSERT(vfsp); 981 982 if (getvfs(&vfsp->vfs_fsid) != vfsp) 983 return (ESTALE); 984 985 smb_tree_get_volname(vfsp, tree); 986 smb_tree_get_flags(si, vfsp, tree); 987 988 VFS_RELE(vfsp); 989 return (0); 990 } 991 992 /* 993 * Extract the volume name. 994 */ 995 static void 996 smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree) 997 { 998 refstr_t *vfs_mntpoint; 999 const char *s; 1000 char *name; 1001 1002 vfs_mntpoint = vfs_getmntpoint(vfsp); 1003 1004 s = vfs_mntpoint->rs_string; 1005 s += strspn(s, "/"); 1006 (void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN); 1007 1008 refstr_rele(vfs_mntpoint); 1009 1010 name = tree->t_volume; 1011 (void) strsep((char **)&name, "/"); 1012 } 1013 1014 /* 1015 * Always set ACL support because the VFS will fake ACLs for file systems 1016 * that don't support them. 1017 * 1018 * Some flags are dependent on the typename, which is also set up here. 1019 * File system types are hardcoded in uts/common/os/vfs_conf.c. 1020 */ 1021 static void 1022 smb_tree_get_flags(const smb_share_t *si, vfs_t *vfsp, smb_tree_t *tree) 1023 { 1024 typedef struct smb_mtype { 1025 char *mt_name; 1026 size_t mt_namelen; 1027 uint32_t mt_flags; 1028 } smb_mtype_t; 1029 1030 static smb_mtype_t smb_mtype[] = { 1031 { "zfs", 3, SMB_TREE_UNICODE_ON_DISK }, 1032 { "ufs", 3, SMB_TREE_UNICODE_ON_DISK }, 1033 { "nfs", 3, SMB_TREE_NFS_MOUNTED }, 1034 { "tmpfs", 5, SMB_TREE_NO_EXPORT } 1035 }; 1036 smb_mtype_t *mtype; 1037 char *name; 1038 uint32_t flags = SMB_TREE_SUPPORTS_ACLS; 1039 int i; 1040 1041 if (si->shr_flags & SMB_SHRF_CATIA) 1042 flags |= SMB_TREE_CATIA; 1043 1044 if (si->shr_flags & SMB_SHRF_ABE) 1045 flags |= SMB_TREE_ABE; 1046 1047 if (vfsp->vfs_flag & VFS_RDONLY) 1048 flags |= SMB_TREE_READONLY; 1049 1050 if (vfsp->vfs_flag & VFS_XATTR) 1051 flags |= SMB_TREE_STREAMS; 1052 1053 if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) 1054 flags |= SMB_TREE_NO_ATIME; 1055 1056 name = vfssw[vfsp->vfs_fstype].vsw_name; 1057 1058 for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) { 1059 mtype = &smb_mtype[i]; 1060 if (strncasecmp(name, mtype->mt_name, mtype->mt_namelen) == 0) 1061 flags |= mtype->mt_flags; 1062 } 1063 1064 (void) strlcpy(tree->t_typename, name, SMB_TYPENAMELEN); 1065 (void) smb_strupr((char *)tree->t_typename); 1066 1067 if (vfs_has_feature(vfsp, VFSFT_XVATTR)) 1068 flags |= SMB_TREE_XVATTR; 1069 1070 if (vfs_has_feature(vfsp, VFSFT_CASEINSENSITIVE)) 1071 flags |= SMB_TREE_CASEINSENSITIVE; 1072 1073 if (vfs_has_feature(vfsp, VFSFT_NOCASESENSITIVE)) 1074 flags |= SMB_TREE_NO_CASESENSITIVE; 1075 1076 if (vfs_has_feature(vfsp, VFSFT_DIRENTFLAGS)) 1077 flags |= SMB_TREE_DIRENTFLAGS; 1078 1079 if (vfs_has_feature(vfsp, VFSFT_ACLONCREATE)) 1080 flags |= SMB_TREE_ACLONCREATE; 1081 1082 if (vfs_has_feature(vfsp, VFSFT_ACEMASKONACCESS)) 1083 flags |= SMB_TREE_ACEMASKONACCESS; 1084 1085 DTRACE_PROBE2(smb__tree__flags, uint32_t, flags, char *, name); 1086 1087 1088 tree->t_flags = flags; 1089 } 1090 1091 /* 1092 * Report share access result to syslog. 1093 */ 1094 static void 1095 smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...) 1096 { 1097 va_list ap; 1098 char buf[128]; 1099 smb_user_t *user = sr->uid_user; 1100 1101 ASSERT(user); 1102 1103 if (smb_tcon_mute) 1104 return; 1105 1106 if ((user->u_name) && (strcasecmp(sharename, "IPC$") == 0)) { 1107 /* 1108 * Only report normal users, i.e. ignore W2K misuse 1109 * of the IPC connection by filtering out internal 1110 * names such as nobody and root. 1111 */ 1112 if ((strcmp(user->u_name, "root") == 0) || 1113 (strcmp(user->u_name, "nobody") == 0)) { 1114 return; 1115 } 1116 } 1117 1118 va_start(ap, fmt); 1119 (void) vsnprintf(buf, 128, fmt, ap); 1120 va_end(ap); 1121 1122 cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s", 1123 user->u_domain, user->u_name, sharename, buf); 1124 } 1125 1126 /* 1127 * smb_tree_lookup_odir 1128 * 1129 * Find the specified odir in the tree's list of odirs, and 1130 * attempt to obtain a hold on the odir. 1131 * 1132 * Returns NULL if odir not found or a hold cannot be obtained. 1133 */ 1134 smb_odir_t * 1135 smb_tree_lookup_odir(smb_tree_t *tree, uint16_t odid) 1136 { 1137 smb_odir_t *od; 1138 smb_llist_t *od_list; 1139 1140 ASSERT(tree); 1141 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1142 1143 od_list = &tree->t_odir_list; 1144 smb_llist_enter(od_list, RW_READER); 1145 1146 od = smb_llist_head(od_list); 1147 while (od) { 1148 if (od->d_odid == odid) { 1149 if (!smb_odir_hold(od)) 1150 od = NULL; 1151 break; 1152 } 1153 od = smb_llist_next(od_list, od); 1154 } 1155 1156 smb_llist_exit(od_list); 1157 return (od); 1158 } 1159 1160 boolean_t 1161 smb_tree_is_connected(smb_tree_t *tree) 1162 { 1163 boolean_t rb; 1164 1165 mutex_enter(&tree->t_mutex); 1166 rb = smb_tree_is_connected_locked(tree); 1167 mutex_exit(&tree->t_mutex); 1168 return (rb); 1169 } 1170 1171 /* 1172 * Get the next open ofile in the list. A reference is taken on 1173 * the ofile, which can be released later with smb_ofile_release(). 1174 * 1175 * If the specified ofile is NULL, search from the beginning of the 1176 * list. Otherwise, the search starts just after that ofile. 1177 * 1178 * Returns NULL if there are no open files in the list. 1179 */ 1180 static smb_ofile_t * 1181 smb_tree_get_ofile(smb_tree_t *tree, smb_ofile_t *of) 1182 { 1183 smb_llist_t *ofile_list; 1184 1185 ASSERT(tree); 1186 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1187 1188 ofile_list = &tree->t_ofile_list; 1189 smb_llist_enter(ofile_list, RW_READER); 1190 1191 if (of) { 1192 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 1193 of = smb_llist_next(ofile_list, of); 1194 } else { 1195 of = smb_llist_head(ofile_list); 1196 } 1197 1198 while (of) { 1199 if (smb_ofile_hold(of)) 1200 break; 1201 1202 of = smb_llist_next(ofile_list, of); 1203 } 1204 1205 smb_llist_exit(ofile_list); 1206 return (of); 1207 } 1208 1209 /* 1210 * smb_tree_get_odir 1211 * 1212 * Find the next odir in the tree's list of odirs, and obtain a 1213 * hold on it. 1214 * If the specified odir is NULL the search starts at the beginning 1215 * of the tree's odir list, otherwise the search starts after the 1216 * specified odir. 1217 */ 1218 static smb_odir_t * 1219 smb_tree_get_odir(smb_tree_t *tree, smb_odir_t *od) 1220 { 1221 smb_llist_t *od_list; 1222 1223 ASSERT(tree); 1224 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1225 1226 od_list = &tree->t_odir_list; 1227 smb_llist_enter(od_list, RW_READER); 1228 1229 if (od) { 1230 ASSERT(od->d_magic == SMB_ODIR_MAGIC); 1231 od = smb_llist_next(od_list, od); 1232 } else { 1233 od = smb_llist_head(od_list); 1234 } 1235 1236 while (od) { 1237 ASSERT(od->d_magic == SMB_ODIR_MAGIC); 1238 1239 if (smb_odir_hold(od)) 1240 break; 1241 od = smb_llist_next(od_list, od); 1242 } 1243 1244 smb_llist_exit(od_list); 1245 return (od); 1246 } 1247 1248 /* 1249 * smb_tree_close_odirs 1250 * 1251 * Close all open odirs in the tree's list which were opened by 1252 * the process identified by pid. 1253 * If pid is zero, close all open odirs in the tree's list. 1254 */ 1255 static void 1256 smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid) 1257 { 1258 smb_odir_t *od, *next_od; 1259 1260 ASSERT(tree); 1261 ASSERT(tree->t_magic == SMB_TREE_MAGIC); 1262 1263 od = smb_tree_get_odir(tree, NULL); 1264 while (od) { 1265 ASSERT(od->d_magic == SMB_ODIR_MAGIC); 1266 ASSERT(od->d_tree == tree); 1267 1268 next_od = smb_tree_get_odir(tree, od); 1269 if ((pid == 0) || (od->d_opened_by_pid == pid)) 1270 smb_odir_close(od); 1271 smb_odir_release(od); 1272 1273 od = next_od; 1274 } 1275 } 1276 1277 static void 1278 smb_tree_set_execsub_info(smb_tree_t *tree, smb_execsub_info_t *subs) 1279 { 1280 subs->e_winname = tree->t_user->u_name; 1281 subs->e_userdom = tree->t_user->u_domain; 1282 subs->e_srv_ipaddr = tree->t_session->local_ipaddr; 1283 subs->e_cli_ipaddr = tree->t_session->ipaddr; 1284 subs->e_cli_netbiosname = tree->t_session->workstation; 1285 subs->e_uid = crgetuid(tree->t_user->u_cred); 1286 } 1287 1288 /* 1289 * Private function to support smb_tree_enum. 1290 */ 1291 static int 1292 smb_tree_enum_private(smb_tree_t *tree, smb_svcenum_t *svcenum) 1293 { 1294 uint8_t *pb; 1295 uint_t nbytes; 1296 int rc; 1297 1298 if (svcenum->se_nskip > 0) { 1299 svcenum->se_nskip--; 1300 return (0); 1301 } 1302 1303 if (svcenum->se_nitems >= svcenum->se_nlimit) { 1304 svcenum->se_nitems = svcenum->se_nlimit; 1305 return (0); 1306 } 1307 1308 pb = &svcenum->se_buf[svcenum->se_bused]; 1309 rc = smb_tree_netinfo_encode(tree, pb, svcenum->se_bavail, &nbytes); 1310 if (rc == 0) { 1311 svcenum->se_bavail -= nbytes; 1312 svcenum->se_bused += nbytes; 1313 svcenum->se_nitems++; 1314 } 1315 1316 return (rc); 1317 } 1318 1319 /* 1320 * Encode connection information into a buffer: connection information 1321 * needed in user space to support RPC requests. 1322 */ 1323 static int 1324 smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen, 1325 uint32_t *nbytes) 1326 { 1327 smb_netconnectinfo_t info; 1328 int rc; 1329 1330 smb_tree_netinfo_init(tree, &info); 1331 rc = smb_netconnectinfo_encode(&info, buf, buflen, nbytes); 1332 smb_tree_netinfo_fini(&info); 1333 1334 return (rc); 1335 } 1336 1337 /* 1338 * Note: ci_numusers should be the number of users connected to 1339 * the share rather than the number of references on the tree but 1340 * we don't have a mechanism to track users/share in smbsrv yet. 1341 */ 1342 static void 1343 smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info) 1344 { 1345 smb_user_t *user; 1346 1347 ASSERT(tree); 1348 1349 info->ci_id = tree->t_tid; 1350 info->ci_type = tree->t_res_type; 1351 info->ci_numopens = tree->t_open_files; 1352 info->ci_numusers = tree->t_refcnt; 1353 info->ci_time = gethrestime_sec() - tree->t_connect_time; 1354 1355 info->ci_sharelen = strlen(tree->t_sharename) + 1; 1356 info->ci_share = smb_strdup(tree->t_sharename); 1357 1358 user = tree->t_user; 1359 ASSERT(user); 1360 1361 info->ci_namelen = user->u_domain_len + user->u_name_len + 2; 1362 info->ci_username = kmem_alloc(info->ci_namelen, KM_SLEEP); 1363 (void) snprintf(info->ci_username, info->ci_namelen, "%s\\%s", 1364 user->u_domain, user->u_name); 1365 } 1366 1367 static void 1368 smb_tree_netinfo_fini(smb_netconnectinfo_t *info) 1369 { 1370 if (info == NULL) 1371 return; 1372 1373 if (info->ci_username) 1374 kmem_free(info->ci_username, info->ci_namelen); 1375 if (info->ci_share) 1376 smb_mfree(info->ci_share); 1377 1378 bzero(info, sizeof (smb_netconnectinfo_t)); 1379 } 1380