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