3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Common functions supporting both:
  28  * SMB1 Trans2 Set File/Path Info,
  29  * SMB2 Set File Info
  30  */
  31 
  32 #include <smbsrv/smb_kproto.h>
  33 #include <smbsrv/smb_fsops.h>
  34 
  35 /*
  36  * smb_set_basic_info
  37  * [MS-FSCC] 2.4.7
  38  *      FileBasicInformation
  39  *      SMB_SET_FILE_BASIC_INFO
  40  *      SMB_FILE_BASIC_INFORMATION
  41  *
  42  * Sets basic file/path information.
  43  *
  44  * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the
  45  * target is not a directory.
  46  *
  47  * For compatibility with windows servers:
  48  * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set
  49  *   clear (0) the file's attributes.
  50  * - if the specified attributes are 0 do NOT change the file's attributes.
  51  */
  52 uint32_t
 
 
  91 
  92         rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
  93         if (rc != 0)
  94                 return (smb_errno2status(rc));
  95 
  96         return (0);
  97 }
  98 
  99 /*
 100  * smb_set_eof_info
 101  *      FileEndOfFileInformation
 102  *      SMB_SET_FILE_END_OF_FILE_INFO
 103  *      SMB_FILE_END_OF_FILE_INFORMATION
 104  */
 105 uint32_t
 106 smb_set_eof_info(smb_request_t *sr, smb_setinfo_t *si)
 107 {
 108         smb_attr_t *attr = &si->si_attr;
 109         smb_node_t *node = si->si_node;
 110         uint64_t eof;
 111         int rc;
 112 
 113         if (smb_mbc_decodef(&si->si_data, "q", &eof) != 0)
 114                 return (NT_STATUS_INFO_LENGTH_MISMATCH);
 115 
 116         if (smb_node_is_dir(node))
 117                 return (NT_STATUS_INVALID_PARAMETER);
 118 
 119         /* If opened by path, break exclusive oplock */
 120         if (sr->fid_ofile == NULL)
 121                 (void) smb_oplock_break(sr, node,
 122                     SMB_OPLOCK_BREAK_EXCLUSIVE | SMB_OPLOCK_BREAK_TO_NONE);
 123 
 124         bzero(attr, sizeof (*attr));
 125         attr->sa_mask = SMB_AT_SIZE;
 126         attr->sa_vattr.va_size = (u_offset_t)eof;
 127         rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
 128         if (rc != 0)
 129                 return (smb_errno2status(rc));
 130 
 131         smb_oplock_break_levelII(node);
 132         return (0);
 133 }
 134 
 135 /*
 136  * smb_set_alloc_info
 137  *      FileAllocationInformation
 138  *      SMB_SET_FILE_ALLOCATION_INFO
 139  *      SMB_FILE_ALLOCATION_INFORMATION
 140  */
 141 uint32_t
 142 smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *si)
 143 {
 144         smb_attr_t *attr = &si->si_attr;
 145         smb_node_t *node = si->si_node;
 146         uint64_t allocsz;
 147         int rc;
 148 
 149         if (smb_mbc_decodef(&si->si_data, "q", &allocsz) != 0)
 150                 return (NT_STATUS_INFO_LENGTH_MISMATCH);
 151 
 152         if (smb_node_is_dir(node))
 153                 return (NT_STATUS_INVALID_PARAMETER);
 154 
 155         /* If opened by path, break exclusive oplock */
 156         if (sr->fid_ofile == NULL)
 157                 (void) smb_oplock_break(sr, node,
 158                     SMB_OPLOCK_BREAK_EXCLUSIVE | SMB_OPLOCK_BREAK_TO_NONE);
 159 
 160         bzero(attr, sizeof (*attr));
 161         attr->sa_mask = SMB_AT_ALLOCSZ;
 162         attr->sa_allocsz = (u_offset_t)allocsz;
 163         rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
 164         if (rc != 0)
 165                 return (smb_errno2status(rc));
 166 
 167         smb_oplock_break_levelII(node);
 168         return (0);
 169 }
 170 
 171 /*
 172  * smb_set_disposition_info
 173  * See:
 174  *      FileDispositionInformation
 175  *      SMB_SET_FILE_DISPOSITION_INFO
 176  *      SMB_FILE_DISPOSITION_INFORMATION
 177  *
 178  * Set/Clear DELETE_ON_CLOSE flag for an open file.
 179  * File should have been opened with DELETE access otherwise
 180  * the operation is not permitted.
 181  *
 182  * NOTE: The node should be marked delete-on-close upon the receipt
 183  * of the Trans2SetFileInfo(SetDispositionInfo) if mark_delete is set.
 184  * It is different than both SmbNtCreateAndX and SmbNtTransact, which
 185  * set delete-on-close on the ofile and defer setting the flag on the
 186  * node until the file is closed.
 187  *
 
 194  *
 195  * 2) If a file is opened with delete-on-close create options and the
 196  * client attempts to unset delete-on-close via Trans2SetFileInfo
 197  * (SetDispositionInfo) prior to the file close, any subsequent open
 198  * requests will still fail with DELETE_PENDING after the file is closed.
 199  *
 200  * 3) If a file is opened with delete-on-close create options and that
 201  * file handle (not the last open handle and the only file handle
 202  * with delete-on-close set) is closed. Any subsequent open requests
 203  * will fail with DELETE_PENDING. Unsetting delete-on-close via
 204  * Trans2SetFileInfo(SetDispositionInfo) at this time will unset the
 205  * node delete-on-close flag, which will result in the file not being
 206  * removed even after the last file handle is closed.
 207  */
 208 uint32_t
 209 smb_set_disposition_info(smb_request_t *sr, smb_setinfo_t *si)
 210 {
 211         smb_node_t *node = si->si_node;
 212         smb_ofile_t *of = sr->fid_ofile;
 213         uint8_t         mark_delete;
 214         uint32_t        flags = 0;
 215 
 216         if (smb_mbc_decodef(&si->si_data, "b", &mark_delete) != 0)
 217                 return (NT_STATUS_INFO_LENGTH_MISMATCH);
 218 
 219         if ((of == NULL) || !(smb_ofile_granted_access(of) & DELETE))
 220                 return (NT_STATUS_ACCESS_DENIED);
 221 
 222         if (mark_delete) {
 223                 if (SMB_TREE_SUPPORTS_CATIA(sr))
 224                         flags |= SMB_CATIA;
 225                 return (smb_node_set_delete_on_close(node, of->f_cr, flags));
 226         } else {
 227                 smb_node_reset_delete_on_close(node);
 228         }
 229 
 230         return (NT_STATUS_SUCCESS);
 231 }
 | 
 
 
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Common functions supporting both:
  28  * SMB1 Trans2 Set File/Path Info,
  29  * SMB2 Set File Info
  30  */
  31 
  32 #include <smbsrv/smb2_kproto.h>
  33 #include <smbsrv/smb_fsops.h>
  34 
  35 /*
  36  * smb_set_basic_info
  37  * [MS-FSCC] 2.4.7
  38  *      FileBasicInformation
  39  *      SMB_SET_FILE_BASIC_INFO
  40  *      SMB_FILE_BASIC_INFORMATION
  41  *
  42  * Sets basic file/path information.
  43  *
  44  * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the
  45  * target is not a directory.
  46  *
  47  * For compatibility with windows servers:
  48  * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set
  49  *   clear (0) the file's attributes.
  50  * - if the specified attributes are 0 do NOT change the file's attributes.
  51  */
  52 uint32_t
 
 
  91 
  92         rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
  93         if (rc != 0)
  94                 return (smb_errno2status(rc));
  95 
  96         return (0);
  97 }
  98 
  99 /*
 100  * smb_set_eof_info
 101  *      FileEndOfFileInformation
 102  *      SMB_SET_FILE_END_OF_FILE_INFO
 103  *      SMB_FILE_END_OF_FILE_INFORMATION
 104  */
 105 uint32_t
 106 smb_set_eof_info(smb_request_t *sr, smb_setinfo_t *si)
 107 {
 108         smb_attr_t *attr = &si->si_attr;
 109         smb_node_t *node = si->si_node;
 110         uint64_t eof;
 111         uint32_t status;
 112         int rc;
 113 
 114         if (smb_mbc_decodef(&si->si_data, "q", &eof) != 0)
 115                 return (NT_STATUS_INFO_LENGTH_MISMATCH);
 116 
 117         if (smb_node_is_dir(node))
 118                 return (NT_STATUS_INVALID_PARAMETER);
 119 
 120         status = smb_oplock_break_SETINFO(node, sr->fid_ofile,
 121             FileEndOfFileInformation);
 122         if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
 123                 if (sr->session->dialect >= SMB_VERS_2_BASE)
 124                         (void) smb2sr_go_async(sr);
 125                 (void) smb_oplock_wait_break(node, 0);
 126                 status = 0;
 127         }
 128         if (status != 0)
 129                 return (status);
 130 
 131         bzero(attr, sizeof (*attr));
 132         attr->sa_mask = SMB_AT_SIZE;
 133         attr->sa_vattr.va_size = (u_offset_t)eof;
 134         rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
 135         if (rc != 0)
 136                 return (smb_errno2status(rc));
 137 
 138         return (0);
 139 }
 140 
 141 /*
 142  * smb_set_alloc_info
 143  *      FileAllocationInformation
 144  *      SMB_SET_FILE_ALLOCATION_INFO
 145  *      SMB_FILE_ALLOCATION_INFORMATION
 146  */
 147 uint32_t
 148 smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *si)
 149 {
 150         smb_attr_t *attr = &si->si_attr;
 151         smb_node_t *node = si->si_node;
 152         uint64_t allocsz;
 153         uint32_t status;
 154         int rc;
 155 
 156         if (smb_mbc_decodef(&si->si_data, "q", &allocsz) != 0)
 157                 return (NT_STATUS_INFO_LENGTH_MISMATCH);
 158 
 159         if (smb_node_is_dir(node))
 160                 return (NT_STATUS_INVALID_PARAMETER);
 161 
 162         status = smb_oplock_break_SETINFO(node, sr->fid_ofile,
 163             FileAllocationInformation);
 164         if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
 165                 if (sr->session->dialect >= SMB_VERS_2_BASE)
 166                         (void) smb2sr_go_async(sr);
 167                 (void) smb_oplock_wait_break(node, 0);
 168                 status = 0;
 169         }
 170         if (status != 0)
 171                 return (status);
 172 
 173         bzero(attr, sizeof (*attr));
 174         attr->sa_mask = SMB_AT_ALLOCSZ;
 175         attr->sa_allocsz = (u_offset_t)allocsz;
 176         rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
 177         if (rc != 0)
 178                 return (smb_errno2status(rc));
 179 
 180         return (0);
 181 }
 182 
 183 /*
 184  * smb_set_disposition_info
 185  * See:
 186  *      FileDispositionInformation
 187  *      SMB_SET_FILE_DISPOSITION_INFO
 188  *      SMB_FILE_DISPOSITION_INFORMATION
 189  *
 190  * Set/Clear DELETE_ON_CLOSE flag for an open file.
 191  * File should have been opened with DELETE access otherwise
 192  * the operation is not permitted.
 193  *
 194  * NOTE: The node should be marked delete-on-close upon the receipt
 195  * of the Trans2SetFileInfo(SetDispositionInfo) if mark_delete is set.
 196  * It is different than both SmbNtCreateAndX and SmbNtTransact, which
 197  * set delete-on-close on the ofile and defer setting the flag on the
 198  * node until the file is closed.
 199  *
 
 206  *
 207  * 2) If a file is opened with delete-on-close create options and the
 208  * client attempts to unset delete-on-close via Trans2SetFileInfo
 209  * (SetDispositionInfo) prior to the file close, any subsequent open
 210  * requests will still fail with DELETE_PENDING after the file is closed.
 211  *
 212  * 3) If a file is opened with delete-on-close create options and that
 213  * file handle (not the last open handle and the only file handle
 214  * with delete-on-close set) is closed. Any subsequent open requests
 215  * will fail with DELETE_PENDING. Unsetting delete-on-close via
 216  * Trans2SetFileInfo(SetDispositionInfo) at this time will unset the
 217  * node delete-on-close flag, which will result in the file not being
 218  * removed even after the last file handle is closed.
 219  */
 220 uint32_t
 221 smb_set_disposition_info(smb_request_t *sr, smb_setinfo_t *si)
 222 {
 223         smb_node_t *node = si->si_node;
 224         smb_ofile_t *of = sr->fid_ofile;
 225         uint8_t         mark_delete;
 226         uint32_t        status;
 227         uint32_t        flags = 0;
 228 
 229         if (smb_mbc_decodef(&si->si_data, "b", &mark_delete) != 0)
 230                 return (NT_STATUS_INFO_LENGTH_MISMATCH);
 231 
 232         if ((of == NULL) || !(smb_ofile_granted_access(of) & DELETE))
 233                 return (NT_STATUS_ACCESS_DENIED);
 234 
 235         if (mark_delete == 0) {
 236                 smb_node_reset_delete_on_close(node);
 237                 return (NT_STATUS_SUCCESS);
 238         }
 239 
 240         /*
 241          * Break any oplock handle caching.
 242          */
 243         status = smb_oplock_break_SETINFO(node, of,
 244             FileDispositionInformation);
 245         if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
 246                 if (sr->session->dialect >= SMB_VERS_2_BASE)
 247                         (void) smb2sr_go_async(sr);
 248                 (void) smb_oplock_wait_break(node, 0);
 249                 status = 0;
 250         }
 251         if (status != 0)
 252                 return (status);
 253 
 254         if (SMB_TREE_SUPPORTS_CATIA(sr))
 255                 flags |= SMB_CATIA;
 256 
 257         return (smb_node_set_delete_on_close(node, of->f_cr, flags));
 258 }
 |