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 * There may be oplock break requests waiting to be sent after 30 * a read raw request completes. 31 */ 32 #define SMB_OPLOCK_BREAKS_PENDING(sr) \ 33 !list_is_empty(&(sr)->session->s_oplock_brkreqs) 34 35 /* 36 * The maximum number of bytes to return from SMB Core 37 * SmbRead or SmbLockAndRead. 38 */ 39 #define SMB_CORE_READ_MAX 4432 40 41 /* 42 * The limit in bytes for SmbReadX. 43 */ 44 #define SMB_READX_MAX 0x10000 45 46 int smb_common_read(smb_request_t *, smb_rw_param_t *); 47 48 /* 49 * Read bytes from a file or named pipe (SMB Core). 50 * 51 * The requested count specifies the number of bytes desired. Offset 52 * is limited to 32 bits, so this client request is inappropriate for 53 * files with 64 bit offsets. 54 * 55 * On return, count is the number of bytes actually being returned, which 56 * may be less than the count requested only if a read specifies bytes 57 * beyond the current file size. In this case only the bytes that exist 58 * are returned. A read completely beyond the end of file results in a 59 * response of length zero. This is the only circumstance when a zero 60 * length response is generated. A count returned which is less than the 61 * count requested is the end of file indicator. 62 */ 63 smb_sdrc_t 64 smb_pre_read(smb_request_t *sr) 65 { 66 smb_rw_param_t *param; 67 uint32_t off_low; 68 uint16_t count; 69 uint16_t remcnt; 70 int rc; 71 72 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 73 sr->arg.rw = param; 74 75 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 76 &count, &off_low, &remcnt); 77 78 param->rw_offset = (uint64_t)off_low; 79 param->rw_count = (uint32_t)count; 80 param->rw_mincnt = 0; 81 82 DTRACE_SMB_2(op__Read__start, smb_request_t *, sr, 83 smb_rw_param_t *, param); 84 85 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 86 } 87 88 void 89 smb_post_read(smb_request_t *sr) 90 { 91 DTRACE_SMB_2(op__Read__done, smb_request_t *, sr, 92 smb_rw_param_t *, sr->arg.rw); 93 94 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 95 } 96 97 smb_sdrc_t 98 smb_com_read(smb_request_t *sr) 99 { 100 smb_rw_param_t *param = sr->arg.rw; 101 uint16_t count; 102 int rc; 103 104 smbsr_lookup_file(sr); 105 if (sr->fid_ofile == NULL) { 106 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 107 return (SDRC_ERROR); 108 } 109 110 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 111 112 if (param->rw_count > SMB_CORE_READ_MAX) 113 param->rw_count = SMB_CORE_READ_MAX; 114 115 if ((rc = smb_common_read(sr, param)) != 0) { 116 smbsr_errno(sr, rc); 117 return (SDRC_ERROR); 118 } 119 120 count = (uint16_t)param->rw_count; 121 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 122 5, count, VAR_BCC, 0x01, count, &sr->raw_data); 123 124 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 125 } 126 127 /* 128 * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/ 129 * SmbLockAndWrite sub-dialect is only valid on disk files: reject any 130 * attempt to use it on non-disk shares. 131 * 132 * The requested count specifies the number of bytes desired. Offset 133 * specifies the offset in the file of the first byte to be locked then 134 * read. Note that offset is limited to 32 bits, so this client request 135 * is inappropriate for files with 64 bit offsets. 136 * 137 * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted 138 * immediately an error should be returned to the client. If an error 139 * occurs on the lock, the bytes should not be read. 140 * 141 * On return, count is the number of bytes actually being returned, which 142 * may be less than the count requested only if a read specifies bytes 143 * beyond the current file size. In this case only the bytes that exist 144 * are returned. A read completely beyond the end of file results in a 145 * response of length zero. This is the only circumstance when a zero 146 * length response is generated. A count returned which is less than the 147 * count requested is the end of file indicator. 148 */ 149 smb_sdrc_t 150 smb_pre_lock_and_read(smb_request_t *sr) 151 { 152 smb_rw_param_t *param; 153 uint32_t off_low; 154 uint16_t count; 155 uint16_t remcnt; 156 int rc; 157 158 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 159 sr->arg.rw = param; 160 161 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 162 &count, &off_low, &remcnt); 163 164 param->rw_offset = (uint64_t)off_low; 165 param->rw_count = (uint32_t)count; 166 param->rw_mincnt = 0; 167 168 DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr, 169 smb_rw_param_t *, param); 170 171 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 172 } 173 174 void 175 smb_post_lock_and_read(smb_request_t *sr) 176 { 177 DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr, 178 smb_rw_param_t *, sr->arg.rw); 179 180 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 181 } 182 183 smb_sdrc_t 184 smb_com_lock_and_read(smb_request_t *sr) 185 { 186 smb_rw_param_t *param = sr->arg.rw; 187 DWORD status; 188 uint16_t count; 189 int rc; 190 191 if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 192 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); 193 return (SDRC_ERROR); 194 } 195 196 smbsr_lookup_file(sr); 197 if (sr->fid_ofile == NULL) { 198 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 199 return (SDRC_ERROR); 200 } 201 202 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 203 204 status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count, 205 0, SMB_LOCK_TYPE_READWRITE); 206 207 if (status != NT_STATUS_SUCCESS) { 208 smb_lock_range_error(sr, status); 209 return (SDRC_ERROR); 210 } 211 212 if (param->rw_count > SMB_CORE_READ_MAX) 213 param->rw_count = SMB_CORE_READ_MAX; 214 215 if ((rc = smb_common_read(sr, param)) != 0) { 216 smbsr_errno(sr, rc); 217 return (SDRC_ERROR); 218 } 219 220 count = (uint16_t)param->rw_count; 221 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 222 5, count, VAR_BCC, 0x1, count, &sr->raw_data); 223 224 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 225 } 226 227 /* 228 * The SMB_COM_READ_RAW protocol is a negotiated option introduced in 229 * SMB Core Plus to maximize performance when reading a large block 230 * of data from a server. This request was extended in LM 0.12 to 231 * support 64-bit offsets; the server can indicate support by setting 232 * CAP_LARGE_FILES in the negotiated capabilities. 233 * 234 * The client must guarantee that there is (and will be) no other request 235 * to the server for the duration of the SMB_COM_READ_RAW, since the 236 * server response has no header or trailer. To help ensure that there 237 * are no interruptions, we block all I/O for the session during read raw. 238 * 239 * If this is the first SMB request received since we sent an oplock break 240 * to this client, we don't know if it's safe to send the raw data because 241 * the requests may have crossed on the wire and the client may have 242 * interpreted the oplock break as part of the raw data. To avoid problems, 243 * we send a zero length session packet, which will force the client to 244 * retry the read. 245 * 246 * Do not return errors from SmbReadRaw. 247 * Read errors are handled by sending a zero length response. 248 */ 249 smb_sdrc_t 250 smb_pre_read_raw(smb_request_t *sr) 251 { 252 smb_rw_param_t *param; 253 uint32_t off_low; 254 uint32_t off_high; 255 uint32_t timeout; 256 uint16_t count; 257 int rc; 258 259 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 260 sr->arg.rw = param; 261 262 if (sr->smb_wct == 8) { 263 rc = smbsr_decode_vwv(sr, "wlwwl2.", &sr->smb_fid, 264 &off_low, &count, ¶m->rw_mincnt, &timeout); 265 if (rc == 0) { 266 param->rw_offset = (uint64_t)off_low; 267 param->rw_count = (uint32_t)count; 268 } 269 } else { 270 rc = smbsr_decode_vwv(sr, "wlwwl2.l", &sr->smb_fid, 271 &off_low, &count, ¶m->rw_mincnt, &timeout, &off_high); 272 if (rc == 0) { 273 param->rw_offset = ((uint64_t)off_high << 32) | off_low; 274 param->rw_count = (uint32_t)count; 275 } 276 } 277 278 DTRACE_SMB_2(op__ReadRaw__start, smb_request_t *, sr, 279 smb_rw_param_t *, param); 280 281 smb_rwx_rwenter(&sr->session->s_lock, RW_WRITER); 282 return (SDRC_SUCCESS); 283 } 284 285 void 286 smb_post_read_raw(smb_request_t *sr) 287 { 288 mbuf_chain_t *mbc; 289 290 if (sr->session->s_state == SMB_SESSION_STATE_READ_RAW_ACTIVE) { 291 if (SMB_OPLOCK_BREAKS_PENDING(sr)) { 292 sr->session->s_state = 293 SMB_SESSION_STATE_OPLOCK_BREAKING; 294 } else { 295 sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 296 } 297 298 while ((mbc = list_head(&sr->session->s_oplock_brkreqs)) != 299 NULL) { 300 SMB_MBC_VALID(mbc); 301 list_remove(&sr->session->s_oplock_brkreqs, mbc); 302 (void) smb_session_send(sr->session, 0, mbc); 303 smb_mbc_free(mbc); 304 } 305 } 306 307 DTRACE_SMB_2(op__ReadRaw__done, smb_request_t *, sr, 308 smb_rw_param_t *, sr->arg.rw); 309 310 smb_rwx_rwexit(&sr->session->s_lock); 311 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 312 } 313 314 smb_sdrc_t 315 smb_com_read_raw(smb_request_t *sr) 316 { 317 smb_rw_param_t *param = sr->arg.rw; 318 319 if (!smb_raw_mode) 320 return (SDRC_DROP_VC); 321 322 switch (sr->session->s_state) { 323 case SMB_SESSION_STATE_NEGOTIATED: 324 sr->session->s_state = SMB_SESSION_STATE_READ_RAW_ACTIVE; 325 break; 326 327 case SMB_SESSION_STATE_OPLOCK_BREAKING: 328 (void) smb_session_send(sr->session, 0, NULL); 329 return (SDRC_NO_REPLY); 330 331 case SMB_SESSION_STATE_TERMINATED: 332 case SMB_SESSION_STATE_DISCONNECTED: 333 return (SDRC_NO_REPLY); 334 335 case SMB_SESSION_STATE_READ_RAW_ACTIVE: 336 sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 337 return (SDRC_DROP_VC); 338 339 case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: 340 case SMB_SESSION_STATE_CONNECTED: 341 case SMB_SESSION_STATE_ESTABLISHED: 342 default: 343 return (SDRC_DROP_VC); 344 } 345 346 smbsr_lookup_file(sr); 347 if (sr->fid_ofile == NULL) { 348 (void) smb_session_send(sr->session, 0, NULL); 349 return (SDRC_NO_REPLY); 350 } 351 352 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 353 354 if (param->rw_mincnt > param->rw_count) 355 param->rw_mincnt = 0; 356 357 if ((smb_common_read(sr, param) != 0) || 358 (SMB_OPLOCK_BREAKS_PENDING(sr))) { 359 (void) smb_session_send(sr->session, 0, NULL); 360 m_freem(sr->raw_data.chain); 361 sr->raw_data.chain = NULL; 362 } else { 363 (void) smb_session_send(sr->session, 0, &sr->raw_data); 364 } 365 366 return (SDRC_NO_REPLY); 367 } 368 369 /* 370 * Read bytes from a file (SMB Core). This request was extended in 371 * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 372 * 12 and including additional offset information. 373 * 374 * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4: 375 * If wct is 12 and CAP_LARGE_READX is set, the count may be larger 376 * than the negotiated buffer size. If maxcnt_high is 0xFF, it must 377 * be ignored. Otherwise, maxcnt_high represents the upper 16 bits 378 * of rw_count. 379 */ 380 smb_sdrc_t 381 smb_pre_read_andx(smb_request_t *sr) 382 { 383 smb_rw_param_t *param; 384 uint32_t off_low; 385 uint32_t off_high; 386 uint32_t maxcnt_high; 387 uint16_t maxcnt_low; 388 uint16_t mincnt; 389 uint16_t remcnt; 390 int rc; 391 392 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP); 393 sr->arg.rw = param; 394 395 if (sr->smb_wct == 12) { 396 rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx, 397 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 398 &remcnt, &off_high); 399 400 param->rw_offset = ((uint64_t)off_high << 32) | 401 (uint64_t)off_low; 402 403 param->rw_count = (uint32_t)maxcnt_low; 404 405 if ((sr->session->capabilities & CAP_LARGE_READX) && 406 (maxcnt_high < 0xFF)) 407 param->rw_count |= maxcnt_high << 16; 408 } else { 409 rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx, 410 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high, 411 &remcnt); 412 413 param->rw_offset = (uint64_t)off_low; 414 param->rw_count = (uint32_t)maxcnt_low; 415 } 416 417 param->rw_mincnt = 0; 418 419 DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr, 420 smb_rw_param_t *, param); 421 422 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 423 } 424 425 void 426 smb_post_read_andx(smb_request_t *sr) 427 { 428 DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr, 429 smb_rw_param_t *, sr->arg.rw); 430 431 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); 432 } 433 434 smb_sdrc_t 435 smb_com_read_andx(smb_request_t *sr) 436 { 437 smb_rw_param_t *param = sr->arg.rw; 438 uint16_t datalen_high; 439 uint16_t datalen_low; 440 uint16_t data_offset; 441 uint16_t offset2; 442 int rc; 443 444 smbsr_lookup_file(sr); 445 if (sr->fid_ofile == NULL) { 446 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 447 return (SDRC_ERROR); 448 } 449 450 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 451 452 if (param->rw_count >= SMB_READX_MAX) 453 param->rw_count = 0; 454 455 if ((rc = smb_common_read(sr, param)) != 0) { 456 smbsr_errno(sr, rc); 457 return (SDRC_ERROR); 458 } 459 460 datalen_low = param->rw_count & 0xFFFF; 461 datalen_high = (param->rw_count >> 16) & 0xFF; 462 463 /* 464 * If this is a secondary command, the data offset 465 * includes the previous wct + sizeof(wct). 466 */ 467 data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1; 468 469 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 470 data_offset += 60; 471 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60; 472 473 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC", 474 12, /* wct */ 475 param->rw_andx, /* secondary andx command */ 476 offset2, /* offset to next command */ 477 0, /* set to 0 for named pipes */ 478 datalen_low, /* data byte count */ 479 data_offset, /* offset from start to data */ 480 datalen_high, /* data byte count */ 481 VAR_BCC, /* BCC marker */ 482 0x00, /* padding */ 483 &sr->raw_data); 484 } else { 485 data_offset += 59; 486 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59; 487 488 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC", 489 12, /* wct */ 490 param->rw_andx, /* secondary andx command */ 491 offset2, /* offset to next command */ 492 -1, /* must be -1 for regular files */ 493 datalen_low, /* data byte count */ 494 data_offset, /* offset from start to data */ 495 datalen_high, /* data byte count */ 496 VAR_BCC, /* BCC marker */ 497 &sr->raw_data); 498 } 499 500 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 501 } 502 503 /* 504 * Common function for reading files or IPC/MSRPC named pipes. All 505 * protocol read functions should lookup the fid before calling this 506 * function. We can't move the fid lookup here because lock-and-read 507 * requires the fid to do locking before attempting the read. 508 * 509 * Reading from a file should break oplocks on the file to LEVEL_II. 510 * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not 511 * required as it is a no-op. If there's anything greater than a 512 * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile 513 * on which the read is occuring and therefore would not be broken. 514 * 515 * Returns errno values. 516 */ 517 int 518 smb_common_read(smb_request_t *sr, smb_rw_param_t *param) 519 { 520 smb_ofile_t *ofile = sr->fid_ofile; 521 smb_node_t *node; 522 smb_vdb_t *vdb = ¶m->rw_vdb; 523 struct mbuf *top; 524 int rc; 525 526 vdb->vdb_tag = 0; 527 vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0]; 528 vdb->vdb_uio.uio_iovcnt = MAX_IOVEC; 529 vdb->vdb_uio.uio_resid = param->rw_count; 530 vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset; 531 vdb->vdb_uio.uio_segflg = UIO_SYSSPACE; 532 vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 533 534 switch (sr->tid_tree->t_res_type & STYPE_MASK) { 535 case STYPE_DISKTREE: 536 node = ofile->f_node; 537 538 if (!smb_node_is_dir(node)) { 539 rc = smb_lock_range_access(sr, node, param->rw_offset, 540 param->rw_count, B_FALSE); 541 if (rc != NT_STATUS_SUCCESS) { 542 rc = ERANGE; 543 break; 544 } 545 } 546 547 if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) && 548 !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) { 549 /* 550 * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only 551 * reads. 552 * 553 * Reject request if the file has been opened 554 * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not 555 * set. 556 */ 557 rc = EACCES; 558 break; 559 } 560 561 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid; 562 top = smb_mbuf_allocate(&vdb->vdb_uio); 563 564 rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio); 565 566 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid; 567 smb_mbuf_trim(top, sr->raw_data.max_bytes); 568 MBC_ATTACH_MBUF(&sr->raw_data, top); 569 break; 570 571 case STYPE_IPC: 572 rc = smb_opipe_read(sr, &vdb->vdb_uio); 573 break; 574 575 default: 576 rc = EACCES; 577 break; 578 } 579 580 param->rw_count -= vdb->vdb_uio.uio_resid; 581 582 if (rc != 0) 583 return (rc); 584 585 if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) { 586 /* 587 * mincnt is only used by read-raw and is typically 588 * zero. If mincnt is greater than zero and the 589 * number of bytes read is less than mincnt, tell 590 * the client that we read nothing. 591 */ 592 param->rw_count = 0; 593 } 594 595 param->rw_offset += param->rw_count; 596 mutex_enter(&sr->fid_ofile->f_mutex); 597 ofile->f_seek_pos = param->rw_offset; 598 mutex_exit(&sr->fid_ofile->f_mutex); 599 return (rc); 600 } 601