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, &param->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, &param->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", &param->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", &param->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 = &param->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 }