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
smb_pre_read(smb_request_t * sr)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
smb_post_read(smb_request_t * sr)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
smb_com_read(smb_request_t * sr)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
smb_pre_lock_and_read(smb_request_t * sr)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
smb_post_lock_and_read(smb_request_t * sr)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
smb_com_lock_and_read(smb_request_t * sr)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
smb_pre_read_raw(smb_request_t * sr)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
smb_post_read_raw(smb_request_t * sr)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
smb_com_read_raw(smb_request_t * sr)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
smb_pre_read_andx(smb_request_t * sr)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", ¶m->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", ¶m->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
smb_post_read_andx(smb_request_t * sr)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
smb_com_read_andx(smb_request_t * sr)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
smb_common_read(smb_request_t * sr,smb_rw_param_t * param)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 = ¶m->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 }
485