Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-2807 Restoring previous versions from snapshots doesn't work with nested folders.
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
SMB-136 Snapshots not visible in Windows previous versions
SMB-65 SMB server in non-global zones (use zone_kcred())
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_vss.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_vss.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * Volume Copy Shadow Services (VSS) provides a way for users to
  28   28   * restore/recover deleted files/directories.
  29   29   * For the server to support VSS for Microsoft clients, there is
  30   30   * two basic functions that need to be implemented.
  31   31   * The first is to intercept the NT_TRANSACT_IOCTL command with
  32   32   * the function code of FSCTL_SRV_ENUMERATE_SNAPSHOTS (0x00144064).
  33   33   * This is to report the count or the count and list of snapshots
  34   34   * for that share.
  35   35   * The second function need to trap commands with the
  36   36   * SMB_FLAGS2_REPARSE_PATH bit set in the smb header.  This bit
  37   37   * means that there is a @GMT token in path that needs to be
  38   38   * processed.  The @GMT token means to process this command, but
  39   39   * in the snapshot.
  40   40   */
  41   41  
  42   42  #include <smbsrv/smb_kproto.h>
  43   43  #include <smbsrv/string.h>
  44      -#include <smbsrv/winioctl.h>
       44 +#include <smb/winioctl.h>
  45   45  #include <smbsrv/smb_door.h>
  46   46  
  47   47  /* Size of the token on the wire due to encoding */
  48   48  #define SMB_VSS_GMT_NET_SIZE(sr) (smb_ascii_or_unicode_null_len(sr) * \
  49   49      SMB_VSS_GMT_SIZE)
  50   50  
  51   51  #define SMB_VSS_COUNT_SIZE 16
  52   52  
  53   53  static boolean_t smb_vss_is_gmttoken(const char *);
  54   54  static const char *smb_vss_find_gmttoken(const char *);
