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