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