1 /* 2 * CDDL HEADER START 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 2016 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 #include <smbsrv/smb_kproto.h> 27 #include <smbsrv/smb_fsops.h> 28 29 /* 30 * The maximum number of bytes to return from SMB Core 31 * SmbRead or SmbLockAndRead. 32 */ 33 #define SMB_CORE_READ_MAX 4432 34 35 /* 36 * The limit in bytes for SmbReadX. 37 */ 38 #define SMB_READX_MAX 0x10000 39 40 int smb_common_read(smb_request_t *, smb_rw_param_t *); 41 42 /* 43 * Read bytes from a file or named pipe (SMB Core). 44 * 45 * The requested count specifies the number of bytes desired. Offset 46 * is limited to 32 bits, so this client request is inappropriate for 47 * files with 64 bit offsets. 48 * 49 * On return, count is the number of bytes actually being returned, which 50 * may be less than the count requested only if a read specifies bytes 51 * beyond the current file size. In this case only the bytes that exist 52 * are returned. A read completely beyond the end of file results in a 53 * response of length zero. This is the only circumstance when a zero 54 * length response is generated. A count returned which is less than the 55 * count requested is the end of file indicator. 56 */ 57 smb_sdrc_t 58 smb_pre_read(smb_request_t *sr) 59 { 60 smb_rw_param_t *param; 61 uint32_t off_low; 62 uint16_t count; 63 uint16_t remcnt; 64 int rc; 65 66 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 67 sr->arg.rw = param; 68 69 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 70 &count, &off_low, &remcnt); 71 72 param->rw_offset = (uint64_t)off_low; 73 param->rw_count = (uint32_t)count; 74 param->rw_mincnt = 0; 75 76 DTRACE_SMB_2(op__Read__start, smb_request_t *, sr, 77 smb_rw_param_t *, param); 78 79 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 80 } 81 82 void 83 smb_post_read(smb_request_t *sr) 84 { 85 DTRACE_SMB_2(op__Read__done, smb_request_t *, sr, 86 smb_rw_param_t *, sr->arg.rw); 87 88 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 89 } 90 91 smb_sdrc_t 92 smb_com_read(smb_request_t *sr) 93 { 94 smb_rw_param_t *param = sr->arg.rw; 95 uint16_t count; 96 int rc; 97 98 smbsr_lookup_file(sr); 99 if (sr->fid_ofile == NULL) { 100 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 101 return (SDRC_ERROR); 102 } 103 104 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 105 106 if (param->rw_count > SMB_CORE_READ_MAX) 107 param->rw_count = SMB_CORE_READ_MAX; 108 109 if ((rc = smb_common_read(sr, param)) != 0) { 110 smbsr_errno(sr, rc); 111 return (SDRC_ERROR); 112 } 113 114 count = (uint16_t)param->rw_count; 115 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 116 5, count, VAR_BCC, 0x01, count, &sr->raw_data); 117 118 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 119 } 120 121 /* 122 * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/ 123 * SmbLockAndWrite sub-dialect is only valid on disk files: reject any 124 * attempt to use it on non-disk shares. 125 * 126 * The requested count specifies the number of bytes desired. Offset 127 * specifies the offset in the file of the first byte to be locked then 128 * read. Note that offset is limited to 32 bits, so this client request 129 * is inappropriate for files with 64 bit offsets. 130 * 131 * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted 132 * immediately an error should be returned to the client. If an error 133 * occurs on the lock, the bytes should not be read. 134 * 135 * On return, count is the number of bytes actually being returned, which 136 * may be less than the count requested only if a read specifies bytes 137 * beyond the current file size. In this case only the bytes that exist 138 * are returned. A read completely beyond the end of file results in a 139 * response of length zero. This is the only circumstance when a zero 140 * length response is generated. A count returned which is less than the 141 * count requested is the end of file indicator. 142 */ 143 smb_sdrc_t 144 smb_pre_lock_and_read(smb_request_t *sr) 145 { 146 smb_rw_param_t *param; 147 uint32_t off_low; 148 uint16_t count; 149 uint16_t remcnt; 150 int rc; 151 152 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 153 sr->arg.rw = param; 154 155 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 156 &count, &off_low, &remcnt); 157 158 param->rw_offset = (uint64_t)off_low; 159 param->rw_count = (uint32_t)count; 160 param->rw_mincnt = 0; 161 162 DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr, 163 smb_rw_param_t *, param); 164 165 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 166 } 167 168 void 169 smb_post_lock_and_read(smb_request_t *sr) 170 { 171 DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr, 172 smb_rw_param_t *, sr->arg.rw); 173 174 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 175 } 176 177 smb_sdrc_t 178 smb_com_lock_and_read(smb_request_t *sr) 179 { 180 smb_rw_param_t *param = sr->arg.rw; 181 DWORD status; 182 uint32_t lk_pid; 183 uint16_t count; 184 int rc; 185 186 if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 187 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); 188 return (SDRC_ERROR); 189 } 190 191 smbsr_lookup_file(sr); 192 if (sr->fid_ofile == NULL) { 193 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 194 return (SDRC_ERROR); 195 } 196 197 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 198 199 /* Note: SMB1 locking uses 16-bit PIDs. */ 200 lk_pid = sr->smb_pid & 0xFFFF; 201 202 status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count, 203 lk_pid, SMB_LOCK_TYPE_READWRITE, 0); 204 205 if (status != NT_STATUS_SUCCESS) { 206 smb_lock_range_error(sr, status); 207 return (SDRC_ERROR); 208 } 209 210 if (param->rw_count > SMB_CORE_READ_MAX) 211 param->rw_count = SMB_CORE_READ_MAX; 212 213 if ((rc = smb_common_read(sr, param)) != 0) { 214 smbsr_errno(sr, rc); 215 return (SDRC_ERROR); 216 } 217 218 count = (uint16_t)param->rw_count; 219 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 220 5, count, VAR_BCC, 0x1, count, &sr->raw_data); 221 222 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 223 } 224 225 /* 226 * Read bytes from a file (SMB Core). This request was extended in 227 * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 228 * 12 and including additional offset information. 229 * 230 * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4: 231 * If wct is 12 and CAP_LARGE_READX is set, the count may be larger 232 * than the negotiated buffer size. If maxcnt_high is 0xFF, it must 233 * be ignored. Otherwise, maxcnt_high represents the upper 16 bits 234 * of rw_count. 235 */ 236 smb_sdrc_t 237 smb_pre_read_andx(smb_request_t *sr) 238 { 239 smb_rw_param_t *param; 240 uint32_t off_low; 241 uint32_t off_high; 242 uint32_t maxcnt_high; 243 uint16_t maxcnt_low; 244 uint16_t mincnt; 245 uint16_t remcnt; 246 int rc; 247 248 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 249 sr->arg.rw = param; 250 251 if (sr->smb_wct == 12) { 252 rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx, 253 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 254 &remcnt, &off_high); 255 256 param->rw_offset = ((uint64_t)off_high << 32) | 257 (uint64_t)off_low; 258 259 param->rw_count = (uint32_t)maxcnt_low; 260 261 if ((sr->session->capabilities & CAP_LARGE_READX) && 262 (maxcnt_high < 0xFF)) 263 param->rw_count |= maxcnt_high << 16; 264 } else { 265 rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx, 266 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 267 &remcnt); 268 269 param->rw_offset = (uint64_t)off_low; 270 param->rw_count = (uint32_t)maxcnt_low; 271 } 272 273 param->rw_mincnt = 0; 274 275 DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr, 276 smb_rw_param_t *, param); 277 278 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 279 } 280 281 void 282 smb_post_read_andx(smb_request_t *sr) 283 { 284 DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr, 285 smb_rw_param_t *, sr->arg.rw); 286 287 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 288 } 289 290 smb_sdrc_t 291 smb_com_read_andx(smb_request_t *sr) 292 { 293 smb_rw_param_t *param = sr->arg.rw; 294 uint16_t datalen_high; 295 uint16_t datalen_low; 296 uint16_t data_offset; 297 uint16_t offset2; 298 int rc; 299 300 smbsr_lookup_file(sr); 301 if (sr->fid_ofile == NULL) { 302 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 303 return (SDRC_ERROR); 304 } 305 306 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 307 308 if (param->rw_count >= SMB_READX_MAX) 309 param->rw_count = 0; 310 311 if ((rc = smb_common_read(sr, param)) != 0) { 312 smbsr_errno(sr, rc); 313 return (SDRC_ERROR); 314 } 315 316 datalen_low = param->rw_count & 0xFFFF; 317 datalen_high = (param->rw_count >> 16) & 0xFF; 318 319 /* 320 * If this is a secondary command, the data offset 321 * includes the previous wct + sizeof(wct). 322 */ 323 data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1; 324 325 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 326 data_offset += 60; 327 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60; 328 329 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC", 330 12, /* wct */ 331 param->rw_andx, /* secondary andx command */ 332 offset2, /* offset to next command */ 333 0, /* set to 0 for named pipes */ 334 datalen_low, /* data byte count */ 335 data_offset, /* offset from start to data */ 336 datalen_high, /* data byte count */ 337 VAR_BCC, /* BCC marker */ 338 0x00, /* padding */ 339 &sr->raw_data); 340 } else { 341 data_offset += 59; 342 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59; 343 344 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC", 345 12, /* wct */ 346 param->rw_andx, /* secondary andx command */ 347 offset2, /* offset to next command */ 348 -1, /* must be -1 for regular files */ 349 datalen_low, /* data byte count */ 350 data_offset, /* offset from start to data */ 351 datalen_high, /* data byte count */ 352 VAR_BCC, /* BCC marker */ 353 &sr->raw_data); 354 } 355 356 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 357 } 358 359 /* 360 * Common function for reading files or IPC/MSRPC named pipes. All 361 * protocol read functions should lookup the fid before calling this 362 * function. We can't move the fid lookup here because lock-and-read 363 * requires the fid to do locking before attempting the read. 364 * 365 * Reading from a file should break oplocks on the file to LEVEL_II. 366 * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not 367 * required as it is a no-op. If there's anything greater than a 368 * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile 369 * on which the read is occuring and therefore would not be broken. 370 * 371 * Returns errno values. 372 */ 373 int 374 smb_common_read(smb_request_t *sr, smb_rw_param_t *param) 375 { 376 smb_ofile_t *ofile = sr->fid_ofile; 377 smb_node_t *node; 378 smb_vdb_t *vdb = ¶m->rw_vdb; 379 struct mbuf *top; 380 int rc; 381 382 vdb->vdb_tag = 0; 383 vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0]; 384 vdb->vdb_uio.uio_iovcnt = MAX_IOVEC; 385 vdb->vdb_uio.uio_resid = param->rw_count; 386 vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset; 387 vdb->vdb_uio.uio_segflg = UIO_SYSSPACE; 388 vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 389 390 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 391 case STYPE_DISKTREE: 392 node = ofile->f_node; 393 394 if (!smb_node_is_dir(node)) { 395 rc = smb_lock_range_access(sr, node, param->rw_offset, 396 param->rw_count, B_FALSE); 397 if (rc != NT_STATUS_SUCCESS) { 398 rc = ERANGE; 399 break; 400 } 401 } 402 403 if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) && 404 !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) { 405 /* 406 * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only 407 * reads. 408 * 409 * Reject request if the file has been opened 410 * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not 411 * set. 412 */ 413 rc = EACCES; 414 break; 415 } 416 417 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 418 top = smb_mbuf_allocate(&vdb->vdb_uio); 419 420 rc = smb_fsop_read(sr, sr->user_cr, node, ofile, 421 &vdb->vdb_uio); 422 423 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 424 smb_mbuf_trim(top, sr->raw_data.max_bytes); 425 MBC_ATTACH_MBUF(&sr->raw_data, top); 426 break; 427 428 case STYPE_IPC: 429 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 430 top = smb_mbuf_allocate(&vdb->vdb_uio); 431 432 rc = smb_opipe_read(sr, &vdb->vdb_uio); 433 434 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 435 smb_mbuf_trim(top, sr->raw_data.max_bytes); 436 MBC_ATTACH_MBUF(&sr->raw_data, top); 437 break; 438 439 default: 440 rc = EACCES; 441 break; 442 } 443 444 param->rw_count -= vdb->vdb_uio.uio_resid; 445 446 if (rc != 0) 447 return (rc); 448 449 if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) { 450 /* 451 * mincnt is only used by read-raw and is typically 452 * zero. If mincnt is greater than zero and the 453 * number of bytes read is less than mincnt, tell 454 * the client that we read nothing. 455 */ 456 param->rw_count = 0; 457 } 458 459 param->rw_offset += param->rw_count; 460 mutex_enter(&sr->fid_ofile->f_mutex); 461 ofile->f_seek_pos = param->rw_offset; 462 mutex_exit(&sr->fid_ofile->f_mutex); 463 return (rc); 464 }