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_1(op__Read__start, smb_request_t *, sr); /* arg.rw */ 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_1(op__Read__done, smb_request_t *, sr); /* arg.rw */ 85 86 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 87 } 88 89 smb_sdrc_t 90 smb_com_read(smb_request_t *sr) 91 { 92 smb_rw_param_t *param = sr->arg.rw; 93 uint16_t count; 94 int rc; 95 96 smbsr_lookup_file(sr); 97 if (sr->fid_ofile == NULL) { 98 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 99 return (SDRC_ERROR); 100 } 101 102 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 103 104 if (param->rw_count > SMB_CORE_READ_MAX) 105 param->rw_count = SMB_CORE_READ_MAX; 106 107 if ((rc = smb_common_read(sr, param)) != 0) { 108 smbsr_errno(sr, rc); 109 return (SDRC_ERROR); 110 } 111 112 count = (uint16_t)param->rw_count; 113 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 114 5, count, VAR_BCC, 0x01, count, &sr->raw_data); 115 116 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 117 } 118 119 /* 120 * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/ 121 * SmbLockAndWrite sub-dialect is only valid on disk files: reject any 122 * attempt to use it on non-disk shares. 123 * 124 * The requested count specifies the number of bytes desired. Offset 125 * specifies the offset in the file of the first byte to be locked then 126 * read. Note that offset is limited to 32 bits, so this client request 127 * is inappropriate for files with 64 bit offsets. 128 * 129 * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted 130 * immediately an error should be returned to the client. If an error 131 * occurs on the lock, the bytes should not be read. 132 * 133 * On return, count is the number of bytes actually being returned, which 134 * may be less than the count requested only if a read specifies bytes 135 * beyond the current file size. In this case only the bytes that exist 136 * are returned. A read completely beyond the end of file results in a 137 * response of length zero. This is the only circumstance when a zero 138 * length response is generated. A count returned which is less than the 139 * count requested is the end of file indicator. 140 */ 141 smb_sdrc_t 142 smb_pre_lock_and_read(smb_request_t *sr) 143 { 144 smb_rw_param_t *param; 145 uint32_t off_low; 146 uint16_t count; 147 uint16_t remcnt; 148 int rc; 149 150 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 151 sr->arg.rw = param; 152 153 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 154 &count, &off_low, &remcnt); 155 156 param->rw_offset = (uint64_t)off_low; 157 param->rw_count = (uint32_t)count; 158 param->rw_mincnt = 0; 159 160 DTRACE_SMB_1(op__LockAndRead__start, smb_request_t *, sr); /* arg.rw */ 161 162 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 163 } 164 165 void 166 smb_post_lock_and_read(smb_request_t *sr) 167 { 168 DTRACE_SMB_1(op__LockAndRead__done, smb_request_t *, sr); /* arg.rw */ 169 170 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 171 } 172 173 smb_sdrc_t 174 smb_com_lock_and_read(smb_request_t *sr) 175 { 176 smb_rw_param_t *param = sr->arg.rw; 177 DWORD status; 178 uint32_t lk_pid; 179 uint16_t count; 180 int rc; 181 182 if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 183 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); 184 return (SDRC_ERROR); 185 } 186 187 smbsr_lookup_file(sr); 188 if (sr->fid_ofile == NULL) { 189 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 190 return (SDRC_ERROR); 191 } 192 193 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 194 195 /* Note: SMB1 locking uses 16-bit PIDs. */ 196 lk_pid = sr->smb_pid & 0xFFFF; 197 198 status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count, 199 lk_pid, SMB_LOCK_TYPE_READWRITE, 0); 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 * The SMB_COM_READ_RAW protocol was a negotiated option introduced in 223 * SMB Core Plus to maximize performance when reading a large block 224 * of data from a server. It's obsolete and no longer supported. 225 * 226 * We keep a handler for it so the dtrace provider can see if 227 * the client tried to use this command. 228 */ 229 smb_sdrc_t 230 smb_pre_read_raw(smb_request_t *sr) 231 { 232 smb_rw_param_t *param; 233 uint32_t off_low; 234 uint32_t off_high; 235 uint32_t timeout; 236 uint16_t count; 237 int rc; 238 239 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 240 sr->arg.rw = param; 241 if (sr->smb_wct == 8) { 242 rc = smbsr_decode_vwv(sr, "wlwwl2.", &sr->smb_fid, 243 &off_low, &count, ¶m->rw_mincnt, &timeout); 244 if (rc == 0) { 245 param->rw_offset = (uint64_t)off_low; 246 param->rw_count = (uint32_t)count; 247 } 248 } else { 249 rc = smbsr_decode_vwv(sr, "wlwwl2.l", &sr->smb_fid, 250 &off_low, &count, ¶m->rw_mincnt, &timeout, &off_high); 251 if (rc == 0) { 252 param->rw_offset = ((uint64_t)off_high << 32) | off_low; 253 param->rw_count = (uint32_t)count; 254 } 255 } 256 DTRACE_SMB_1(op__ReadRaw__start, smb_request_t *, sr); /* arg.rw */ 257 return (SDRC_SUCCESS); 258 } 259 260 void 261 smb_post_read_raw(smb_request_t *sr) 262 { 263 DTRACE_SMB_1(op__ReadRaw__done, smb_request_t *, sr); /* arg.rw */ 264 265 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 266 } 267 268 smb_sdrc_t 269 smb_com_read_raw(smb_request_t *sr) 270 { 271 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS, 272 ERROR_NOT_SUPPORTED); 273 return (SDRC_ERROR); 274 } 275 276 /* 277 * Read bytes from a file (SMB Core). This request was extended in 278 * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 279 * 12 and including additional offset information. 280 * 281 * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4: 282 * If wct is 12 and CAP_LARGE_READX is set, the count may be larger 283 * than the negotiated buffer size. If maxcnt_high is 0xFF, it must 284 * be ignored. Otherwise, maxcnt_high represents the upper 16 bits 285 * of rw_count. 286 */ 287 smb_sdrc_t 288 smb_pre_read_andx(smb_request_t *sr) 289 { 290 smb_rw_param_t *param; 291 uint32_t off_low; 292 uint32_t off_high; 293 uint32_t maxcnt_high; 294 uint16_t maxcnt_low; 295 uint16_t mincnt; 296 uint16_t remcnt; 297 int rc; 298 299 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 300 sr->arg.rw = param; 301 302 if (sr->smb_wct == 12) { 303 rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx, 304 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 305 &remcnt, &off_high); 306 307 param->rw_offset = ((uint64_t)off_high << 32) | 308 (uint64_t)off_low; 309 310 param->rw_count = (uint32_t)maxcnt_low; 311 312 if ((sr->session->capabilities & CAP_LARGE_READX) && 313 (maxcnt_high < 0xFF)) 314 param->rw_count |= maxcnt_high << 16; 315 } else { 316 rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx, 317 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 318 &remcnt); 319 320 param->rw_offset = (uint64_t)off_low; 321 param->rw_count = (uint32_t)maxcnt_low; 322 } 323 324 param->rw_mincnt = 0; 325 326 DTRACE_SMB_1(op__ReadX__start, smb_request_t *, sr); /* arg.rw */ 327 328 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 329 } 330 331 void 332 smb_post_read_andx(smb_request_t *sr) 333 { 334 DTRACE_SMB_1(op__ReadX__done, smb_request_t *, sr); /* arg.rw */ 335 336 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 337 } 338 339 smb_sdrc_t 340 smb_com_read_andx(smb_request_t *sr) 341 { 342 smb_rw_param_t *param = sr->arg.rw; 343 uint16_t datalen_high; 344 uint16_t datalen_low; 345 uint16_t data_offset; 346 uint16_t offset2; 347 int rc; 348 349 smbsr_lookup_file(sr); 350 if (sr->fid_ofile == NULL) { 351 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 352 return (SDRC_ERROR); 353 } 354 355 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 356 357 if (param->rw_count >= SMB_READX_MAX) 358 param->rw_count = 0; 359 360 if ((rc = smb_common_read(sr, param)) != 0) { 361 smbsr_errno(sr, rc); 362 return (SDRC_ERROR); 363 } 364 365 datalen_low = param->rw_count & 0xFFFF; 366 datalen_high = (param->rw_count >> 16) & 0xFF; 367 368 /* 369 * If this is a secondary command, the data offset 370 * includes the previous wct + sizeof(wct). 371 */ 372 data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1; 373 374 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 375 data_offset += 60; 376 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60; 377 378 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC", 379 12, /* wct */ 380 param->rw_andx, /* secondary andx command */ 381 offset2, /* offset to next command */ 382 0, /* set to 0 for named pipes */ 383 datalen_low, /* data byte count */ 384 data_offset, /* offset from start to data */ 385 datalen_high, /* data byte count */ 386 VAR_BCC, /* BCC marker */ 387 0x00, /* padding */ 388 &sr->raw_data); 389 } else { 390 data_offset += 59; 391 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59; 392 393 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC", 394 12, /* wct */ 395 param->rw_andx, /* secondary andx command */ 396 offset2, /* offset to next command */ 397 -1, /* must be -1 for regular files */ 398 datalen_low, /* data byte count */ 399 data_offset, /* offset from start to data */ 400 datalen_high, /* data byte count */ 401 VAR_BCC, /* BCC marker */ 402 &sr->raw_data); 403 } 404 405 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 406 } 407 408 /* 409 * Common function for reading files or IPC/MSRPC named pipes. All 410 * protocol read functions should lookup the fid before calling this 411 * function. We can't move the fid lookup here because lock-and-read 412 * requires the fid to do locking before attempting the read. 413 * 414 * Reading from a file should break oplocks on the file to LEVEL_II. 415 * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not 416 * required as it is a no-op. If there's anything greater than a 417 * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile 418 * on which the read is occuring and therefore would not be broken. 419 * 420 * Returns errno values. 421 */ 422 int 423 smb_common_read(smb_request_t *sr, smb_rw_param_t *param) 424 { 425 smb_ofile_t *ofile = sr->fid_ofile; 426 smb_node_t *node; 427 smb_vdb_t *vdb = ¶m->rw_vdb; 428 struct mbuf *top; 429 int rc; 430 431 vdb->vdb_tag = 0; 432 vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0]; 433 vdb->vdb_uio.uio_iovcnt = MAX_IOVEC; 434 vdb->vdb_uio.uio_resid = param->rw_count; 435 vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset; 436 vdb->vdb_uio.uio_segflg = UIO_SYSSPACE; 437 vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 438 439 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 440 case STYPE_DISKTREE: 441 node = ofile->f_node; 442 443 if (!smb_node_is_dir(node)) { 444 rc = smb_lock_range_access(sr, node, param->rw_offset, 445 param->rw_count, B_FALSE); 446 if (rc != NT_STATUS_SUCCESS) { 447 rc = ERANGE; 448 break; 449 } 450 } 451 452 if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) && 453 !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) { 454 /* 455 * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only 456 * reads. 457 * 458 * Reject request if the file has been opened 459 * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not 460 * set. 461 */ 462 rc = EACCES; 463 break; 464 } 465 466 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 467 top = smb_mbuf_allocate(&vdb->vdb_uio); 468 469 rc = smb_fsop_read(sr, sr->user_cr, node, ofile, 470 &vdb->vdb_uio); 471 472 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 473 smb_mbuf_trim(top, sr->raw_data.max_bytes); 474 MBC_ATTACH_MBUF(&sr->raw_data, top); 475 break; 476 477 case STYPE_IPC: 478 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 479 top = smb_mbuf_allocate(&vdb->vdb_uio); 480 481 rc = smb_opipe_read(sr, &vdb->vdb_uio); 482 483 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 484 smb_mbuf_trim(top, sr->raw_data.max_bytes); 485 MBC_ATTACH_MBUF(&sr->raw_data, top); 486 break; 487 488 default: 489 rc = EACCES; 490 break; 491 } 492 493 param->rw_count -= vdb->vdb_uio.uio_resid; 494 495 if (rc != 0) 496 return (rc); 497 498 if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) { 499 /* 500 * mincnt is only used by read-raw and is typically 501 * zero. If mincnt is greater than zero and the 502 * number of bytes read is less than mincnt, tell 503 * the client that we read nothing. 504 */ 505 param->rw_count = 0; 506 } 507 508 param->rw_offset += param->rw_count; 509 mutex_enter(&sr->fid_ofile->f_mutex); 510 ofile->f_seek_pos = param->rw_offset; 511 mutex_exit(&sr->fid_ofile->f_mutex); 512 return (rc); 513 }