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 2018 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_START(op__Read, 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_DONE(op__Read, 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_START(op__LockAndRead, 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_DONE(op__LockAndRead, 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         DTRACE_SMB_START(op__ReadRaw, smb_request_t *, sr);
 233         return (SDRC_SUCCESS);
 234 }
 235 
 236 void
 237 smb_post_read_raw(smb_request_t *sr)
 238 {
 239         DTRACE_SMB_DONE(op__ReadRaw, smb_request_t *, sr);
 240 }
 241 
 242 smb_sdrc_t
 243 smb_com_read_raw(smb_request_t *sr)
 244 {
 245         smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS,
 246             ERROR_NOT_SUPPORTED);
 247         return (SDRC_ERROR);
 248 }
 249 
 250 /*
 251  * Read bytes from a file (SMB Core).  This request was extended in
 252  * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
 253  * 12 and including additional offset information.
 254  *
 255  * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4:
 256  * If wct is 12 and CAP_LARGE_READX is set, the count may be larger
 257  * than the negotiated buffer size.  If maxcnt_high is 0xFF, it must
 258  * be ignored.  Otherwise, maxcnt_high represents the upper 16 bits
 259  * of rw_count.
 260  */
 261 smb_sdrc_t
 262 smb_pre_read_andx(smb_request_t *sr)
 263 {
 264         smb_rw_param_t *param;
 265         uint32_t off_low;
 266         uint32_t off_high;
 267         uint32_t maxcnt_high;
 268         uint16_t maxcnt_low;
 269         uint16_t mincnt;
 270         uint16_t remcnt;
 271         int rc;
 272 
 273         param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
 274         sr->arg.rw = param;
 275 
 276         if (sr->smb_wct == 12) {
 277                 rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", &param->rw_andx,
 278                     &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
 279                     &remcnt, &off_high);
 280 
 281                 param->rw_offset = ((uint64_t)off_high << 32) |
 282                     (uint64_t)off_low;
 283 
 284                 param->rw_count = (uint32_t)maxcnt_low;
 285 
 286                 if ((sr->session->capabilities & CAP_LARGE_READX) &&
 287                     (maxcnt_high < 0xFF))
 288                         param->rw_count |= maxcnt_high << 16;
 289         } else {
 290                 rc = smbsr_decode_vwv(sr, "b3.wlwwlw", &param->rw_andx,
 291                     &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
 292                     &remcnt);
 293 
 294                 param->rw_offset = (uint64_t)off_low;
 295                 param->rw_count = (uint32_t)maxcnt_low;
 296         }
 297 
 298         param->rw_mincnt = 0;
 299 
 300         DTRACE_SMB_START(op__ReadX, smb_request_t *, sr); /* arg.rw */
 301 
 302         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 303 }
 304 
 305 void
 306 smb_post_read_andx(smb_request_t *sr)
 307 {
 308         DTRACE_SMB_DONE(op__ReadX, smb_request_t *, sr); /* arg.rw */
 309 
 310         kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
 311 }
 312 
 313 smb_sdrc_t
 314 smb_com_read_andx(smb_request_t *sr)
 315 {
 316         smb_rw_param_t *param = sr->arg.rw;
 317         uint16_t datalen_high;
 318         uint16_t datalen_low;
 319         uint16_t data_offset;
 320         uint16_t offset2;
 321         int rc;
 322 
 323         smbsr_lookup_file(sr);
 324         if (sr->fid_ofile == NULL) {
 325                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 326                 return (SDRC_ERROR);
 327         }
 328 
 329         sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
 330 
 331         if (param->rw_count >= SMB_READX_MAX)
 332                 param->rw_count = 0;
 333 
 334         if ((rc = smb_common_read(sr, param)) != 0) {
 335                 smbsr_errno(sr, rc);
 336                 return (SDRC_ERROR);
 337         }
 338 
 339         datalen_low = param->rw_count & 0xFFFF;
 340         datalen_high = (param->rw_count >> 16) & 0xFF;
 341 
 342         /*
 343          * If this is a secondary command, the data offset
 344          * includes the previous wct + sizeof(wct).
 345          */
 346         data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1;
 347 
 348         if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
 349                 data_offset += 60;
 350                 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60;
 351 
 352                 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC",
 353                     12,                 /* wct */
 354                     param->rw_andx,  /* secondary andx command */
 355                     offset2,            /* offset to next command */
 356                     0,                  /* set to 0 for named pipes */
 357                     datalen_low,        /* data byte count */
 358                     data_offset,        /* offset from start to data */
 359                     datalen_high,       /* data byte count */
 360                     VAR_BCC,            /* BCC marker */
 361                     0x00,               /* padding */
 362                     &sr->raw_data);
 363         } else {
 364                 data_offset += 59;
 365                 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59;
 366 
 367                 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC",
 368                     12,                 /* wct */
 369                     param->rw_andx,  /* secondary andx command */
 370                     offset2,            /* offset to next command */
 371                     -1,                 /* must be -1 for regular files */
 372                     datalen_low,        /* data byte count */
 373                     data_offset,        /* offset from start to data */
 374                     datalen_high,       /* data byte count */
 375                     VAR_BCC,            /* BCC marker */
 376                     &sr->raw_data);
 377         }
 378 
 379         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 380 }
 381 
 382 /*
 383  * Common function for reading files or IPC/MSRPC named pipes.  All
 384  * protocol read functions should lookup the fid before calling this
 385  * function.  We can't move the fid lookup here because lock-and-read
 386  * requires the fid to do locking before attempting the read.
 387  *
 388  * Reading from a file does not break oplocks because any need for
 389  * breaking before read is handled in open.
 390  *
 391  * Returns errno values.
 392  */
 393 int
 394 smb_common_read(smb_request_t *sr, smb_rw_param_t *param)
 395 {
 396         smb_ofile_t *ofile = sr->fid_ofile;
 397         smb_node_t *node;
 398         smb_vdb_t *vdb = &param->rw_vdb;
 399         struct mbuf *top;
 400         int rc;
 401 
 402         vdb->vdb_tag = 0;
 403         vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
 404         vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
 405         vdb->vdb_uio.uio_resid = param->rw_count;
 406         vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset;
 407         vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
 408         vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
 409 
 410         switch (sr->tid_tree->t_res_type & STYPE_MASK) {
 411         case STYPE_DISKTREE:
 412                 node = ofile->f_node;
 413 
 414                 if (!smb_node_is_dir(node)) {
 415                         rc = smb_lock_range_access(sr, node, param->rw_offset,
 416                             param->rw_count, B_FALSE);
 417                         if (rc != NT_STATUS_SUCCESS) {
 418                                 rc = ERANGE;
 419                                 break;
 420                         }
 421                 }
 422 
 423                 if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) &&
 424                     !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) {
 425                         /*
 426                          * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only
 427                          * reads.
 428                          *
 429                          * Reject request if the file has been opened
 430                          * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not
 431                          * set.
 432                          */
 433                         rc = EACCES;
 434                         break;
 435                 }
 436 
 437                 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
 438                 top = smb_mbuf_allocate(&vdb->vdb_uio);
 439 
 440                 rc = smb_fsop_read(sr, sr->user_cr, node, ofile,
 441                     &vdb->vdb_uio, 0);
 442 
 443                 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
 444                 smb_mbuf_trim(top, sr->raw_data.max_bytes);
 445                 MBC_ATTACH_MBUF(&sr->raw_data, top);
 446                 break;
 447 
 448         case STYPE_IPC:
 449                 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
 450                 top = smb_mbuf_allocate(&vdb->vdb_uio);
 451 
 452                 rc = smb_opipe_read(sr, &vdb->vdb_uio);
 453 
 454                 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
 455                 smb_mbuf_trim(top, sr->raw_data.max_bytes);
 456                 MBC_ATTACH_MBUF(&sr->raw_data, top);
 457                 break;
 458 
 459         default:
 460                 rc = EACCES;
 461                 break;
 462         }
 463 
 464         param->rw_count -= vdb->vdb_uio.uio_resid;
 465 
 466         if (rc != 0)
 467                 return (rc);
 468 
 469         if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) {
 470                 /*
 471                  * mincnt is only used by read-raw and is typically
 472                  * zero.  If mincnt is greater than zero and the
 473                  * number of bytes read is less than mincnt, tell
 474                  * the client that we read nothing.
 475                  */
 476                 param->rw_count = 0;
 477         }
 478 
 479         param->rw_offset += param->rw_count;
 480         mutex_enter(&sr->fid_ofile->f_mutex);
 481         ofile->f_seek_pos = param->rw_offset;
 482         mutex_exit(&sr->fid_ofile->f_mutex);
 483         return (rc);
 484 }