xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_read.c (revision 7b59d02d2a384be9a08087b14defadd214b3c1dd)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/syslog.h>
29 #include <smbsrv/smb_incl.h>
30 #include <smbsrv/smb_fsops.h>
31 
32 
33 typedef struct smb_read_param {
34 	uint64_t r_offset;
35 	uint16_t r_count;
36 	uint16_t r_mincnt;
37 } smb_read_param_t;
38 
39 
40 int smb_common_read(struct smb_request *, smb_read_param_t *);
41 
42 
43 /*
44  * Read bytes from a file or named pipe (SMB Core).
45  *
46  * The requested count specifies the number of bytes desired.  Offset
47  * is limited to 32 bits, so this client request is inappropriate for
48  * files with 64 bit offsets.
49  *
50  * On return, count is the number of bytes actually being returned, which
51  * may be less than the count requested only if a read specifies bytes
52  * beyond the current file size.  In this case only the bytes that exist
53  * are returned.  A read completely beyond the end of file results in a
54  * response of length zero.  This is the only circumstance when a zero
55  * length response is generated.  A count returned which is less than the
56  * count requested is the end of file indicator.
57  */
58 smb_sdrc_t
59 smb_com_read(struct smb_request *sr)
60 {
61 	smb_read_param_t param;
62 	uint32_t off_low;
63 	uint16_t remcnt;
64 	int rc;
65 
66 	rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
67 	    &param.r_count, &off_low, &remcnt);
68 	if (rc != 0)
69 		return (SDRC_ERROR_REPLY);
70 
71 	param.r_offset = (uint64_t)off_low;
72 	param.r_mincnt = 0;
73 
74 	sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
75 	if (sr->fid_ofile == NULL) {
76 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
77 		return (SDRC_ERROR_REPLY);
78 	}
79 
80 	if ((rc = smb_common_read(sr, &param)) != 0) {
81 		smbsr_errno(sr, rc);
82 		return (SDRC_ERROR_REPLY);
83 	}
84 
85 	rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
86 	    5, param.r_count, VAR_BCC, 0x01, param.r_count, &sr->raw_data);
87 
88 	return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
89 }
90 
91 /*
92  * Lock and read bytes from a file (SMB Core Plus).  The SmbLockAndRead/
93  * SmbLockAndWrite sub-dialect is only valid on disk files: reject any
94  * attempt to use it on non-disk shares.
95  *
96  * The requested count specifies the number of bytes desired.  Offset
97  * specifies the offset in the file of the first byte to be locked then
98  * read. Note that offset is limited to 32 bits, so this client request
99  * is inappropriate for files with 64 bit offsets.
100  *
101  * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted
102  * immediately an error should be returned to the client.  If an error
103  * occurs on the lock, the bytes should not be read.
104  *
105  * On return, count is the number of bytes actually being returned, which
106  * may be less than the count requested only if a read specifies bytes
107  * beyond the current file size.  In this case only the bytes that exist
108  * are returned.  A read completely beyond the end of file results in a
109  * response of length zero.  This is the only circumstance when a zero
110  * length response is generated.  A count returned which is less than the
111  * count requested is the end of file indicator.
112  */
113 smb_sdrc_t
114 smb_com_lock_and_read(struct smb_request *sr)
115 {
116 	smb_read_param_t param;
117 	uint16_t remcnt;
118 	uint32_t off_low;
119 	DWORD result;
120 	int rc;
121 
122 	if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
123 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
124 		return (SDRC_ERROR_REPLY);
125 	}
126 
127 	rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
128 	    &param.r_count, &off_low, &remcnt);
129 	if (rc != 0)
130 		return (SDRC_ERROR_REPLY);
131 
132 	param.r_offset = (uint64_t)off_low;
133 	param.r_mincnt = 0;
134 
135 	sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
136 	if (sr->fid_ofile == NULL) {
137 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
138 		return (SDRC_ERROR_REPLY);
139 	}
140 
141 	result = smb_lock_range(sr, sr->fid_ofile, param.r_offset,
142 	    (uint64_t)param.r_count, UINT_MAX, SMB_LOCK_TYPE_READWRITE);
143 	if (result != NT_STATUS_SUCCESS) {
144 		smb_lock_range_error(sr, result);
145 		return (SDRC_ERROR_REPLY);
146 	}
147 
148 	if ((rc = smb_common_read(sr, &param)) != 0) {
149 		smbsr_errno(sr, rc);
150 		return (SDRC_ERROR_REPLY);
151 	}
152 
153 	rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
154 	    5, param.r_count, VAR_BCC, 0x1, param.r_count, &sr->raw_data);
155 
156 	return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
157 }
158 
159 /*
160  * The SMB_COM_READ_RAW protocol is a negotiated option introduced in
161  * SMB Core Plus to maximize performance when reading a large block
162  * of data from a server.  This request was extended in LM 0.12 to
163  * support 64-bit offsets; the server can indicate support by setting
164  * CAP_LARGE_FILES in the negotiated capabilities.
165  *
166  * The client must guarantee that there is (and will be) no other request
167  * to the server for the duration of the SMB_COM_READ_RAW, since the
168  * server response has no header or trailer. To help ensure that there
169  * are no interruptions, we block all I/O for the session during read raw.
170  *
171  * If this is the first SMB request received since we sent an oplock break
172  * to this client, we don't know if it's safe to send the raw data because
173  * the requests may have crossed on the wire and the client may have
174  * interpreted the oplock break as part of the raw data. To avoid problems,
175  * we send a zero length session packet, which will force the client to
176  * retry the read.
177  *
178  * Read errors are handled by sending a zero length response.
179  */
180 smb_sdrc_t
181 smb_com_read_raw(struct smb_request *sr)
182 {
183 	smb_read_param_t	param;
184 	smb_node_t		*node;
185 	uint32_t		off_low;
186 	uint32_t		off_high;
187 	uint32_t		timeout;
188 	int			rc;
189 
190 	switch (sr->session->s_state) {
191 	case SMB_SESSION_STATE_NEGOTIATED:
192 		if (sr->smb_wct == 8) {
193 			rc = smbsr_decode_vwv(sr, "wlwwl2.", &sr->smb_fid,
194 			    &off_low, &param.r_count, &param.r_mincnt,
195 			    &timeout);
196 			param.r_offset = (uint64_t)off_low;
197 		} else {
198 			rc = smbsr_decode_vwv(sr, "wlwwl2.l", &sr->smb_fid,
199 			    &off_low, &param.r_count, &param.r_mincnt, &timeout,
200 			    &off_high);
201 			param.r_offset = ((uint64_t)off_high << 32) | off_low;
202 		}
203 
204 		if (rc != 0)
205 			return (SDRC_ERROR_REPLY);
206 
207 		sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree,
208 		    sr->smb_fid);
209 		if (sr->fid_ofile == NULL) {
210 			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
211 			    ERRDOS, ERRbadfid);
212 			return (SDRC_ERROR_REPLY);
213 		}
214 
215 		rc = smb_common_read(sr, &param);
216 		/*
217 		 * XXX Do we need to handle errors here?  What if we have an
218 		 * access error (either permissions or range lock violations?
219 		 */
220 		if (STYPE_ISDSK(sr->tid_tree->t_res_type)) {
221 			node = sr->fid_ofile->f_node;
222 			if (node->n_oplock.op_flags & OPLOCK_FLAG_BREAKING) {
223 				rc = EAGAIN;
224 			}
225 		}
226 
227 		if (rc != 0) {
228 			(void) smb_session_send(sr->session, 0, NULL);
229 			m_freem(sr->raw_data.chain);
230 			sr->raw_data.chain = 0;
231 		} else {
232 			(void) smb_session_send(sr->session, 0, &sr->raw_data);
233 		}
234 		return (SDRC_NO_REPLY);
235 
236 	case SMB_SESSION_STATE_OPLOCK_BREAKING:
237 		(void) smb_session_send(sr->session, 0, NULL);
238 		sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED;
239 		return (SDRC_NO_REPLY);
240 
241 	case SMB_SESSION_STATE_WRITE_RAW_ACTIVE:
242 		ASSERT(0);
243 		return (SDRC_DROP_VC);
244 
245 	case SMB_SESSION_STATE_TERMINATED:
246 		ASSERT(0);
247 		return (SDRC_NO_REPLY);
248 
249 	case SMB_SESSION_STATE_DISCONNECTED:
250 		return (SDRC_NO_REPLY);
251 
252 	case SMB_SESSION_STATE_CONNECTED:
253 	case SMB_SESSION_STATE_ESTABLISHED:
254 	default:
255 		ASSERT(0);
256 		return (SDRC_DROP_VC);
257 	}
258 }
259 
260 /*
261  * Read bytes from a file (SMB Core).  This request was extended in
262  * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
263  * 12 and including additional offset information.
264  */
265 smb_sdrc_t
266 smb_com_read_andx(struct smb_request *sr)
267 {
268 	smb_read_param_t param;
269 	uint32_t off_low;
270 	uint32_t off_high;
271 	uint16_t remcnt;
272 	uint16_t offset2;
273 	uint8_t secondary;
274 	int rc;
275 
276 	if (sr->smb_wct == 12) {
277 		rc = smbsr_decode_vwv(sr, "b3.wlw6.wl", &secondary,
278 		    &sr->smb_fid, &off_low, &param.r_count, &remcnt, &off_high);
279 
280 		param.r_offset = ((uint64_t)off_high << 32) | off_low;
281 	} else {
282 		rc = smbsr_decode_vwv(sr, "b3.wlw6.w", &secondary,
283 		    &sr->smb_fid, &off_low, &param.r_count, &remcnt);
284 
285 		param.r_offset = (uint64_t)off_low;
286 	}
287 
288 	if (rc != 0)
289 		return (SDRC_ERROR_REPLY);
290 
291 	param.r_mincnt = 0;
292 
293 	sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid);
294 	if (sr->fid_ofile == NULL) {
295 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
296 		return (SDRC_ERROR_REPLY);
297 	}
298 
299 	if ((rc = smb_common_read(sr, &param)) != 0) {
300 		smbsr_errno(sr, rc);
301 		return (SDRC_ERROR_REPLY);
302 	}
303 
304 	/*
305 	 * Ensure that the next response offset is zero
306 	 * if there is no secondary command.
307 	 */
308 	offset2 = (secondary == 0xFF) ? 0 : param.r_count + 59;
309 
310 	/*
311 	 * The STYPE_IPC response format is different.
312 	 * The unknown value (2) may be to indicate that it
313 	 * is a follow-up to an earlier RPC transaction.
314 	 */
315 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
316 		rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wbC",
317 		    12,			/* wct */
318 		    secondary,		/* Secondary andx command */
319 		    offset2,		/* offset to next */
320 		    0,			/* must be 0 */
321 		    param.r_count,	/* data byte count */
322 		    60,			/* Offset from start to data */
323 		    VAR_BCC,		/* BCC marker */
324 		    0x02,		/* unknown */
325 		    &sr->raw_data);
326 	} else {
327 		rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wC",
328 		    12,			/* wct */
329 		    secondary,		/* Secondary andx command */
330 		    offset2,		/* offset to next */
331 		    -1,			/* must be -1 */
332 		    param.r_count,	/* data byte count */
333 		    59,			/* Offset from start to data */
334 		    VAR_BCC,		/* BCC marker */
335 		    &sr->raw_data);
336 	}
337 
338 	return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
339 }
340 
341 /*
342  * Common function for reading files or IPC/MSRPC named pipes.  All
343  * protocol read functions should lookup the fid before calling this
344  * function.  We can't move the fid lookup here because lock-and-read
345  * requires the fid to do locking before attempting the read.
346  *
347  * Returns errno values.
348  */
349 int
350 smb_common_read(struct smb_request *sr, smb_read_param_t *param)
351 {
352 	smb_ofile_t *ofile = sr->fid_ofile;
353 	smb_node_t *node;
354 	struct vardata_block *vdb;
355 	struct mbuf *top;
356 	int rc;
357 
358 	vdb = kmem_zalloc(sizeof (struct vardata_block), KM_SLEEP);
359 	vdb->tag = 0;
360 	vdb->uio.uio_iov = &vdb->iovec[0];
361 	vdb->uio.uio_iovcnt = MAX_IOVEC;
362 	vdb->uio.uio_resid = param->r_count;
363 	vdb->uio.uio_loffset = (offset_t)param->r_offset;
364 	vdb->uio.uio_segflg = UIO_SYSSPACE;
365 
366 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
367 	case STYPE_DISKTREE:
368 		node = ofile->f_node;
369 
370 		if (node->attr.sa_vattr.va_type != VDIR) {
371 			rc = smb_lock_range_access(sr, node, param->r_offset,
372 			    param->r_count, B_FALSE);
373 			if (rc != NT_STATUS_SUCCESS) {
374 				rc = ERANGE;
375 				break;
376 			}
377 		}
378 
379 		(void) smb_sync_fsattr(sr, sr->user_cr, node);
380 
381 		sr->raw_data.max_bytes = vdb->uio.uio_resid;
382 		top = smb_mbuf_allocate(&vdb->uio);
383 
384 		rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->uio,
385 		    &node->attr);
386 
387 		sr->raw_data.max_bytes -= vdb->uio.uio_resid;
388 		smb_mbuf_trim(top, sr->raw_data.max_bytes);
389 		MBC_ATTACH_MBUF(&sr->raw_data, top);
390 		break;
391 
392 	case STYPE_IPC:
393 		rc = smb_rpc_read(sr, &vdb->uio);
394 		break;
395 
396 	default:
397 		rc = EACCES;
398 		break;
399 	}
400 
401 	param->r_count -= vdb->uio.uio_resid;
402 	kmem_free(vdb, sizeof (struct vardata_block));
403 
404 	if (rc != 0)
405 		return (rc);
406 
407 	if (param->r_mincnt != 0 && param->r_count < param->r_mincnt) {
408 		/*
409 		 * mincnt is only used by read-raw and is typically
410 		 * zero.  If mincnt is greater than zero and the
411 		 * number of bytes read is less than mincnt, tell
412 		 * the client that we read nothing.
413 		 */
414 		param->r_count = 0;
415 	}
416 
417 	param->r_offset += param->r_count;
418 	mutex_enter(&sr->fid_ofile->f_mutex);
419 	ofile->f_seek_pos = param->r_offset;
420 	mutex_exit(&sr->fid_ofile->f_mutex);
421 	return (rc);
422 }
423 
424 /*
425  * The Read Block Multiplexed protocol is used to maximize performance
426  * when reading a large block of data from server to client while still
427  * allowing other operations to take place between the client and server
428  * in parallel.
429  *
430  * The mpx sub protocol is not supported because we support only
431  * connection oriented transports and NT supports SMB_COM_READ_MPX
432  * only over connectionless transports.
433  */
434 /*ARGSUSED*/
435 smb_sdrc_t
436 smb_com_read_mpx(struct smb_request *sr)
437 {
438 	return (SDRC_UNIMPLEMENTED);
439 }
440 
441 /*ARGSUSED*/
442 smb_sdrc_t
443 smb_com_read_mpx_secondary(struct smb_request *sr)
444 {
445 	return (SDRC_UNIMPLEMENTED);
446 }
447