Print this page
    
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-4797 MS-Office crash while saving a file on a Nexenta smb share
Revert "NEX-4324 Should not include $DATA when enumerating streams"
This reverts commits c72f3674cf6d0db6a44cd40c1ed626e79f20a537
and 2db2cee12b7a06b6651924ff35cf8bfc42a3b32f.
NEX-4324 Should not include $DATA when enumerating streams (lint)
NEX-4324 Should not include $DATA when enumerating streams
Reviewed by: Daniel Borek <daniel.borek@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
re #14152 Race between ipmi_submit_driver_request() and kcs_loop() (sync with illumos fix 3902)
SMB-46 File handle leaks exposed by mtime fixes (rm 7815)
re #7815 SMB server delivers old modification time...
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  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  /*
  23   23   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  25   25   */
  26   26  
  27   27  #include <smbsrv/smb_kproto.h>
  28   28  #include <smbsrv/smb_vops.h>
  29   29  #include <smbsrv/smb_fsops.h>
  30   30  
  31   31  /*
  32   32   * Trans2 Query File/Path Information Levels:
  33   33   *
  34   34   * SMB_INFO_STANDARD
  35   35   * SMB_INFO_QUERY_EA_SIZE
  36   36   * SMB_INFO_QUERY_EAS_FROM_LIST
  37   37   * SMB_INFO_QUERY_ALL_EAS - not valid for pipes
  38   38   * SMB_INFO_IS_NAME_VALID - only valid when query is by path
  39   39   *
  40   40   * SMB_QUERY_FILE_BASIC_INFO
  41   41   * SMB_QUERY_FILE_STANDARD_INFO
  42   42   * SMB_QUERY_FILE_EA_INFO
  43   43   * SMB_QUERY_FILE_NAME_INFO
  44   44   * SMB_QUERY_FILE_ALL_INFO
  45   45   * SMB_QUERY_FILE_ALT_NAME_INFO - not valid for pipes
  46   46   * SMB_QUERY_FILE_STREAM_INFO - not valid for pipes
  47   47   * SMB_QUERY_FILE_COMPRESSION_INFO - not valid for pipes
  48   48   *
  49   49   * Supported Passthrough levels:
  50   50   * SMB_FILE_BASIC_INFORMATION
  51   51   * SMB_FILE_STANDARD_INFORMATION
  52   52   * SMB_FILE_INTERNAL_INFORMATION
  53   53   * SMB_FILE_EA_INFORMATION
  54   54   * SMB_FILE_ACCESS_INFORMATION - not yet supported when query by path
  55   55   * SMB_FILE_NAME_INFORMATION
  56   56   * SMB_FILE_ALL_INFORMATION
  57   57   * SMB_FILE_ALT_NAME_INFORMATION - not valid for pipes
  58   58   * SMB_FILE_STREAM_INFORMATION - not valid for pipes
  59   59   * SMB_FILE_COMPRESSION_INFORMATION - not valid for pipes
  60   60   * SMB_FILE_NETWORK_OPEN_INFORMATION - not valid for pipes
  61   61   * SMB_FILE_ATTR_TAG_INFORMATION - not valid for pipes
  62   62   *
  63   63   * Internal levels representing non trans2 requests
  64   64   * SMB_QUERY_INFORMATION
  65   65   * SMB_QUERY_INFORMATION2
  66   66   */
  67   67  
  68   68  /*
  69   69   * SMB_STREAM_ENCODE_FIXED_SIZE:
  70   70   * 2 dwords + 2 quadwords => 4 + 4 + 8 + 8 => 24
  71   71   */
  72   72  #define SMB_STREAM_ENCODE_FIXED_SZ      24
  73   73  
  74   74  /* See smb_queryinfo_t in smb_ktypes.h */
  75   75  #define qi_mtime        qi_attr.sa_vattr.va_mtime
  76   76  #define qi_ctime        qi_attr.sa_vattr.va_ctime
  77   77  #define qi_atime        qi_attr.sa_vattr.va_atime
  78   78  #define qi_crtime       qi_attr.sa_crtime
  79   79  
  80   80  static int smb_query_by_fid(smb_request_t *, smb_xa_t *, uint16_t);
  81   81  static int smb_query_by_path(smb_request_t *, smb_xa_t *, uint16_t);
  82   82  
  83   83  static int smb_query_fileinfo(smb_request_t *, smb_node_t *,
  84   84      uint16_t, smb_queryinfo_t *);
  85   85  static int smb_query_pipeinfo(smb_request_t *, smb_opipe_t *,
  86   86      uint16_t, smb_queryinfo_t *);
  87   87  static boolean_t smb_query_pipe_valid_infolev(smb_request_t *, uint16_t);
  88   88  
  89   89  static int smb_query_encode_response(smb_request_t *, smb_xa_t *,
  90   90      uint16_t, smb_queryinfo_t *);
  91   91  static boolean_t smb_stream_fits(smb_request_t *, mbuf_chain_t *,
  92   92      char *, uint32_t);
  93   93  static int smb_query_pathname(smb_request_t *, smb_node_t *, boolean_t,
  94   94      smb_queryinfo_t *);
  95   95  
  96   96  int smb_query_passthru;
  97   97  
  98   98  /*
  99   99   * smb_com_trans2_query_file_information
 100  100   */
 101  101  smb_sdrc_t
 102  102  smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa)
 103  103  {
 104  104          uint16_t infolev;
 105  105  
 106  106          if (smb_mbc_decodef(&xa->req_param_mb, "ww",
 107  107              &sr->smb_fid, &infolev) != 0)
 108  108                  return (SDRC_ERROR);
 109  109  
 110  110          if (smb_query_by_fid(sr, xa, infolev) != 0)
 111  111                  return (SDRC_ERROR);
 112  112  
 113  113          return (SDRC_SUCCESS);
 114  114  }
 115  115  
 116  116  /*
 117  117   * smb_com_trans2_query_path_information
 118  118   */
 119  119  smb_sdrc_t
 120  120  smb_com_trans2_query_path_information(smb_request_t *sr, smb_xa_t *xa)
 121  121  {
 122  122          uint16_t        infolev;
 123  123          smb_fqi_t       *fqi = &sr->arg.dirop.fqi;
 124  124  
 125  125          if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
 126  126                  smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
 127  127                      ERRDOS, ERROR_INVALID_FUNCTION);
 128  128                  return (SDRC_ERROR);
 129  129          }
 130  130  
 131  131          if (smb_mbc_decodef(&xa->req_param_mb, "%w4.u",
 132  132              sr, &infolev, &fqi->fq_path.pn_path) != 0)
 133  133                  return (SDRC_ERROR);
 134  134  
 135  135          if (smb_query_by_path(sr, xa, infolev) != 0)
 136  136                  return (SDRC_ERROR);
 137  137  
 138  138          return (SDRC_SUCCESS);
 139  139  }
 140  140  
 141  141  /*
  
    | 
      ↓ open down ↓ | 
    107 lines elided | 
    
      ↑ open up ↑ | 
  
 142  142   * smb_com_query_information (aka getattr)
 143  143   */
 144  144  smb_sdrc_t
 145  145  smb_pre_query_information(smb_request_t *sr)
 146  146  {
 147  147          int rc;
 148  148          smb_fqi_t *fqi = &sr->arg.dirop.fqi;
 149  149  
 150  150          rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);
 151  151  
 152      -        DTRACE_SMB_2(op__QueryInformation__start, smb_request_t *, sr,
 153      -            smb_fqi_t *, fqi);
      152 +        DTRACE_SMB_START(op__QueryInformation, smb_request_t *, sr);
 154  153  
 155  154          return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 156  155  }
 157  156  
 158  157  void
 159  158  smb_post_query_information(smb_request_t *sr)
 160  159  {
 161      -        DTRACE_SMB_1(op__QueryInformation__done, smb_request_t *, sr);
      160 +        DTRACE_SMB_DONE(op__QueryInformation, smb_request_t *, sr);
 162  161  }
 163  162  
 164  163  smb_sdrc_t
 165  164  smb_com_query_information(smb_request_t *sr)
 166  165  {
 167  166          uint16_t infolev = SMB_QUERY_INFORMATION;
 168  167  
 169  168          if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
 170  169                  smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 171  170                      ERRDOS, ERROR_ACCESS_DENIED);
 172  171                  return (SDRC_ERROR);
 173  172          }
 174  173  
 175  174          if (smb_query_by_path(sr, NULL, infolev) != 0)
 176  175                  return (SDRC_ERROR);
 177  176  
 178  177          return (SDRC_SUCCESS);
 179  178  }
  
    | 
      ↓ open down ↓ | 
    8 lines elided | 
    
      ↑ open up ↑ | 
  
 180  179  
 181  180  /*
 182  181   * smb_com_query_information2 (aka getattre)
 183  182   */
 184  183  smb_sdrc_t
 185  184  smb_pre_query_information2(smb_request_t *sr)
 186  185  {
 187  186          int rc;
 188  187          rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
 189  188  
 190      -        DTRACE_SMB_1(op__QueryInformation2__start, smb_request_t *, sr);
      189 +        DTRACE_SMB_START(op__QueryInformation2, smb_request_t *, sr);
 191  190  
 192  191          return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 193  192  }
 194  193  
 195  194  void
 196  195  smb_post_query_information2(smb_request_t *sr)
 197  196  {
 198      -        DTRACE_SMB_1(op__QueryInformation2__done, smb_request_t *, sr);
      197 +        DTRACE_SMB_DONE(op__QueryInformation2, smb_request_t *, sr);
 199  198  }
 200  199  
 201  200  smb_sdrc_t
 202  201  smb_com_query_information2(smb_request_t *sr)
 203  202  {
 204  203          uint16_t infolev = SMB_QUERY_INFORMATION2;
 205  204  
 206  205          if (smb_query_by_fid(sr, NULL, infolev) != 0)
 207  206                  return (SDRC_ERROR);
 208  207  
 209  208          return (SDRC_SUCCESS);
 210  209  }
 211  210  
 212  211  /*
 213  212   * smb_query_by_fid
 214  213   *
 215  214   * Common code for querying file information by open file (or pipe) id.
 216  215   * Use the id to identify the node / pipe object and request the
 217  216   * smb_queryinfo_t data for that object.
 218  217   */
 219  218  static int
 220  219  smb_query_by_fid(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
 221  220  {
 222  221          int             rc;
 223  222          smb_queryinfo_t *qinfo;
 224  223          smb_node_t      *node;
 225  224          smb_opipe_t     *opipe;
 226  225  
 227  226          smbsr_lookup_file(sr);
 228  227  
 229  228          if (sr->fid_ofile == NULL) {
 230  229                  smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 231  230                  return (-1);
 232  231          }
 233  232  
 234  233          if (infolev == SMB_INFO_IS_NAME_VALID) {
 235  234                  smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
 236  235                  smbsr_release_file(sr);
 237  236                  return (-1);
 238  237          }
 239  238  
 240  239          if ((sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE) &&
 241  240              (!smb_query_pipe_valid_infolev(sr, infolev))) {
 242  241                  smbsr_release_file(sr);
 243  242                  return (-1);
 244  243          }
 245  244  
 246  245          sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
 247  246          qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
 248  247  
 249  248          switch (sr->fid_ofile->f_ftype) {
 250  249          case SMB_FTYPE_DISK:
 251  250                  node = sr->fid_ofile->f_node;
 252  251                  rc = smb_query_fileinfo(sr, node, infolev, qinfo);
 253  252                  break;
 254  253          case SMB_FTYPE_MESG_PIPE:
 255  254                  opipe = sr->fid_ofile->f_pipe;
 256  255                  rc = smb_query_pipeinfo(sr, opipe, infolev, qinfo);
 257  256                  break;
 258  257          default:
 259  258                  smbsr_error(sr, 0, ERRDOS, ERRbadfile);
 260  259                  rc = -1;
 261  260                  break;
 262  261          }
 263  262  
 264  263          if (rc == 0)
 265  264                  rc = smb_query_encode_response(sr, xa, infolev, qinfo);
 266  265  
 267  266          kmem_free(qinfo, sizeof (smb_queryinfo_t));
 268  267          smbsr_release_file(sr);
 269  268          return (rc);
 270  269  }
 271  270  
 272  271  /*
 273  272   * smb_query_by_path
 274  273   *
 275  274   * Common code for querying file information by file name.
 276  275   * Use the file name to identify the node object and request the
 277  276   * smb_queryinfo_t data for that node.
 278  277   *
 279  278   * Path should be set in sr->arg.dirop.fqi.fq_path prior to
 280  279   * calling smb_query_by_path.
 281  280   *
 282  281   * Querying attributes on a named pipe by name is an error and
 283  282   * is handled in the calling functions so that they can return
 284  283   * the appropriate error status code (which differs by caller).
 285  284   */
 286  285  static int
 287  286  smb_query_by_path(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
 288  287  {
 289  288          smb_queryinfo_t *qinfo;
 290  289          smb_node_t      *node, *dnode;
 291  290          smb_pathname_t  *pn;
 292  291          int             rc;
 293  292  
 294  293          /*
 295  294           * The function smb_query_fileinfo is used here and in
 296  295           * smb_query_by_fid.  That common function needs this
 297  296           * one to call it with a NULL fid_ofile, so check here.
 298  297           * Note: smb_query_by_fid enforces the opposite.
 299  298           *
 300  299           * In theory we could ASSERT this, but whether we have
 301  300           * fid_ofile set here depends on what sequence of SMB
 302  301           * commands the client has sent in this message, so
 303  302           * let's be cautious and handle it as an error.
 304  303           */
 305  304          if (sr->fid_ofile != NULL)
 306  305                  return (-1);
 307  306  
 308  307  
 309  308          /* VALID, but not yet supported */
 310  309          if (infolev == SMB_FILE_ACCESS_INFORMATION) {
 311  310                  smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
 312  311                  return (-1);
 313  312          }
 314  313  
 315  314          pn = &sr->arg.dirop.fqi.fq_path;
 316  315          smb_pathname_init(sr, pn, pn->pn_path);
 317  316          if (!smb_pathname_validate(sr, pn))
 318  317                  return (-1);
 319  318  
 320  319          qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
 321  320  
 322  321          rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
  
    | 
      ↓ open down ↓ | 
    114 lines elided | 
    
      ↑ open up ↑ | 
  
 323  322              sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode,
 324  323              qinfo->qi_name);
 325  324  
 326  325          if (rc == 0) {
 327  326                  rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS,
 328  327                      sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node);
 329  328                  smb_node_release(dnode);
 330  329          }
 331  330  
 332  331          if (rc != 0) {
 333      -                if (rc == ENOENT)
 334      -                        smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
 335      -                            ERRDOS, ERROR_FILE_NOT_FOUND);
 336      -                else
 337      -                        smbsr_errno(sr, rc);
      332 +                smbsr_errno(sr, rc);
 338  333  
 339  334                  kmem_free(qinfo, sizeof (smb_queryinfo_t));
 340  335                  return (-1);
 341  336          }
 342  337  
 343  338          if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
 344  339                  smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
 345  340                  kmem_free(qinfo, sizeof (smb_queryinfo_t));
 346  341                  smb_node_release(node);
 347  342                  return (-1);
 348  343          }
 349  344  
 350  345          rc = smb_query_fileinfo(sr, node, infolev, qinfo);
 351  346          if (rc != 0) {
 352  347                  kmem_free(qinfo, sizeof (smb_queryinfo_t));
 353  348                  smb_node_release(node);
 354  349                  return (rc);
 355  350          }
 356  351  
 357  352          /* If delete_on_close - NT_STATUS_DELETE_PENDING */
 358  353          if (qinfo->qi_delete_on_close) {
 359  354                  smbsr_error(sr, NT_STATUS_DELETE_PENDING,
 360  355                      ERRDOS, ERROR_ACCESS_DENIED);
 361  356                  kmem_free(qinfo, sizeof (smb_queryinfo_t));
 362  357                  smb_node_release(node);
 363  358                  return (-1);
 364  359          }
 365  360  
 366  361          rc = smb_query_encode_response(sr, xa, infolev, qinfo);
 367  362          kmem_free(qinfo, sizeof (smb_queryinfo_t));
 368  363          smb_node_release(node);
 369  364          return (rc);
 370  365  }
 371  366  
 372  367  /*
 373  368   * smb_size32
 374  369   * Some responses only support 32 bit file sizes. If the file size
 375  370   * exceeds UINT_MAX (32 bit) we return UINT_MAX in the response.
 376  371   */
 377  372  static uint32_t
 378  373  smb_size32(u_offset_t size)
 379  374  {
 380  375          return ((size > UINT_MAX) ? UINT_MAX : (uint32_t)size);
 381  376  }
 382  377  
 383  378  /*
 384  379   * smb_query_encode_response
 385  380   *
 386  381   * Encode the data from smb_queryinfo_t into client response
 387  382   */
 388  383  int
 389  384  smb_query_encode_response(smb_request_t *sr, smb_xa_t *xa,
 390  385      uint16_t infolev, smb_queryinfo_t *qinfo)
 391  386  {
 392  387          uint16_t dattr;
 393  388          u_offset_t datasz, allocsz;
 394  389          uint32_t status;
 395  390  
 396  391          dattr = qinfo->qi_attr.sa_dosattr & FILE_ATTRIBUTE_MASK;
 397  392          datasz = qinfo->qi_attr.sa_vattr.va_size;
 398  393          allocsz = qinfo->qi_attr.sa_allocsz;
 399  394  
 400  395          switch (infolev) {
 401  396          case SMB_QUERY_INFORMATION:
 402  397                  (void) smbsr_encode_result(sr, 10, 0, "bwll10.w",
 403  398                      10,
 404  399                      dattr,
 405  400                      smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
 406  401                      smb_size32(datasz),
 407  402                      0);
 408  403                  break;
 409  404  
 410  405          case SMB_QUERY_INFORMATION2:
 411  406                  (void) smbsr_encode_result(sr, 11, 0, "byyyllww",
 412  407                      11,
 413  408                      smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
 414  409                      smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
 415  410                      smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
 416  411                      smb_size32(datasz), smb_size32(allocsz), dattr, 0);
 417  412          break;
 418  413  
 419  414          case SMB_FILE_ACCESS_INFORMATION:
 420  415                  ASSERT(sr->fid_ofile);
 421  416                  (void) smb_mbc_encodef(&xa->rep_data_mb, "l",
 422  417                      sr->fid_ofile->f_granted_access);
 423  418                  break;
 424  419  
 425  420          case SMB_INFO_STANDARD:
 426  421                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 427  422                  (void) smb_mbc_encodef(&xa->rep_data_mb,
 428  423                      ((sr->session->native_os == NATIVE_OS_WIN95) ?
 429  424                      "YYYllw" : "yyyllw"),
 430  425                      smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
 431  426                      smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
 432  427                      smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
 433  428                      smb_size32(datasz), smb_size32(allocsz), dattr);
 434  429                  break;
 435  430  
 436  431          case SMB_INFO_QUERY_EA_SIZE:
 437  432                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 438  433                  (void) smb_mbc_encodef(&xa->rep_data_mb,
 439  434                      ((sr->session->native_os == NATIVE_OS_WIN95) ?
 440  435                      "YYYllwl" : "yyyllwl"),
 441  436                      smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
 442  437                      smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
 443  438                      smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
 444  439                      smb_size32(datasz), smb_size32(allocsz), dattr, 0);
 445  440                  break;
 446  441  
 447  442          case SMB_INFO_QUERY_ALL_EAS:
 448  443          case SMB_INFO_QUERY_EAS_FROM_LIST:
 449  444                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 450  445                  (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
 451  446                  break;
 452  447  
 453  448          case SMB_INFO_IS_NAME_VALID:
 454  449                  break;
 455  450  
 456  451          case SMB_QUERY_FILE_BASIC_INFO:
 457  452          case SMB_FILE_BASIC_INFORMATION:
 458  453                  /*
 459  454                   * NT includes 6 bytes (spec says 4) at the end of this
 460  455                   * response, which are required by NetBench 5.01.
 461  456                   */
 462  457                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 463  458                  (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.",
 464  459                      &qinfo->qi_crtime,
 465  460                      &qinfo->qi_atime,
 466  461                      &qinfo->qi_mtime,
 467  462                      &qinfo->qi_ctime,
 468  463                      dattr);
 469  464                  break;
 470  465  
 471  466          case SMB_QUERY_FILE_STANDARD_INFO:
 472  467          case SMB_FILE_STANDARD_INFORMATION:
 473  468                  /* 2-byte pad at end */
 474  469                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 475  470                  (void) smb_mbc_encodef(&xa->rep_data_mb, "qqlbb2.",
 476  471                      (uint64_t)allocsz,
 477  472                      (uint64_t)datasz,
 478  473                      qinfo->qi_attr.sa_vattr.va_nlink,
 479  474                      qinfo->qi_delete_on_close,
 480  475                      qinfo->qi_isdir);
 481  476                  break;
 482  477  
 483  478          case SMB_QUERY_FILE_EA_INFO:
 484  479          case SMB_FILE_EA_INFORMATION:
 485  480                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 486  481                  (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
 487  482                  break;
 488  483  
 489  484          case SMB_QUERY_FILE_NAME_INFO:
 490  485          case SMB_FILE_NAME_INFORMATION:
 491  486                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 492  487                  (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", sr,
 493  488                      qinfo->qi_namelen, qinfo->qi_name);
 494  489                  break;
 495  490  
 496  491          case SMB_QUERY_FILE_ALL_INFO:
 497  492          case SMB_FILE_ALL_INFORMATION:
 498  493                  /*
 499  494                   * There is a 6-byte pad between Attributes and AllocationSize,
 500  495                   * and a 2-byte pad after the Directory field.
 501  496                   */
 502  497                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 503  498                  (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.qqlbb2.l",
 504  499                      &qinfo->qi_crtime,
 505  500                      &qinfo->qi_atime,
 506  501                      &qinfo->qi_mtime,
 507  502                      &qinfo->qi_ctime,
 508  503                      dattr,
 509  504                      (uint64_t)allocsz,
 510  505                      (uint64_t)datasz,
 511  506                      qinfo->qi_attr.sa_vattr.va_nlink,
 512  507                      qinfo->qi_delete_on_close,
 513  508                      qinfo->qi_isdir,
 514  509                      0);
 515  510  
 516  511                  (void) smb_mbc_encodef(&xa->rep_data_mb, "%lu",
 517  512                      sr, qinfo->qi_namelen, qinfo->qi_name);
 518  513                  break;
 519  514  
 520  515          case SMB_QUERY_FILE_ALT_NAME_INFO:
 521  516          case SMB_FILE_ALT_NAME_INFORMATION:
 522  517                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 523  518                  (void) smb_mbc_encodef(&xa->rep_data_mb, "%lU", sr,
 524  519                      smb_wcequiv_strlen(qinfo->qi_shortname),
 525  520                      qinfo->qi_shortname);
 526  521                  break;
 527  522  
 528  523          case SMB_QUERY_FILE_STREAM_INFO:
 529  524          case SMB_FILE_STREAM_INFORMATION:
 530  525                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 531  526                  status = smb_query_stream_info(sr, &xa->rep_data_mb, qinfo);
 532  527                  if (status)
 533  528                          smbsr_status(sr, status, 0, 0);
 534  529                  break;
 535  530  
 536  531          case SMB_QUERY_FILE_COMPRESSION_INFO:
 537  532          case SMB_FILE_COMPRESSION_INFORMATION:
 538  533                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 539  534                  (void) smb_mbc_encodef(&xa->rep_data_mb, "qwbbb3.",
 540  535                      datasz, 0, 0, 0, 0);
 541  536                  break;
 542  537  
 543  538          case SMB_FILE_INTERNAL_INFORMATION:
 544  539                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 545  540                  (void) smb_mbc_encodef(&xa->rep_data_mb, "q",
 546  541                      qinfo->qi_attr.sa_vattr.va_nodeid);
 547  542                  break;
 548  543  
 549  544          case SMB_FILE_NETWORK_OPEN_INFORMATION:
 550  545                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 551  546                  (void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTqql4.",
 552  547                      &qinfo->qi_crtime,
 553  548                      &qinfo->qi_atime,
 554  549                      &qinfo->qi_mtime,
 555  550                      &qinfo->qi_ctime,
 556  551                      (uint64_t)allocsz,
 557  552                      (uint64_t)datasz,
 558  553                      (uint32_t)dattr);
 559  554                  break;
 560  555  
 561  556          case SMB_FILE_ATTR_TAG_INFORMATION:
 562  557                  /*
 563  558                   * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the
 564  559                   * second dword should be the reparse tag.  Otherwise
 565  560                   * the tag value should be set to zero.
 566  561                   * We don't support reparse points, so we set the tag
 567  562                   * to zero.
 568  563                   */
 569  564                  (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
 570  565                  (void) smb_mbc_encodef(&xa->rep_data_mb, "ll",
 571  566                      (uint32_t)dattr, 0);
 572  567                  break;
 573  568  
 574  569          default:
 575  570                  if ((infolev > 1000) && smb_query_passthru)
 576  571                          smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
 577  572                              ERRDOS, ERROR_NOT_SUPPORTED);
 578  573                  else
 579  574                          smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
 580  575                  return (-1);
 581  576          }
 582  577  
 583  578          return (0);
 584  579  }
 585  580  
 586  581  /*
 587  582   * smb_encode_stream_info
 588  583   *
 589  584   * This function encodes the streams information.
 590  585   * The following rules about how have been derived from observed NT
 591  586   * behaviour.
 592  587   *
 593  588   * If the target is a file:
 594  589   * 1. If there are no named streams, the response should still contain
 595  590   *    an entry for the unnamed stream.
 596  591   * 2. If there are named streams, the response should contain an entry
 597  592   *    for the unnamed stream followed by the entries for the named
 598  593   *    streams.
 599  594   *
 600  595   * If the target is a directory:
 601  596   * 1. If there are no streams, the response is complete. Directories
 602  597   *    do not report the unnamed stream.
 603  598   * 2. If there are streams, the response should contain entries for
 604  599   *    those streams but there should not be an entry for the unnamed
 605  600   *    stream.
 606  601   *
 607  602   * Note that the stream name lengths exclude the null terminator but
 608  603   * the field lengths (i.e. next offset calculations) need to include
 609  604   * the null terminator and be padded to a multiple of 8 bytes. The
 610  605   * last entry does not seem to need any padding.
 611  606   *
 612  607   * If an error is encountered when trying to read the stream entries
 613  608   * (smb_odir_read_streaminfo) it is treated as if there are no [more]
 614  609   * entries. The entries that have been read so far are returned and
 615  610   * no error is reported.
 616  611   *
 617  612   * If the response buffer is not large enough to return all of the
 618  613   * named stream entries, the entries that do fit are returned and
 619  614   * a warning code is set (NT_STATUS_BUFFER_OVERFLOW). The next_offset
 620  615   * value in the last returned entry must be 0.
 621  616   */
 622  617  uint32_t
 623  618  smb_query_stream_info(smb_request_t *sr, mbuf_chain_t *mbc,
 624  619          smb_queryinfo_t *qinfo)
 625  620  {
 626  621          char *stream_name;
 627  622          uint32_t next_offset;
 628  623          uint32_t stream_nlen;
 629  624          uint32_t pad;
 630  625          u_offset_t datasz, allocsz;
 631  626          smb_streaminfo_t *sinfo, *sinfo_next;
 632  627          int rc = 0;
 633  628          boolean_t done = B_FALSE;
 634  629          boolean_t eos = B_FALSE;
 635  630          smb_odir_t *od = NULL;
 636  631          uint32_t status = 0;
 637  632  
 638  633          smb_node_t *fnode = qinfo->qi_node;
 639  634          smb_attr_t *attr = &qinfo->qi_attr;
 640  635  
 641  636          ASSERT(fnode);
 642  637          if (SMB_IS_STREAM(fnode)) {
 643  638                  fnode = fnode->n_unode;
 644  639                  ASSERT(fnode);
 645  640          }
 646  641          ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
 647  642          ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
  
    | 
      ↓ open down ↓ | 
    300 lines elided | 
    
      ↑ open up ↑ | 
  
 648  643  
 649  644          sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
 650  645          sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
 651  646          datasz = attr->sa_vattr.va_size;
 652  647          allocsz = attr->sa_allocsz;
 653  648  
 654  649          status = smb_odir_openat(sr, fnode, &od);
 655  650          switch (status) {
 656  651          case 0:
 657  652                  break;
      653 +        case NT_STATUS_OBJECT_NAME_NOT_FOUND:
 658  654          case NT_STATUS_NO_SUCH_FILE:
 659  655          case NT_STATUS_NOT_SUPPORTED:
 660  656                  /* No streams. */
      657 +                status = 0;
 661  658                  done = B_TRUE;
 662  659                  break;
 663  660          default:
 664  661                  return (status);
 665  662          }
 666  663  
 667  664          if (!done) {
 668  665                  rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
 669  666                  if ((rc != 0) || (eos))
 670  667                          done = B_TRUE;
 671  668          }
 672  669  
 673  670          /* If not a directory, encode an entry for the unnamed stream. */
 674  671          if (qinfo->qi_isdir == 0) {
 675  672                  stream_name = "::$DATA";
 676  673                  stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
 677  674                  next_offset = SMB_STREAM_ENCODE_FIXED_SZ + stream_nlen +
 678  675                      smb_ascii_or_unicode_null_len(sr);
 679  676  
 680  677                  /* Can unnamed stream fit in response buffer? */
 681  678                  if (MBC_ROOM_FOR(mbc, next_offset) == 0) {
 682  679                          done = B_TRUE;
 683  680                          status = NT_STATUS_BUFFER_OVERFLOW;
 684  681                  } else {
 685  682                          /* Can first named stream fit in rsp buffer? */
 686  683                          if (!done && !smb_stream_fits(sr, mbc, sinfo->si_name,
 687  684                              next_offset)) {
 688  685                                  done = B_TRUE;
 689  686                                  status = NT_STATUS_BUFFER_OVERFLOW;
 690  687                          }
 691  688  
 692  689                          if (done)
 693  690                                  next_offset = 0;
 694  691  
 695  692                          (void) smb_mbc_encodef(mbc, "%llqqu", sr,
 696  693                              next_offset, stream_nlen, datasz, allocsz,
 697  694                              stream_name);
 698  695                  }
 699  696          }
 700  697  
 701  698          /*
 702  699           * If there is no next entry, or there is not enough space in
 703  700           * the response buffer for the next entry, the next_offset and
 704  701           * padding are 0.
 705  702           */
 706  703          while (!done) {
 707  704                  stream_nlen = smb_ascii_or_unicode_strlen(sr, sinfo->si_name);
 708  705                  sinfo_next->si_name[0] = 0;
 709  706  
 710  707                  rc = smb_odir_read_streaminfo(sr, od, sinfo_next, &eos);
 711  708                  if ((rc != 0) || (eos)) {
 712  709                          done = B_TRUE;
 713  710                  } else {
 714  711                          next_offset = SMB_STREAM_ENCODE_FIXED_SZ +
 715  712                              stream_nlen +
 716  713                              smb_ascii_or_unicode_null_len(sr);
 717  714                          pad = smb_pad_align(next_offset, 8);
 718  715                          next_offset += pad;
 719  716  
 720  717                          /* Can next named stream fit in response buffer? */
 721  718                          if (!smb_stream_fits(sr, mbc, sinfo_next->si_name,
 722  719                              next_offset)) {
 723  720                                  done = B_TRUE;
 724  721                                  status = NT_STATUS_BUFFER_OVERFLOW;
 725  722                          }
 726  723                  }
 727  724  
 728  725                  if (done) {
 729  726                          next_offset = 0;
 730  727                          pad = 0;
 731  728                  }
 732  729  
 733  730                  (void) smb_mbc_encodef(mbc, "%llqqu#.",
 734  731                      sr, next_offset, stream_nlen,
 735  732                      sinfo->si_size, sinfo->si_alloc_size,
 736  733                      sinfo->si_name, pad);
 737  734  
 738  735                  (void) memcpy(sinfo, sinfo_next, sizeof (smb_streaminfo_t));
 739  736          }
 740  737  
 741  738          kmem_free(sinfo, sizeof (smb_streaminfo_t));
 742  739          kmem_free(sinfo_next, sizeof (smb_streaminfo_t));
 743  740          if (od) {
 744  741                  smb_odir_close(od);
 745  742                  smb_odir_release(od);
 746  743          }
 747  744  
 748  745          return (status);
 749  746  }
 750  747  
 751  748  /*
 752  749   * smb_stream_fits
 753  750   *
 754  751   * Check if the named stream entry can fit in the response buffer.
 755  752   *
 756  753   * Required space =
 757  754   *      offset (size of current entry)
 758  755   *      + SMB_STREAM_ENCODE_FIXED_SIZE
 759  756   *      + length of encoded stream name
 760  757   *      + length of null terminator
 761  758   *      + alignment padding
 762  759   */
 763  760  static boolean_t
 764  761  smb_stream_fits(smb_request_t *sr, mbuf_chain_t *mbc,
 765  762          char *name, uint32_t offset)
 766  763  {
 767  764          uint32_t len, pad;
 768  765  
 769  766          len = SMB_STREAM_ENCODE_FIXED_SZ +
 770  767              smb_ascii_or_unicode_strlen(sr, name) +
 771  768              smb_ascii_or_unicode_null_len(sr);
 772  769          pad = smb_pad_align(len, 8);
 773  770          len += pad;
 774  771  
 775  772          return (MBC_ROOM_FOR(mbc, offset + len) != 0);
 776  773  }
 777  774  
 778  775  /*
 779  776   * smb_query_fileinfo
 780  777   *
 781  778   * Populate smb_queryinfo_t structure for SMB_FTYPE_DISK
 782  779   * (This should become an smb_ofile / smb_node function.)
 783  780   */
 784  781  int
 785  782  smb_query_fileinfo(smb_request_t *sr, smb_node_t *node, uint16_t infolev,
 786  783      smb_queryinfo_t *qinfo)
 787  784  {
 788  785          int rc = 0;
 789  786  
 790  787          /* If shortname required but not supported -> OBJECT_NAME_NOT_FOUND */
 791  788          if ((infolev == SMB_QUERY_FILE_ALT_NAME_INFO) ||
 792  789              (infolev == SMB_FILE_ALT_NAME_INFORMATION)) {
 793  790                  if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_SHORTNAMES)) {
 794  791                          smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
 795  792                              ERRDOS, ERROR_FILE_NOT_FOUND);
 796  793                          return (-1);
 797  794                  }
 798  795          }
 799  796  
 800  797          (void) bzero(qinfo, sizeof (smb_queryinfo_t));
 801  798  
 802  799          /* See: smb_query_encode_response */
 803  800          qinfo->qi_attr.sa_mask = SMB_AT_ALL;
 804  801          rc = smb_node_getattr(sr, node, sr->user_cr, sr->fid_ofile,
 805  802              &qinfo->qi_attr);
 806  803          if (rc != 0) {
 807  804                  smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
 808  805                      ERRDOS, ERROR_INTERNAL_ERROR);
 809  806                  return (-1);
 810  807          }
 811  808  
 812  809          qinfo->qi_node = node;
 813  810          qinfo->qi_delete_on_close =
 814  811              (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0;
 815  812          qinfo->qi_isdir = smb_node_is_dir(node);
 816  813  
 817  814          /*
 818  815           * The number of links reported should be the number of
 819  816           * non-deleted links. Thus if delete_on_close is set,
 820  817           * decrement the link count.
 821  818           */
 822  819          if (qinfo->qi_delete_on_close &&
 823  820              qinfo->qi_attr.sa_vattr.va_nlink > 0) {
 824  821                  --(qinfo->qi_attr.sa_vattr.va_nlink);
 825  822          }
 826  823  
 827  824          /*
 828  825           * populate name, namelen and shortname ONLY for the information
 829  826           * levels that require these fields
 830  827           */
 831  828          switch (infolev) {
 832  829          case SMB_QUERY_FILE_ALL_INFO:
 833  830          case SMB_FILE_ALL_INFORMATION:
 834  831                  rc = smb_query_pathname(sr, node, B_TRUE, qinfo);
 835  832                  break;
 836  833          case SMB_QUERY_FILE_NAME_INFO:
 837  834          case SMB_FILE_NAME_INFORMATION:
 838  835                  rc = smb_query_pathname(sr, node, B_FALSE, qinfo);
 839  836                  break;
 840  837          case SMB_QUERY_FILE_ALT_NAME_INFO:
 841  838          case SMB_FILE_ALT_NAME_INFORMATION:
 842  839                  smb_query_shortname(node, qinfo);
 843  840                  break;
 844  841          default:
 845  842                  break;
 846  843          }
 847  844  
 848  845          if (rc != 0) {
 849  846                  smbsr_errno(sr, rc);
 850  847                  return (-1);
 851  848          }
 852  849          return (0);
 853  850  }
 854  851  
 855  852  /*
 856  853   * smb_query_pathname
 857  854   *
 858  855   * Determine the absolute pathname of 'node' within the share.
 859  856   * For some levels (e.g. ALL_INFO) the pathname should include the
 860  857   * sharename for others (e.g. NAME_INFO) the pathname should be
 861  858   * relative to the share.
 862  859   * For example if the node represents file "test1.txt" in directory
 863  860   * "dir1" on share "share1"
 864  861   * - if include_share is TRUE the pathname would be: \share1\dir1\test1.txt
 865  862   * - if include_share is FALSE the pathname would be: \dir1\test1.txt
 866  863   *
 867  864   * For some reason NT will not show the security tab in the root
 868  865   * directory of a mapped drive unless the filename length is greater
 869  866   * than one. So if the length is 1 we set it to 2 to persuade NT to
 870  867   * show the tab. It should be safe because of the null terminator.
 871  868   */
 872  869  static int
 873  870  smb_query_pathname(smb_request_t *sr, smb_node_t *node, boolean_t include_share,
 874  871      smb_queryinfo_t *qinfo)
 875  872  {
 876  873          smb_tree_t *tree = sr->tid_tree;
 877  874          char *buf = qinfo->qi_name;
 878  875          size_t buflen = MAXPATHLEN;
 879  876          size_t len;
 880  877          int rc;
 881  878  
 882  879          if (include_share) {
 883  880                  len = snprintf(buf, buflen, "\\%s", tree->t_sharename);
 884  881                  if (len == (buflen - 1))
 885  882                          return (ENAMETOOLONG);
 886  883  
 887  884                  buf += len;
 888  885                  buflen -= len;
 889  886          }
 890  887  
 891  888          if (node == tree->t_snode) {
 892  889                  if (!include_share)
 893  890                          (void) strlcpy(buf, "\\", buflen);
 894  891                  return (0);
 895  892          }
 896  893  
 897  894          rc =  smb_node_getshrpath(node, tree, buf, buflen);
 898  895          if (rc == 0) {
 899  896                  qinfo->qi_namelen =
 900  897                      smb_ascii_or_unicode_strlen(sr, qinfo->qi_name);
 901  898                  if (qinfo->qi_namelen == 1)
 902  899                          qinfo->qi_namelen = 2;
 903  900          }
 904  901          return (rc);
 905  902  }
 906  903  
 907  904  /*
 908  905   * smb_query_shortname
 909  906   *
 910  907   * If the node is a named stream, use its associated
 911  908   * unnamed stream name to determine the shortname.
 912  909   * If a shortname is required (smb_needs_mangle()), generate it
 913  910   * using smb_mangle(), otherwise, convert the original name to
 914  911   * upper-case and return it as the alternative name.
 915  912   */
 916  913  void
 917  914  smb_query_shortname(smb_node_t *node, smb_queryinfo_t *qinfo)
 918  915  {
 919  916          char *namep;
 920  917  
 921  918          if (SMB_IS_STREAM(node))
 922  919                  namep = node->n_unode->od_name;
 923  920          else
 924  921                  namep = node->od_name;
 925  922  
 926  923          if (smb_needs_mangled(namep)) {
 927  924                  smb_mangle(namep, qinfo->qi_attr.sa_vattr.va_nodeid,
 928  925                      qinfo->qi_shortname, SMB_SHORTNAMELEN);
 929  926          } else {
 930  927                  (void) strlcpy(qinfo->qi_shortname, namep, SMB_SHORTNAMELEN);
 931  928                  (void) smb_strupr(qinfo->qi_shortname);
 932  929          }
 933  930  }
 934  931  
 935  932  /*
 936  933   * smb_query_pipeinfo
 937  934   *
 938  935   * Populate smb_queryinfo_t structure for SMB_FTYPE_MESG_PIPE
 939  936   * (This should become an smb_opipe function.)
 940  937   */
 941  938  static int
 942  939  smb_query_pipeinfo(smb_request_t *sr, smb_opipe_t *opipe, uint16_t infolev,
 943  940      smb_queryinfo_t *qinfo)
 944  941  {
 945  942          char *namep = opipe->p_name;
 946  943  
 947  944          (void) bzero(qinfo, sizeof (smb_queryinfo_t));
 948  945          qinfo->qi_node = NULL;
 949  946          qinfo->qi_attr.sa_vattr.va_nlink = 1;
 950  947          qinfo->qi_delete_on_close = 1;
 951  948          qinfo->qi_isdir = 0;
 952  949  
 953  950          if ((infolev == SMB_INFO_STANDARD) ||
 954  951              (infolev == SMB_INFO_QUERY_EA_SIZE) ||
 955  952              (infolev == SMB_QUERY_INFORMATION2)) {
 956  953                  qinfo->qi_attr.sa_dosattr = 0;
 957  954          } else {
 958  955                  qinfo->qi_attr.sa_dosattr = FILE_ATTRIBUTE_NORMAL;
 959  956          }
 960  957  
 961  958          /* If the leading \ is missing from the pipe name, add it. */
 962  959          if (*namep != '\\')
 963  960                  (void) snprintf(qinfo->qi_name, MAXNAMELEN, "\\%s", namep);
 964  961          else
 965  962                  (void) strlcpy(qinfo->qi_name, namep, MAXNAMELEN);
 966  963  
 967  964          qinfo->qi_namelen=
 968  965              smb_ascii_or_unicode_strlen(sr, qinfo->qi_name);
 969  966  
 970  967          return (0);
 971  968  }
 972  969  
 973  970  /*
 974  971   * smb_query_pipe_valid_infolev
 975  972   *
 976  973   * If the infolev is not valid for a message pipe, the error
 977  974   * information is set in sr and B_FALSE is returned.
 978  975   * Otherwise, returns B_TRUE.
 979  976   */
 980  977  static boolean_t
 981  978  smb_query_pipe_valid_infolev(smb_request_t *sr, uint16_t infolev)
 982  979  {
 983  980          switch (infolev) {
 984  981          case SMB_INFO_QUERY_ALL_EAS:
 985  982                  smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 986  983                      ERRDOS, ERROR_ACCESS_DENIED);
 987  984                  return (B_FALSE);
 988  985  
 989  986          case SMB_QUERY_FILE_ALT_NAME_INFO:
 990  987          case SMB_FILE_ALT_NAME_INFORMATION:
 991  988          case SMB_QUERY_FILE_STREAM_INFO:
 992  989          case SMB_FILE_STREAM_INFORMATION:
 993  990          case SMB_QUERY_FILE_COMPRESSION_INFO:
 994  991          case SMB_FILE_COMPRESSION_INFORMATION:
 995  992          case SMB_FILE_NETWORK_OPEN_INFORMATION:
 996  993          case SMB_FILE_ATTR_TAG_INFORMATION:
 997  994                  smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 998  995                      ERRDOS, ERROR_INVALID_PARAMETER);
 999  996                  return (B_FALSE);
1000  997          }
1001  998  
1002  999          return (B_TRUE);
1003 1000  }
  
    | 
      ↓ open down ↓ | 
    333 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX