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