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", ¶m->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", ¶m->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 = ¶m->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 }