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 2013 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <smbsrv/smb_kproto.h>
  28 #include <smbsrv/smb_vops.h>
  29 #include <smbsrv/smb_fsops.h>
  30 
  31 /*
  32  * Trans2 Query File/Path Information Levels:
  33  *
  34  * SMB_INFO_STANDARD
  35  * SMB_INFO_QUERY_EA_SIZE
  36  * SMB_INFO_QUERY_EAS_FROM_LIST
  37  * SMB_INFO_QUERY_ALL_EAS - not valid for pipes
  38  * SMB_INFO_IS_NAME_VALID - only valid when query is by path
  39  *
  40  * SMB_QUERY_FILE_BASIC_INFO
  41  * SMB_QUERY_FILE_STANDARD_INFO
  42  * SMB_QUERY_FILE_EA_INFO
  43  * SMB_QUERY_FILE_NAME_INFO
  44  * SMB_QUERY_FILE_ALL_INFO
 
 
 132             sr, &infolev, &fqi->fq_path.pn_path) != 0)
 133                 return (SDRC_ERROR);
 134 
 135         if (smb_query_by_path(sr, xa, infolev) != 0)
 136                 return (SDRC_ERROR);
 137 
 138         return (SDRC_SUCCESS);
 139 }
 140 
 141 /*
 142  * smb_com_query_information (aka getattr)
 143  */
 144 smb_sdrc_t
 145 smb_pre_query_information(smb_request_t *sr)
 146 {
 147         int rc;
 148         smb_fqi_t *fqi = &sr->arg.dirop.fqi;
 149 
 150         rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);
 151 
 152         DTRACE_SMB_2(op__QueryInformation__start, smb_request_t *, sr,
 153             smb_fqi_t *, fqi);
 154 
 155         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 156 }
 157 
 158 void
 159 smb_post_query_information(smb_request_t *sr)
 160 {
 161         DTRACE_SMB_1(op__QueryInformation__done, smb_request_t *, sr);
 162 }
 163 
 164 smb_sdrc_t
 165 smb_com_query_information(smb_request_t *sr)
 166 {
 167         uint16_t infolev = SMB_QUERY_INFORMATION;
 168 
 169         if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
 170                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 171                     ERRDOS, ERROR_ACCESS_DENIED);
 172                 return (SDRC_ERROR);
 173         }
 174 
 175         if (smb_query_by_path(sr, NULL, infolev) != 0)
 176                 return (SDRC_ERROR);
 177 
 178         return (SDRC_SUCCESS);
 179 }
 180 
 181 /*
 182  * smb_com_query_information2 (aka getattre)
 183  */
 184 smb_sdrc_t
 185 smb_pre_query_information2(smb_request_t *sr)
 186 {
 187         int rc;
 188         rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
 189 
 190         DTRACE_SMB_1(op__QueryInformation2__start, smb_request_t *, sr);
 191 
 192         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 193 }
 194 
 195 void
 196 smb_post_query_information2(smb_request_t *sr)
 197 {
 198         DTRACE_SMB_1(op__QueryInformation2__done, smb_request_t *, sr);
 199 }
 200 
 201 smb_sdrc_t
 202 smb_com_query_information2(smb_request_t *sr)
 203 {
 204         uint16_t infolev = SMB_QUERY_INFORMATION2;
 205 
 206         if (smb_query_by_fid(sr, NULL, infolev) != 0)
 207                 return (SDRC_ERROR);
 208 
 209         return (SDRC_SUCCESS);
 210 }
 211 
 212 /*
 213  * smb_query_by_fid
 214  *
 215  * Common code for querying file information by open file (or pipe) id.
 216  * Use the id to identify the node / pipe object and request the
 217  * smb_queryinfo_t data for that object.
 218  */
 
 313         }
 314 
 315         pn = &sr->arg.dirop.fqi.fq_path;
 316         smb_pathname_init(sr, pn, pn->pn_path);
 317         if (!smb_pathname_validate(sr, pn))
 318                 return (-1);
 319 
 320         qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
 321 
 322         rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
 323             sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode,
 324             qinfo->qi_name);
 325 
 326         if (rc == 0) {
 327                 rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS,
 328                     sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node);
 329                 smb_node_release(dnode);
 330         }
 331 
 332         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);
 338 
 339                 kmem_free(qinfo, sizeof (smb_queryinfo_t));
 340                 return (-1);
 341         }
 342 
 343         if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
 344                 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
 345                 kmem_free(qinfo, sizeof (smb_queryinfo_t));
 346                 smb_node_release(node);
 347                 return (-1);
 348         }
 349 
 350         rc = smb_query_fileinfo(sr, node, infolev, qinfo);
 351         if (rc != 0) {
 352                 kmem_free(qinfo, sizeof (smb_queryinfo_t));
 353                 smb_node_release(node);
 354                 return (rc);
 355         }
 356 
 
 638         smb_node_t *fnode = qinfo->qi_node;
 639         smb_attr_t *attr = &qinfo->qi_attr;
 640 
 641         ASSERT(fnode);
 642         if (SMB_IS_STREAM(fnode)) {
 643                 fnode = fnode->n_unode;
 644                 ASSERT(fnode);
 645         }
 646         ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
 647         ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
 648 
 649         sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
 650         sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
 651         datasz = attr->sa_vattr.va_size;
 652         allocsz = attr->sa_allocsz;
 653 
 654         status = smb_odir_openat(sr, fnode, &od);
 655         switch (status) {
 656         case 0:
 657                 break;
 658         case NT_STATUS_NO_SUCH_FILE:
 659         case NT_STATUS_NOT_SUPPORTED:
 660                 /* No streams. */
 661                 done = B_TRUE;
 662                 break;
 663         default:
 664                 return (status);
 665         }
 666 
 667         if (!done) {
 668                 rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
 669                 if ((rc != 0) || (eos))
 670                         done = B_TRUE;
 671         }
 672 
 673         /* If not a directory, encode an entry for the unnamed stream. */
 674         if (qinfo->qi_isdir == 0) {
 675                 stream_name = "::$DATA";
 676                 stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
 677                 next_offset = SMB_STREAM_ENCODE_FIXED_SZ + stream_nlen +
 678                     smb_ascii_or_unicode_null_len(sr);
 679 
 680                 /* Can unnamed stream fit in response buffer? */
 
 | 
 
 
   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 2017 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <smbsrv/smb_kproto.h>
  28 #include <smbsrv/smb_vops.h>
  29 #include <smbsrv/smb_fsops.h>
  30 
  31 /*
  32  * Trans2 Query File/Path Information Levels:
  33  *
  34  * SMB_INFO_STANDARD
  35  * SMB_INFO_QUERY_EA_SIZE
  36  * SMB_INFO_QUERY_EAS_FROM_LIST
  37  * SMB_INFO_QUERY_ALL_EAS - not valid for pipes
  38  * SMB_INFO_IS_NAME_VALID - only valid when query is by path
  39  *
  40  * SMB_QUERY_FILE_BASIC_INFO
  41  * SMB_QUERY_FILE_STANDARD_INFO
  42  * SMB_QUERY_FILE_EA_INFO
  43  * SMB_QUERY_FILE_NAME_INFO
  44  * SMB_QUERY_FILE_ALL_INFO
 
 
 132             sr, &infolev, &fqi->fq_path.pn_path) != 0)
 133                 return (SDRC_ERROR);
 134 
 135         if (smb_query_by_path(sr, xa, infolev) != 0)
 136                 return (SDRC_ERROR);
 137 
 138         return (SDRC_SUCCESS);
 139 }
 140 
 141 /*
 142  * smb_com_query_information (aka getattr)
 143  */
 144 smb_sdrc_t
 145 smb_pre_query_information(smb_request_t *sr)
 146 {
 147         int rc;
 148         smb_fqi_t *fqi = &sr->arg.dirop.fqi;
 149 
 150         rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);
 151 
 152         DTRACE_SMB_START(op__QueryInformation, smb_request_t *, sr);
 153 
 154         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 155 }
 156 
 157 void
 158 smb_post_query_information(smb_request_t *sr)
 159 {
 160         DTRACE_SMB_DONE(op__QueryInformation, smb_request_t *, sr);
 161 }
 162 
 163 smb_sdrc_t
 164 smb_com_query_information(smb_request_t *sr)
 165 {
 166         uint16_t infolev = SMB_QUERY_INFORMATION;
 167 
 168         if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
 169                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 170                     ERRDOS, ERROR_ACCESS_DENIED);
 171                 return (SDRC_ERROR);
 172         }
 173 
 174         if (smb_query_by_path(sr, NULL, infolev) != 0)
 175                 return (SDRC_ERROR);
 176 
 177         return (SDRC_SUCCESS);
 178 }
 179 
 180 /*
 181  * smb_com_query_information2 (aka getattre)
 182  */
 183 smb_sdrc_t
 184 smb_pre_query_information2(smb_request_t *sr)
 185 {
 186         int rc;
 187         rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
 188 
 189         DTRACE_SMB_START(op__QueryInformation2, smb_request_t *, sr);
 190 
 191         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 192 }
 193 
 194 void
 195 smb_post_query_information2(smb_request_t *sr)
 196 {
 197         DTRACE_SMB_DONE(op__QueryInformation2, smb_request_t *, sr);
 198 }
 199 
 200 smb_sdrc_t
 201 smb_com_query_information2(smb_request_t *sr)
 202 {
 203         uint16_t infolev = SMB_QUERY_INFORMATION2;
 204 
 205         if (smb_query_by_fid(sr, NULL, infolev) != 0)
 206                 return (SDRC_ERROR);
 207 
 208         return (SDRC_SUCCESS);
 209 }
 210 
 211 /*
 212  * smb_query_by_fid
 213  *
 214  * Common code for querying file information by open file (or pipe) id.
 215  * Use the id to identify the node / pipe object and request the
 216  * smb_queryinfo_t data for that object.
 217  */
 
 312         }
 313 
 314         pn = &sr->arg.dirop.fqi.fq_path;
 315         smb_pathname_init(sr, pn, pn->pn_path);
 316         if (!smb_pathname_validate(sr, pn))
 317                 return (-1);
 318 
 319         qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
 320 
 321         rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
 322             sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode,
 323             qinfo->qi_name);
 324 
 325         if (rc == 0) {
 326                 rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS,
 327                     sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node);
 328                 smb_node_release(dnode);
 329         }
 330 
 331         if (rc != 0) {
 332                 smbsr_errno(sr, rc);
 333 
 334                 kmem_free(qinfo, sizeof (smb_queryinfo_t));
 335                 return (-1);
 336         }
 337 
 338         if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
 339                 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
 340                 kmem_free(qinfo, sizeof (smb_queryinfo_t));
 341                 smb_node_release(node);
 342                 return (-1);
 343         }
 344 
 345         rc = smb_query_fileinfo(sr, node, infolev, qinfo);
 346         if (rc != 0) {
 347                 kmem_free(qinfo, sizeof (smb_queryinfo_t));
 348                 smb_node_release(node);
 349                 return (rc);
 350         }
 351 
 
 633         smb_node_t *fnode = qinfo->qi_node;
 634         smb_attr_t *attr = &qinfo->qi_attr;
 635 
 636         ASSERT(fnode);
 637         if (SMB_IS_STREAM(fnode)) {
 638                 fnode = fnode->n_unode;
 639                 ASSERT(fnode);
 640         }
 641         ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
 642         ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
 643 
 644         sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
 645         sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
 646         datasz = attr->sa_vattr.va_size;
 647         allocsz = attr->sa_allocsz;
 648 
 649         status = smb_odir_openat(sr, fnode, &od);
 650         switch (status) {
 651         case 0:
 652                 break;
 653         case NT_STATUS_OBJECT_NAME_NOT_FOUND:
 654         case NT_STATUS_NO_SUCH_FILE:
 655         case NT_STATUS_NOT_SUPPORTED:
 656                 /* No streams. */
 657                 status = 0;
 658                 done = B_TRUE;
 659                 break;
 660         default:
 661                 return (status);
 662         }
 663 
 664         if (!done) {
 665                 rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
 666                 if ((rc != 0) || (eos))
 667                         done = B_TRUE;
 668         }
 669 
 670         /* If not a directory, encode an entry for the unnamed stream. */
 671         if (qinfo->qi_isdir == 0) {
 672                 stream_name = "::$DATA";
 673                 stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
 674                 next_offset = SMB_STREAM_ENCODE_FIXED_SZ + stream_nlen +
 675                     smb_ascii_or_unicode_null_len(sr);
 676 
 677                 /* Can unnamed stream fit in response buffer? */
 
 |