↓ open down ↓ 16 lines elided ↑ open up ↑
  71   71   * SMB_VSS_COUNT_SIZE, then all that is requested is the count, otherwise
  72   72   * return the count and the list of @GMT tokens (one token for each
  73   73   * snapshot).
  74   74   */
  75   75  uint32_t
  76   76  smb_vss_enum_snapshots(smb_request_t *sr, smb_fsctl_t *fsctl)
  77   77  {
  78   78          uint32_t count = 0;
  79   79          char *root_path;
  80   80          uint32_t status = NT_STATUS_SUCCESS;
  81      -        smb_node_t *tnode;
  82   81          smb_gmttoken_response_t snaps;
  83   82  
  84      -        ASSERT(sr->tid_tree);
  85      -        ASSERT(sr->tid_tree->t_snode);
       83 +        ASSERT(sr->fid_ofile);
       84 +        ASSERT(sr->fid_ofile->f_node);
  86   85  
  87   86          if (fsctl->MaxOutputResp < SMB_VSS_COUNT_SIZE)
  88   87                  return (NT_STATUS_INVALID_PARAMETER);
  89   88  
  90      -        tnode = sr->tid_tree->t_snode;
       89 +        /*
       90 +         * smbd will find the root of the lowest filesystem from mntpath of a
       91 +         * file by comparing it agaisnt mnttab, repeatedly removing components
       92 +         * until one matches.
       93 +         */
  91   94          root_path  = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
  92      -        if (smb_node_getmntpath(tnode, root_path, MAXPATHLEN) != 0)
       95 +        if (smb_node_getmntpath(sr->fid_ofile->f_node, root_path,
       96 +            MAXPATHLEN) != 0)
  93   97                  return (NT_STATUS_INVALID_PARAMETER);
  94   98  
  95   99          if (fsctl->MaxOutputResp == SMB_VSS_COUNT_SIZE) {
  96  100                  count = smb_vss_get_count(sr->tid_tree, root_path);
  97  101                  if (smb_mbc_encodef(fsctl->out_mbc, "lllw", count, 0,
  98  102                      (count * SMB_VSS_GMT_NET_SIZE(sr) +
  99  103                      smb_ascii_or_unicode_null_len(sr)), 0) != 0) {
 100  104                          status = NT_STATUS_INVALID_PARAMETER;
 101  105                  }
 102  106          } else {
↓ open down ↓ 8 lines elided ↑ open up ↑
 111  115          }
 112  116  
 113  117          kmem_free(root_path, MAXPATHLEN);
 114  118          return (status);
 115  119  }
 116  120  
 117  121  /*
 118  122   * sr - the request info, used to find root of dataset,
 119  123   *      unicode or ascii, where the share is rooted in the
 120  124   *      dataset
 121      - * root_node - root of the share
 122  125   * cur_node - where in the share for the command
 123      - * buf - is the path for the command to be processed
 124      - *       returned without @GMT if processed
 125  126   * vss_cur_node - returned value for the snapshot version
 126  127   *                of the cur_node
 127      - * vss_root_node - returned value for the snapshot version
 128      - *                 of the root_node
      128 + * gmttoken - if SMB1, the gmttoken to be used to find the snapshot.
      129 + *            Otherwise, NULL.
 129  130   *
 130  131   * This routine is the processing for handling the
 131  132   * SMB_FLAGS2_REPARSE_PATH bit being set in the smb header.
 132  133   *
 133  134   * By using the cur_node passed in, a new node is found or
 134  135   * created that is the same place in the directory tree, but
 135      - * in the snapshot. We also use root_node to do the same for
 136      - * the root.
 137      - * Once the new smb node is found, the path is modified by
 138      - * removing the @GMT token from the path in the buf.
      136 + * in the snapshot.
 139  137   */
 140  138  int
 141      -smb_vss_lookup_nodes(smb_request_t *sr, smb_node_t *root_node,
 142      -    smb_node_t *cur_node, char *buf, smb_node_t **vss_cur_node,
 143      -    smb_node_t **vss_root_node)
      139 +smb_vss_lookup_nodes(smb_request_t *sr, smb_node_t *cur_node,
      140 +    smb_node_t **vss_cur_node, char *gmttoken)
 144  141  {
 145  142          smb_arg_open_t  *op = &sr->arg.open;
 146      -        smb_node_t      *tnode;
 147  143          char            *snapname, *path;
 148      -        char            *gmttoken;
 149      -        char            gmttok_buf[SMB_VSS_GMT_SIZE];
 150  144          vnode_t         *fsrootvp = NULL;
 151  145          time_t          toktime;
 152  146          int             err = 0;
 153      -        boolean_t       smb1;
 154  147  
 155  148          if (sr->tid_tree == NULL)
 156  149                  return (ESTALE);
 157  150  
 158      -        tnode = sr->tid_tree->t_snode;
 159      -
 160      -        ASSERT(tnode);
 161      -        ASSERT(tnode->vp);
 162      -        ASSERT(tnode->vp->v_vfsp);
 163      -
 164      -        smb1 = (sr->session->dialect < SMB_VERS_2_BASE);
 165      -        if (smb1) {
 166      -                const char *p;
 167      -
 168      -                /* get gmttoken from buf */
 169      -                if ((p = smb_vss_find_gmttoken(buf)) == NULL)
 170      -                        return (ENOENT);
 171      -
 172      -                bcopy(p, gmttok_buf, SMB_VSS_GMT_SIZE);
 173      -                gmttok_buf[SMB_VSS_GMT_SIZE - 1] = '\0';
 174      -                gmttoken = gmttok_buf;
      151 +        if (gmttoken != NULL) {
 175  152                  toktime = 0;
 176  153          } else {
 177  154                  /* SMB2 and later */
 178      -                gmttoken = NULL;
 179  155                  toktime = op->timewarp.tv_sec;
 180  156          }
 181  157  
 182  158          path = smb_srm_alloc(sr, MAXPATHLEN);
 183  159          snapname = smb_srm_alloc(sr, MAXPATHLEN);
 184  160  
 185      -        err = smb_node_getmntpath(tnode, path, MAXPATHLEN);
      161 +        err = smb_node_getmntpath(cur_node, path, MAXPATHLEN);
 186  162          if (err != 0)
 187  163                  return (err);
 188  164  
 189  165          /*
 190  166           * Find the corresponding snapshot name.  If snapname is
 191  167           * empty after the map call, no such snapshot was found.
 192  168           */
 193  169          *snapname = '\0';
 194  170          smb_vss_map_gmttoken(sr->tid_tree, path, gmttoken, toktime,
 195  171              snapname);
 196  172          if (*snapname == '\0')
 197  173                  return (ENOENT);
 198  174  
 199  175          /* find snapshot nodes */
 200      -        err = VFS_ROOT(tnode->vp->v_vfsp, &fsrootvp);
      176 +        err = VFS_ROOT(cur_node->vp->v_vfsp, &fsrootvp);
 201  177          if (err != 0)
 202  178                  return (err);
 203  179  
 204      -        /* find snapshot node corresponding to root_node */
 205      -        err = smb_vss_lookup_node(sr, root_node, fsrootvp,
 206      -            snapname, cur_node, vss_root_node);
 207      -        if (err == 0) {
 208      -                /* find snapshot node corresponding to cur_node */
 209      -                err = smb_vss_lookup_node(sr, cur_node, fsrootvp,
 210      -                    snapname, cur_node, vss_cur_node);
 211      -                if (err != 0)
 212      -                        smb_node_release(*vss_root_node);
 213      -        }
      180 +        /* find snapshot node corresponding to cur_node */
      181 +        err = smb_vss_lookup_node(sr, cur_node, fsrootvp,
      182 +            snapname, cur_node, vss_cur_node);
 214  183  
 215  184          VN_RELE(fsrootvp);
 216  185  
 217      -        if (smb1)
 218      -                smb_vss_remove_first_token_from_path(buf);
 219      -
 220  186          return (err);
 221  187  }
 222  188  
 223  189  /*
 224  190   * Find snapshot node corresponding to 'node', and return it in
 225  191   * 'vss_node', as follows:
 226  192   * - find the path from fsrootvp to node, appending it to the
 227  193   *   the snapshot path
 228  194   * - lookup the vnode and smb_node (vss_node).
 229  195   */
↓ open down ↓ 189 lines elided ↑ open up ↑
 419  385          xdr_free(smb_gmttoken_response_xdr, (char *)reply);
 420  386  }
 421  387  
 422  388  /*
 423  389   * Returns the snapshot name for the @GMT token provided for the dataset
 424  390   * of the path.  If the snapshot cannot be found, a string with a NULL
 425  391   * is returned.
 426  392   */
 427  393  static void
 428  394  smb_vss_map_gmttoken(smb_tree_t *tree, char *path, char *gmttoken,
 429      -        time_t toktime, char *snapname)
      395 +    time_t toktime, char *snapname)
 430  396  {
 431  397          smb_gmttoken_snapname_t request;
 432  398          smb_string_t            result;
 433  399  
 434  400          bzero(&result, sizeof (smb_string_t));
 435  401          result.buf = snapname;
 436  402  
 437  403          request.gts_path = path;
 438  404          request.gts_gmttoken = gmttoken;
 439  405          request.gts_toktime = toktime;
 440  406  
 441  407          (void) smb_kdoor_upcall(tree->t_server, SMB_DR_VSS_MAP_GMTTOKEN,
 442  408              &request, smb_gmttoken_snapname_xdr,
 443  409              &result, smb_string_xdr);
      410 +}
      411 +
      412 +int
      413 +smb_vss_extract_gmttoken(char *buf, char *gmttoken)
      414 +{
      415 +        const char *p;
      416 +
      417 +        /* get gmttoken from buf */
      418 +        if ((p = smb_vss_find_gmttoken(buf)) == NULL)
      419 +                return (ENOENT);
      420 +
      421 +        bcopy(p, gmttoken, SMB_VSS_GMT_SIZE);
      422 +        gmttoken[SMB_VSS_GMT_SIZE - 1] = '\0';
      423 +
      424 +        smb_vss_remove_first_token_from_path(buf);
      425 +
      426 +        return (0);
 444  427  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX