1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. 14 */ 15 16 /* 17 * Dispatch function for SMB2_SET_INFO 18 * 19 * [MS-FSCC 2.4] If a file system does not support ... 20 * an Information Classs, NT_STATUS_INVALID_PARAMETER... 21 */ 22 23 #include <smbsrv/smb2_kproto.h> 24 #include <smbsrv/smb_fsops.h> 25 #include <smbsrv/ntifs.h> 26 27 static uint32_t smb2_setf_rename(smb_request_t *, smb_setinfo_t *); 28 static uint32_t smb2_setf_link(smb_request_t *, smb_setinfo_t *); 29 30 static uint32_t smb2_setf_seek(smb_request_t *, smb_setinfo_t *); 31 static uint32_t smb2_setf_full_ea(smb_request_t *, smb_setinfo_t *); 32 static uint32_t smb2_setf_mode(smb_request_t *, smb_setinfo_t *); 33 34 static uint32_t smb2_setf_pipe(smb_request_t *, smb_setinfo_t *); 35 static uint32_t smb2_setf_valid_len(smb_request_t *, smb_setinfo_t *); 36 static uint32_t smb2_setf_shortname(smb_request_t *, smb_setinfo_t *); 37 38 39 uint32_t 40 smb2_setinfo_file(smb_request_t *sr, smb_setinfo_t *si, int InfoClass) 41 { 42 smb_ofile_t *of = sr->fid_ofile; 43 uint32_t status; 44 45 si->si_node = of->f_node; 46 47 /* Most info levels need a disk file */ 48 switch (of->f_ftype) { 49 case SMB_FTYPE_DISK: 50 case SMB_FTYPE_PRINTER: 51 break; 52 case SMB_FTYPE_BYTE_PIPE: 53 case SMB_FTYPE_MESG_PIPE: 54 if (InfoClass != FilePipeInformation) 55 return (NT_STATUS_INVALID_PARAMETER); 56 break; 57 default: 58 return (NT_STATUS_INTERNAL_ERROR); 59 break; 60 } 61 62 switch (InfoClass) { 63 case FileBasicInformation: /* 4 */ 64 status = smb_set_basic_info(sr, si); 65 break; 66 case FileRenameInformation: /* 10 */ 67 status = smb2_setf_rename(sr, si); 68 break; 69 case FileLinkInformation: /* 11 */ 70 status = smb2_setf_link(sr, si); 71 break; 72 case FileDispositionInformation: /* 13 */ 73 status = smb_set_disposition_info(sr, si); 74 break; 75 case FilePositionInformation: /* 14 */ 76 status = smb2_setf_seek(sr, si); 77 break; 78 case FileFullEaInformation: /* 15 */ 79 status = smb2_setf_full_ea(sr, si); 80 break; 81 case FileModeInformation: /* 16 */ 82 status = smb2_setf_mode(sr, si); 83 break; 84 case FileAllocationInformation: /* 19 */ 85 status = smb_set_alloc_info(sr, si); 86 break; 87 case FileEndOfFileInformation: /* 20 */ 88 status = smb_set_eof_info(sr, si); 89 break; 90 case FilePipeInformation: /* 23 */ 91 status = smb2_setf_pipe(sr, si); 92 break; 93 case FileValidDataLengthInformation: /* 39 */ 94 status = smb2_setf_valid_len(sr, si); 95 break; 96 case FileShortNameInformation: /* 40 */ 97 status = smb2_setf_shortname(sr, si); 98 break; 99 default: 100 status = NT_STATUS_INVALID_INFO_CLASS; 101 break; 102 } 103 104 return (status); 105 } 106 107 108 /* 109 * FileRenameInformation 110 * See also: smb_set_rename_info() 111 */ 112 static uint32_t 113 smb2_setf_rename(smb_request_t *sr, smb_setinfo_t *si) 114 { 115 char *fname; 116 uint8_t flags; 117 uint64_t rootdir; 118 uint32_t namelen; 119 uint32_t status = 0; 120 int rc; 121 122 rc = smb_mbc_decodef(&si->si_data, "b7.ql", 123 &flags, &rootdir, &namelen); 124 if (rc == 0) { 125 rc = smb_mbc_decodef(&si->si_data, "%#U", 126 sr, namelen, &fname); 127 } 128 if (rc != 0) 129 return (NT_STATUS_INFO_LENGTH_MISMATCH); 130 131 if ((rootdir != 0) || (namelen == 0) || (namelen >= SMB_MAXPATHLEN)) { 132 return (NT_STATUS_INVALID_PARAMETER); 133 } 134 135 status = smb_setinfo_rename(sr, si->si_node, fname, flags); 136 137 return (status); 138 } 139 140 /* 141 * FileLinkInformation 142 */ 143 static uint32_t 144 smb2_setf_link(smb_request_t *sr, smb_setinfo_t *si) 145 { 146 char *fname; 147 uint8_t flags; 148 uint64_t rootdir; 149 uint32_t namelen; 150 uint32_t status = 0; 151 int rc; 152 153 rc = smb_mbc_decodef(&si->si_data, "b7.ql", 154 &flags, &rootdir, &namelen); 155 if (rc == 0) { 156 rc = smb_mbc_decodef(&si->si_data, "%#U", 157 sr, namelen, &fname); 158 } 159 if (rc != 0) 160 return (NT_STATUS_INFO_LENGTH_MISMATCH); 161 162 if ((rootdir != 0) || (namelen == 0) || (namelen >= SMB_MAXPATHLEN)) { 163 return (NT_STATUS_INVALID_PARAMETER); 164 } 165 166 status = smb_setinfo_link(sr, si->si_node, fname, flags); 167 168 return (status); 169 } 170 171 172 /* 173 * FilePositionInformation 174 */ 175 static uint32_t 176 smb2_setf_seek(smb_request_t *sr, smb_setinfo_t *si) 177 { 178 smb_ofile_t *of = sr->fid_ofile; 179 uint64_t newoff; 180 181 if (smb_mbc_decodef(&si->si_data, "q", &newoff) != 0) 182 return (NT_STATUS_INVALID_PARAMETER); 183 184 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 185 mutex_enter(&of->f_mutex); 186 of->f_seek_pos = newoff; 187 mutex_exit(&of->f_mutex); 188 189 return (0); 190 } 191 192 /* 193 * FileFullEaInformation 194 * We could put EAs in a named stream... 195 */ 196 /* ARGSUSED */ 197 static uint32_t 198 smb2_setf_full_ea(smb_request_t *sr, smb_setinfo_t *si) 199 { 200 return (NT_STATUS_EAS_NOT_SUPPORTED); 201 } 202 203 /* 204 * FileModeInformation [MS-FSCC 2.4.24] 205 * FILE_WRITE_THROUGH 206 * FILE_SEQUENTIAL_ONLY 207 * FILE_NO_INTERMEDIATE_BUFFERING 208 * etc. 209 */ 210 static uint32_t 211 smb2_setf_mode(smb_request_t *sr, smb_setinfo_t *si) 212 { 213 _NOTE(ARGUNUSED(sr)) 214 uint32_t Mode; 215 216 if (smb_mbc_decodef(&si->si_data, "l", &Mode) != 0) 217 return (NT_STATUS_INVALID_PARAMETER); 218 219 #if 0 /* XXX - todo */ 220 if (Mode & FILE_WRITE_THROUGH) { 221 /* store this in the ofile */ 222 } 223 #endif 224 225 return (NT_STATUS_SUCCESS); 226 } 227 228 229 230 /* 231 * FilePipeInformation 232 */ 233 static uint32_t 234 smb2_setf_pipe(smb_request_t *sr, smb_setinfo_t *si) 235 { 236 _NOTE(ARGUNUSED(si)) 237 smb_ofile_t *of = sr->fid_ofile; 238 uint32_t ReadMode; 239 uint32_t CompletionMode; 240 uint32_t status; 241 242 if (smb_mbc_decodef(&si->si_data, "ll", 243 &ReadMode, &CompletionMode) != 0) 244 return (NT_STATUS_INFO_LENGTH_MISMATCH); 245 246 switch (of->f_ftype) { 247 case SMB_FTYPE_BYTE_PIPE: 248 case SMB_FTYPE_MESG_PIPE: 249 /* 250 * XXX: Do we need to actually do anything with 251 * ReadMode or CompletionMode? If so, (later) 252 * store these in the opipe object. 253 * 254 * See also: smb2_sif_pipe() 255 */ 256 status = 0; 257 break; 258 case SMB_FTYPE_DISK: 259 case SMB_FTYPE_PRINTER: 260 default: 261 status = NT_STATUS_INVALID_PARAMETER; 262 } 263 264 return (status); 265 } 266 267 /* 268 * FileValidDataLengthInformation 269 */ 270 /* ARGSUSED */ 271 static uint32_t 272 smb2_setf_valid_len(smb_request_t *sr, smb_setinfo_t *si) 273 { 274 smb_ofile_t *of = sr->fid_ofile; 275 uint64_t eod; 276 int rc; 277 278 if (smb_mbc_decodef(&si->si_data, "q", &eod) != 0) 279 return (NT_STATUS_INFO_LENGTH_MISMATCH); 280 281 /* 282 * Zero out data from EoD to end of file. 283 * (Passing len=0 covers to end of file) 284 */ 285 rc = smb_fsop_freesp(sr, of->f_cr, of, eod, 0); 286 if (rc != 0) 287 return (smb_errno2status(rc)); 288 289 return (0); 290 } 291 292 /* 293 * FileShortNameInformation 294 * We can (optionally) support supply short names, 295 * but you can't change them. 296 */ 297 static uint32_t 298 smb2_setf_shortname(smb_request_t *sr, smb_setinfo_t *si) 299 { 300 _NOTE(ARGUNUSED(si)) 301 smb_ofile_t *of = sr->fid_ofile; 302 303 if (of->f_ftype != SMB_FTYPE_DISK) 304 return (NT_STATUS_INVALID_PARAMETER); 305 if ((of->f_tree->t_flags & SMB_TREE_SHORTNAMES) == 0) 306 return (NT_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME); 307 308 return (NT_STATUS_ACCESS_DENIED); 309 } 310