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