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 2015 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 uint16_t count; 183 int rc; 184 185 if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 186 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); 187 return (SDRC_ERROR); 188 } 189 190 smbsr_lookup_file(sr); 191 if (sr->fid_ofile == NULL) { 192 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 193 return (SDRC_ERROR); 194 } 195 196 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 197 198 status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count, 199 0, SMB_LOCK_TYPE_READWRITE); 200 201 if (status != NT_STATUS_SUCCESS) { 202 smb_lock_range_error(sr, status); 203 return (SDRC_ERROR); 204 } 205 206 if (param->rw_count > SMB_CORE_READ_MAX) 207 param->rw_count = SMB_CORE_READ_MAX; 208 209 if ((rc = smb_common_read(sr, param)) != 0) { 210 smbsr_errno(sr, rc); 211 return (SDRC_ERROR); 212 } 213 214 count = (uint16_t)param->rw_count; 215 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 216 5, count, VAR_BCC, 0x1, count, &sr->raw_data); 217 218 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 219 } 220 221 /* 222 * Read bytes from a file (SMB Core). This request was extended in 223 * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 224 * 12 and including additional offset information. 225 * 226 * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4: 227 * If wct is 12 and CAP_LARGE_READX is set, the count may be larger 228 * than the negotiated buffer size. If maxcnt_high is 0xFF, it must 229 * be ignored. Otherwise, maxcnt_high represents the upper 16 bits 230 * of rw_count. 231 */ 232 smb_sdrc_t 233 smb_pre_read_andx(smb_request_t *sr) 234 { 235 smb_rw_param_t *param; 236 uint32_t off_low; 237 uint32_t off_high; 238 uint32_t maxcnt_high; 239 uint16_t maxcnt_low; 240 uint16_t mincnt; 241 uint16_t remcnt; 242 int rc; 243 244 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 245 sr->arg.rw = param; 246 247 if (sr->smb_wct == 12) { 248 rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx, 249 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 250 &remcnt, &off_high); 251 252 param->rw_offset = ((uint64_t)off_high << 32) | 253 (uint64_t)off_low; 254 255 param->rw_count = (uint32_t)maxcnt_low; 256 257 if ((sr->session->capabilities & CAP_LARGE_READX) && 258 (maxcnt_high < 0xFF)) 259 param->rw_count |= maxcnt_high << 16; 260 } else { 261 rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx, 262 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 263 &remcnt); 264 265 param->rw_offset = (uint64_t)off_low; 266 param->rw_count = (uint32_t)maxcnt_low; 267 } 268 269 param->rw_mincnt = 0; 270 271 DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr, 272 smb_rw_param_t *, param); 273 274 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 275 } 276 277 void 278 smb_post_read_andx(smb_request_t *sr) 279 { 280 DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr, 281 smb_rw_param_t *, sr->arg.rw); 282 283 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 284 } 285 286 smb_sdrc_t 287 smb_com_read_andx(smb_request_t *sr) 288 { 289 smb_rw_param_t *param = sr->arg.rw; 290 uint16_t datalen_high; 291 uint16_t datalen_low; 292 uint16_t data_offset; 293 uint16_t offset2; 294 int rc; 295 296 smbsr_lookup_file(sr); 297 if (sr->fid_ofile == NULL) { 298 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 299 return (SDRC_ERROR); 300 } 301 302 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 303 304 if (param->rw_count >= SMB_READX_MAX) 305 param->rw_count = 0; 306 307 if ((rc = smb_common_read(sr, param)) != 0) { 308 smbsr_errno(sr, rc); 309 return (SDRC_ERROR); 310 } 311 312 datalen_low = param->rw_count & 0xFFFF; 313 datalen_high = (param->rw_count >> 16) & 0xFF; 314 315 /* 316 * If this is a secondary command, the data offset 317 * includes the previous wct + sizeof(wct). 318 */ 319 data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1; 320 321 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 322 data_offset += 60; 323 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60; 324 325 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC", 326 12, /* wct */ 327 param->rw_andx, /* secondary andx command */ 328 offset2, /* offset to next command */ 329 0, /* set to 0 for named pipes */ 330 datalen_low, /* data byte count */ 331 data_offset, /* offset from start to data */ 332 datalen_high, /* data byte count */ 333 VAR_BCC, /* BCC marker */ 334 0x00, /* padding */ 335 &sr->raw_data); 336 } else { 337 data_offset += 59; 338 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59; 339 340 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC", 341 12, /* wct */ 342 param->rw_andx, /* secondary andx command */ 343 offset2, /* offset to next command */ 344 -1, /* must be -1 for regular files */ 345 datalen_low, /* data byte count */ 346 data_offset, /* offset from start to data */ 347 datalen_high, /* data byte count */ 348 VAR_BCC, /* BCC marker */ 349 &sr->raw_data); 350 } 351 352 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 353 } 354 355 /* 356 * Common function for reading files or IPC/MSRPC named pipes. All 357 * protocol read functions should lookup the fid before calling this 358 * function. We can't move the fid lookup here because lock-and-read 359 * requires the fid to do locking before attempting the read. 360 * 361 * Reading from a file should break oplocks on the file to LEVEL_II. 362 * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not 363 * required as it is a no-op. If there's anything greater than a 364 * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile 365 * on which the read is occuring and therefore would not be broken. 366 * 367 * Returns errno values. 368 */ 369 int 370 smb_common_read(smb_request_t *sr, smb_rw_param_t *param) 371 { 372 smb_ofile_t *ofile = sr->fid_ofile; 373 smb_node_t *node; 374 smb_vdb_t *vdb = ¶m->rw_vdb; 375 struct mbuf *top; 376 int rc; 377 378 vdb->vdb_tag = 0; 379 vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0]; 380 vdb->vdb_uio.uio_iovcnt = MAX_IOVEC; 381 vdb->vdb_uio.uio_resid = param->rw_count; 382 vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset; 383 vdb->vdb_uio.uio_segflg = UIO_SYSSPACE; 384 vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 385 386 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 387 case STYPE_DISKTREE: 388 node = ofile->f_node; 389 390 if (!smb_node_is_dir(node)) { 391 rc = smb_lock_range_access(sr, node, param->rw_offset, 392 param->rw_count, B_FALSE); 393 if (rc != NT_STATUS_SUCCESS) { 394 rc = ERANGE; 395 break; 396 } 397 } 398 399 if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) && 400 !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) { 401 /* 402 * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only 403 * reads. 404 * 405 * Reject request if the file has been opened 406 * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not 407 * set. 408 */ 409 rc = EACCES; 410 break; 411 } 412 413 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 414 top = smb_mbuf_allocate(&vdb->vdb_uio); 415 416 rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio); 417 418 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 419 smb_mbuf_trim(top, sr->raw_data.max_bytes); 420 MBC_ATTACH_MBUF(&sr->raw_data, top); 421 break; 422 423 case STYPE_IPC: 424 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 425 top = smb_mbuf_allocate(&vdb->vdb_uio); 426 427 rc = smb_opipe_read(sr, &vdb->vdb_uio); 428 429 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 430 smb_mbuf_trim(top, sr->raw_data.max_bytes); 431 MBC_ATTACH_MBUF(&sr->raw_data, top); 432 break; 433 434 default: 435 rc = EACCES; 436 break; 437 } 438 439 param->rw_count -= vdb->vdb_uio.uio_resid; 440 441 if (rc != 0) 442 return (rc); 443 444 if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) { 445 /* 446 * mincnt is only used by read-raw and is typically 447 * zero. If mincnt is greater than zero and the 448 * number of bytes read is less than mincnt, tell 449 * the client that we read nothing. 450 */ 451 param->rw_count = 0; 452 } 453 454 param->rw_offset += param->rw_count; 455 mutex_enter(&sr->fid_ofile->f_mutex); 456 ofile->f_seek_pos = param->rw_offset; 457 mutex_exit(&sr->fid_ofile->f_mutex); 458 return (rc); 459 } 460