xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_opipe.c (revision c5f48fa536d16d8fe59d1bb62faa7eb8e891610c)
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 /*
27  * This module provides the interface to NDR RPC.
28  */
29 
30 #include <sys/stat.h>
31 #include <sys/uio.h>
32 #include <sys/ksynch.h>
33 #include <sys/stropts.h>
34 #include <sys/socket.h>
35 #include <sys/filio.h>
36 #include <smbsrv/smb_kproto.h>
37 #include <smbsrv/smb_xdr.h>
38 #include <smb/winioctl.h>
39 
40 static uint32_t smb_opipe_transceive(smb_request_t *, smb_fsctl_t *);
41 
42 /*
43  * Allocate a new opipe and return it, or NULL, in which case
44  * the caller will report "internal error".
45  */
46 static smb_opipe_t *
47 smb_opipe_alloc(smb_request_t *sr)
48 {
49 	smb_server_t	*sv = sr->sr_server;
50 	smb_opipe_t	*opipe;
51 	ksocket_t	sock;
52 
53 	if (ksocket_socket(&sock, AF_UNIX, SOCK_STREAM, 0,
54 	    KSOCKET_SLEEP, sr->user_cr) != 0)
55 		return (NULL);
56 
57 	opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP);
58 
59 	bzero(opipe, sizeof (smb_opipe_t));
60 	mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL);
61 	cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL);
62 	opipe->p_magic = SMB_OPIPE_MAGIC;
63 	opipe->p_server = sv;
64 	opipe->p_refcnt = 1;
65 	opipe->p_socket = sock;
66 
67 	return (opipe);
68 }
69 
70 /*
71  * Destroy an opipe.  This is normally called from smb_ofile_delete
72  * when the ofile has no more references and is about to be free'd.
73  * This is also called here in error handling code paths, before
74  * the opipe is installed under an ofile.
75  */
76 void
77 smb_opipe_dealloc(smb_opipe_t *opipe)
78 {
79 	smb_server_t *sv;
80 
81 	SMB_OPIPE_VALID(opipe);
82 	sv = opipe->p_server;
83 	SMB_SERVER_VALID(sv);
84 
85 	/*
86 	 * This is called in the error path when opening,
87 	 * in which case we close the socket here.
88 	 */
89 	if (opipe->p_socket != NULL)
90 		(void) ksocket_close(opipe->p_socket, zone_kcred());
91 
92 	opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC;
93 	cv_destroy(&opipe->p_cv);
94 	mutex_destroy(&opipe->p_mutex);
95 
96 	kmem_cache_free(smb_cache_opipe, opipe);
97 }
98 
99 /*
100  * Helper for open: build pipe name and connect.
101  */
102 static int
103 smb_opipe_connect(smb_request_t *sr, smb_opipe_t *opipe)
104 {
105 	struct sockaddr_un saddr;
106 	smb_arg_open_t	*op = &sr->sr_open;
107 	const char *name;
108 	int rc;
109 
110 	name = op->fqi.fq_path.pn_path;
111 	name += strspn(name, "\\");
112 	if (smb_strcasecmp(name, "PIPE", 4) == 0) {
113 		name += 4;
114 		name += strspn(name, "\\");
115 	}
116 	(void) strlcpy(opipe->p_name, name, SMB_OPIPE_MAXNAME);
117 	(void) smb_strlwr(opipe->p_name);
118 
119 	bzero(&saddr, sizeof (saddr));
120 	saddr.sun_family = AF_UNIX;
121 	(void) snprintf(saddr.sun_path, sizeof (saddr.sun_path),
122 	    "%s/%s", SMB_PIPE_DIR, opipe->p_name);
123 	rc = ksocket_connect(opipe->p_socket, (struct sockaddr *)&saddr,
124 	    sizeof (saddr), sr->user_cr);
125 
126 	return (rc);
127 }
128 
129 /*
130  * Helper for open: encode and send the user info.
131  *
132  * We send information about this client + user to the
133  * pipe service so it can use it for access checks.
134  * The service MAY deny the open based on this info,
135  * (i.e. anonymous session trying to open a pipe that
136  * requires authentication) in which case we will read
137  * an error status from the service and return that.
138  */
139 static void
140 smb_opipe_send_userinfo(smb_request_t *sr, smb_opipe_t *opipe,
141     smb_error_t *errp)
142 {
143 	XDR xdrs;
144 	smb_netuserinfo_t nui;
145 	smb_pipehdr_t phdr;
146 	char *buf;
147 	uint32_t buflen;
148 	uint32_t status;
149 	size_t iocnt = 0;
150 	int rc;
151 
152 	/*
153 	 * Any errors building the XDR message etc.
154 	 */
155 	errp->status = NT_STATUS_INTERNAL_ERROR;
156 
157 	smb_user_netinfo_init(sr->uid_user, &nui);
158 	phdr.ph_magic = SMB_PIPE_HDR_MAGIC;
159 	phdr.ph_uilen = xdr_sizeof(smb_netuserinfo_xdr, &nui);
160 
161 	buflen = sizeof (phdr) + phdr.ph_uilen;
162 	buf = kmem_alloc(buflen, KM_SLEEP);
163 
164 	bcopy(&phdr, buf, sizeof (phdr));
165 	xdrmem_create(&xdrs, buf + sizeof (phdr),
166 	    buflen - (sizeof (phdr)), XDR_ENCODE);
167 	if (!smb_netuserinfo_xdr(&xdrs, &nui))
168 		goto out;
169 
170 	/*
171 	 * If we fail sending the netuserinfo or recv'ing the
172 	 * status reponse, we have probably run into the limit
173 	 * on the number of open pipes.  That's this status:
174 	 */
175 	errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
176 
177 	rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
178 	    &iocnt, sr->user_cr);
179 	if (rc == 0 && iocnt != buflen)
180 		rc = EIO;
181 	if (rc != 0)
182 		goto out;
183 
184 	rc = ksocket_recv(opipe->p_socket, &status, sizeof (status), 0,
185 	    &iocnt, sr->user_cr);
186 	if (rc != 0 || iocnt != sizeof (status))
187 		goto out;
188 
189 	/*
190 	 * Return the status we read from the pipe service,
191 	 * normally NT_STATUS_SUCCESS, but could be something
192 	 * else like NT_STATUS_ACCESS_DENIED.
193 	 */
194 	errp->status = status;
195 
196 out:
197 	xdr_destroy(&xdrs);
198 	kmem_free(buf, buflen);
199 	smb_user_netinfo_fini(&nui);
200 }
201 
202 /*
203  * smb_opipe_open
204  *
205  * Open an RPC named pipe. This routine should be called if
206  * a file open is requested on a share of type STYPE_IPC.
207  * If we recognize the pipe, we setup a new ofile.
208  *
209  * Returns 0 on success, Otherwise an NT status code.
210  */
211 int
212 smb_opipe_open(smb_request_t *sr, uint32_t uniqid)
213 {
214 	smb_arg_open_t	*op = &sr->sr_open;
215 	smb_attr_t *ap = &op->fqi.fq_fattr;
216 	smb_ofile_t *ofile;
217 	smb_opipe_t *opipe;
218 	smb_error_t err;
219 
220 	opipe = smb_opipe_alloc(sr);
221 	if (opipe == NULL)
222 		return (NT_STATUS_INTERNAL_ERROR);
223 
224 	if (smb_opipe_connect(sr, opipe) != 0) {
225 		smb_opipe_dealloc(opipe);
226 		return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
227 	}
228 
229 	smb_opipe_send_userinfo(sr, opipe, &err);
230 	if (err.status != 0) {
231 		smb_opipe_dealloc(opipe);
232 		return (err.status);
233 	}
234 
235 	/*
236 	 * Note: If smb_ofile_open succeeds, the new ofile is
237 	 * in the FID lists can can be used by I/O requests.
238 	 */
239 	op->create_options = 0;
240 	op->pipe = opipe;
241 	ofile = smb_ofile_open(sr, NULL, op,
242 	    SMB_FTYPE_MESG_PIPE, uniqid, &err);
243 	op->pipe = NULL;
244 	if (ofile == NULL) {
245 		smb_opipe_dealloc(opipe);
246 		return (err.status);
247 	}
248 
249 	/* An "up" pointer, for debug. */
250 	opipe->p_ofile = ofile;
251 
252 	/*
253 	 * Caller expects attributes in op->fqi
254 	 */
255 	(void) smb_opipe_getattr(ofile, &op->fqi.fq_fattr);
256 
257 	op->dsize = 0;
258 	op->dattr = ap->sa_dosattr;
259 	op->fileid = ap->sa_vattr.va_nodeid;
260 	op->ftype = SMB_FTYPE_MESG_PIPE;
261 	op->action_taken = SMB_OACT_OPLOCK | SMB_OACT_OPENED;
262 	op->devstate = SMB_PIPE_READMODE_MESSAGE
263 	    | SMB_PIPE_TYPE_MESSAGE
264 	    | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
265 
266 	sr->smb_fid = ofile->f_fid;
267 	sr->fid_ofile = ofile;
268 
269 	return (NT_STATUS_SUCCESS);
270 }
271 
272 /*
273  * smb_opipe_close
274  *
275  * Called by smb_ofile_close for pipes.
276  *
277  * Note: ksocket_close may block while waiting for
278  * any I/O threads with a hold to get out.
279  */
280 void
281 smb_opipe_close(smb_ofile_t *of)
282 {
283 	smb_opipe_t *opipe;
284 	ksocket_t sock;
285 
286 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
287 	ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
288 	opipe = of->f_pipe;
289 	SMB_OPIPE_VALID(opipe);
290 
291 	mutex_enter(&opipe->p_mutex);
292 	sock = opipe->p_socket;
293 	opipe->p_socket = NULL;
294 	mutex_exit(&opipe->p_mutex);
295 
296 	(void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr);
297 	(void) ksocket_close(sock, of->f_cr);
298 }
299 
300 /*
301  * smb_opipe_write
302  *
303  * Write RPC request data to the pipe.  The client should call smb_opipe_read
304  * to complete the exchange and obtain the RPC response.
305  *
306  * Returns 0 on success or an errno on failure.
307  */
308 int
309 smb_opipe_write(smb_request_t *sr, struct uio *uio)
310 {
311 	struct nmsghdr msghdr;
312 	smb_ofile_t *ofile;
313 	smb_opipe_t *opipe;
314 	ksocket_t sock;
315 	size_t sent = 0;
316 	int rc = 0;
317 
318 	ofile = sr->fid_ofile;
319 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
320 	opipe = ofile->f_pipe;
321 	SMB_OPIPE_VALID(opipe);
322 
323 	mutex_enter(&opipe->p_mutex);
324 	sock = opipe->p_socket;
325 	if (sock != NULL)
326 		ksocket_hold(sock);
327 	mutex_exit(&opipe->p_mutex);
328 	if (sock == NULL)
329 		return (EBADF);
330 
331 	bzero(&msghdr, sizeof (msghdr));
332 	msghdr.msg_iov = uio->uio_iov;
333 	msghdr.msg_iovlen = uio->uio_iovcnt;
334 
335 	/*
336 	 * This should block until we've sent it all,
337 	 * or given up due to errors (pipe closed).
338 	 */
339 	while (uio->uio_resid > 0) {
340 		rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr);
341 		if (rc != 0)
342 			break;
343 		uio->uio_resid -= sent;
344 	}
345 
346 	ksocket_rele(sock);
347 
348 	return (rc);
349 }
350 
351 /*
352  * smb_opipe_read
353  *
354  * This interface may be called from smb_opipe_transact (write, read)
355  * or from smb_read / smb2_read to get the rest of an RPC response.
356  * The response data (and length) are returned via the uio.
357  */
358 int
359 smb_opipe_read(smb_request_t *sr, struct uio *uio)
360 {
361 	struct nmsghdr msghdr;
362 	smb_ofile_t *ofile;
363 	smb_opipe_t *opipe;
364 	ksocket_t sock;
365 	size_t recvcnt = 0;
366 	int rc;
367 
368 	ofile = sr->fid_ofile;
369 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
370 	opipe = ofile->f_pipe;
371 	SMB_OPIPE_VALID(opipe);
372 
373 	mutex_enter(&opipe->p_mutex);
374 	sock = opipe->p_socket;
375 	if (sock != NULL)
376 		ksocket_hold(sock);
377 	mutex_exit(&opipe->p_mutex);
378 	if (sock == NULL)
379 		return (EBADF);
380 
381 	bzero(&msghdr, sizeof (msghdr));
382 	msghdr.msg_iov = uio->uio_iov;
383 	msghdr.msg_iovlen = uio->uio_iovcnt;
384 
385 	/*
386 	 * This should block only if there's no data.
387 	 * A single call to recvmsg does just that.
388 	 * (Intentionaly no recv loop here.)
389 	 */
390 	rc = ksocket_recvmsg(sock, &msghdr, 0,
391 	    &recvcnt, ofile->f_cr);
392 	if (rc != 0)
393 		goto out;
394 
395 	if (recvcnt == 0) {
396 		/* Other side closed. */
397 		rc = EPIPE;
398 		goto out;
399 	}
400 	uio->uio_resid -= recvcnt;
401 
402 out:
403 	ksocket_rele(sock);
404 
405 	return (rc);
406 }
407 
408 int
409 smb_opipe_ioctl(smb_request_t *sr, int cmd, void *arg, int *rvalp)
410 {
411 	smb_ofile_t *ofile;
412 	smb_opipe_t *opipe;
413 	ksocket_t sock;
414 	int rc;
415 
416 	ofile = sr->fid_ofile;
417 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
418 	opipe = ofile->f_pipe;
419 	SMB_OPIPE_VALID(opipe);
420 
421 	mutex_enter(&opipe->p_mutex);
422 	sock = opipe->p_socket;
423 	if (sock != NULL)
424 		ksocket_hold(sock);
425 	mutex_exit(&opipe->p_mutex);
426 	if (sock == NULL)
427 		return (EBADF);
428 
429 	rc = ksocket_ioctl(sock, cmd, (intptr_t)arg, rvalp, ofile->f_cr);
430 
431 	ksocket_rele(sock);
432 
433 	return (rc);
434 }
435 
436 /*
437  * Get the smb_attr_t for a named pipe.
438  * Caller has already cleared to zero.
439  */
440 int
441 smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
442 {
443 
444 	if (of->f_pipe == NULL)
445 		return (EINVAL);
446 
447 	ap->sa_vattr.va_type = VFIFO;
448 	ap->sa_vattr.va_nlink = 1;
449 	ap->sa_vattr.va_nodeid = (uintptr_t)of->f_pipe;
450 	ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
451 	ap->sa_allocsz = SMB_PIPE_MAX_MSGSIZE;
452 
453 	return (0);
454 }
455 
456 int
457 smb_opipe_getname(smb_ofile_t *of, char *buf, size_t buflen)
458 {
459 	smb_opipe_t *opipe;
460 
461 	if ((opipe = of->f_pipe) == NULL)
462 		return (EINVAL);
463 
464 	(void) snprintf(buf, buflen, "\\%s", opipe->p_name);
465 	return (0);
466 }
467 
468 /*
469  * Handler for smb2_ioctl
470  */
471 /* ARGSUSED */
472 uint32_t
473 smb_opipe_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
474 {
475 	uint32_t status;
476 
477 	switch (fsctl->CtlCode) {
478 	case FSCTL_PIPE_TRANSCEIVE:
479 		status = smb_opipe_transceive(sr, fsctl);
480 		break;
481 
482 	case FSCTL_PIPE_PEEK:
483 	case FSCTL_PIPE_WAIT:
484 		/* XXX todo */
485 		status = NT_STATUS_NOT_SUPPORTED;
486 		break;
487 
488 	default:
489 		ASSERT(!"CtlCode");
490 		status = NT_STATUS_INTERNAL_ERROR;
491 		break;
492 	}
493 
494 	return (status);
495 }
496 
497 static uint32_t
498 smb_opipe_transceive(smb_request_t *sr, smb_fsctl_t *fsctl)
499 {
500 	smb_vdb_t	vdb;
501 	smb_ofile_t	*ofile;
502 	struct mbuf	*mb;
503 	uint32_t	status;
504 	int		len, rc;
505 
506 	/*
507 	 * Caller checked that this is the IPC$ share,
508 	 * and that this call has a valid open handle.
509 	 * Just check the type.
510 	 */
511 	ofile = sr->fid_ofile;
512 	if (ofile->f_ftype != SMB_FTYPE_MESG_PIPE)
513 		return (NT_STATUS_INVALID_HANDLE);
514 
515 	rc = smb_mbc_decodef(fsctl->in_mbc, "#B",
516 	    fsctl->InputCount, &vdb);
517 	if (rc != 0) {
518 		/* Not enough data sent. */
519 		return (NT_STATUS_INVALID_PARAMETER);
520 	}
521 
522 	rc = smb_opipe_write(sr, &vdb.vdb_uio);
523 	if (rc != 0)
524 		return (smb_errno2status(rc));
525 
526 	vdb.vdb_tag = 0;
527 	vdb.vdb_uio.uio_iov = &vdb.vdb_iovec[0];
528 	vdb.vdb_uio.uio_iovcnt = MAX_IOVEC;
529 	vdb.vdb_uio.uio_segflg = UIO_SYSSPACE;
530 	vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
531 	vdb.vdb_uio.uio_loffset = (offset_t)0;
532 	vdb.vdb_uio.uio_resid = fsctl->MaxOutputResp;
533 	mb = smb_mbuf_allocate(&vdb.vdb_uio);
534 
535 	rc = smb_opipe_read(sr, &vdb.vdb_uio);
536 	if (rc != 0) {
537 		m_freem(mb);
538 		return (smb_errno2status(rc));
539 	}
540 
541 	len = fsctl->MaxOutputResp - vdb.vdb_uio.uio_resid;
542 	smb_mbuf_trim(mb, len);
543 	MBC_ATTACH_MBUF(fsctl->out_mbc, mb);
544 
545 	/*
546 	 * If the output buffer holds a partial pipe message,
547 	 * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
548 	 * As we don't have message boundary markers, the best
549 	 * we can do is return that status when we have ALL of:
550 	 *	Output buffer was < SMB_PIPE_MAX_MSGSIZE
551 	 *	We filled the output buffer (resid==0)
552 	 *	There's more data (ioctl FIONREAD)
553 	 */
554 	status = NT_STATUS_SUCCESS;
555 	if (fsctl->MaxOutputResp < SMB_PIPE_MAX_MSGSIZE &&
556 	    vdb.vdb_uio.uio_resid == 0) {
557 		int nread = 0, trval;
558 		rc = smb_opipe_ioctl(sr, FIONREAD, &nread, &trval);
559 		if (rc == 0 && nread != 0)
560 			status = NT_STATUS_BUFFER_OVERFLOW;
561 	}
562 
563 	return (status);
564 }
565