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