xref: /titanic_41/usr/src/uts/common/fs/smbsrv/smb_opipe.c (revision a95c812d9d8f3561ba53bcaf3728f8e05fa5bdc9)
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 2015 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 
39 /*
40  * Allocate a new opipe and return it, or NULL, in which case
41  * the caller will report "internal error".
42  */
43 static smb_opipe_t *
smb_opipe_alloc(smb_request_t * sr)44 smb_opipe_alloc(smb_request_t *sr)
45 {
46 	smb_server_t	*sv = sr->sr_server;
47 	smb_opipe_t	*opipe;
48 	ksocket_t	sock;
49 
50 	if (ksocket_socket(&sock, AF_UNIX, SOCK_STREAM, 0,
51 	    KSOCKET_SLEEP, sr->user_cr) != 0)
52 		return (NULL);
53 
54 	opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP);
55 
56 	bzero(opipe, sizeof (smb_opipe_t));
57 	mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL);
58 	cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL);
59 	opipe->p_magic = SMB_OPIPE_MAGIC;
60 	opipe->p_server = sv;
61 	opipe->p_refcnt = 1;
62 	opipe->p_socket = sock;
63 
64 	return (opipe);
65 }
66 
67 /*
68  * Destroy an opipe.  This is normally called from smb_ofile_delete
69  * when the ofile has no more references and is about to be free'd.
70  * This is also called here in error handling code paths, before
71  * the opipe is installed under an ofile.
72  */
73 void
smb_opipe_dealloc(smb_opipe_t * opipe)74 smb_opipe_dealloc(smb_opipe_t *opipe)
75 {
76 	smb_server_t *sv;
77 
78 	SMB_OPIPE_VALID(opipe);
79 	sv = opipe->p_server;
80 	SMB_SERVER_VALID(sv);
81 
82 	/*
83 	 * This is called in the error path when opening,
84 	 * in which case we close the socket here.
85 	 */
86 	if (opipe->p_socket != NULL)
87 		(void) ksocket_close(opipe->p_socket, zone_kcred());
88 
89 	opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC;
90 	cv_destroy(&opipe->p_cv);
91 	mutex_destroy(&opipe->p_mutex);
92 
93 	kmem_cache_free(smb_cache_opipe, opipe);
94 }
95 
96 /*
97  * Helper for open: build pipe name and connect.
98  */
99 static int
smb_opipe_connect(smb_request_t * sr,smb_opipe_t * opipe)100 smb_opipe_connect(smb_request_t *sr, smb_opipe_t *opipe)
101 {
102 	struct sockaddr_un saddr;
103 	smb_arg_open_t	*op = &sr->sr_open;
104 	const char *name;
105 	int rc;
106 
107 	name = op->fqi.fq_path.pn_path;
108 	name += strspn(name, "\\");
109 	if (smb_strcasecmp(name, "PIPE", 4) == 0) {
110 		name += 4;
111 		name += strspn(name, "\\");
112 	}
113 	(void) strlcpy(opipe->p_name, name, SMB_OPIPE_MAXNAME);
114 	(void) smb_strlwr(opipe->p_name);
115 
116 	bzero(&saddr, sizeof (saddr));
117 	saddr.sun_family = AF_UNIX;
118 	(void) snprintf(saddr.sun_path, sizeof (saddr.sun_path),
119 	    "%s/%s", SMB_PIPE_DIR, opipe->p_name);
120 	rc = ksocket_connect(opipe->p_socket, (struct sockaddr *)&saddr,
121 	    sizeof (saddr), sr->user_cr);
122 
123 	return (rc);
124 }
125 
126 /*
127  * Helper for open: encode and send the user info.
128  *
129  * We send information about this client + user to the
130  * pipe service so it can use it for access checks.
131  * The service MAY deny the open based on this info,
132  * (i.e. anonymous session trying to open a pipe that
133  * requires authentication) in which case we will read
134  * an error status from the service and return that.
135  */
136 static void
smb_opipe_send_userinfo(smb_request_t * sr,smb_opipe_t * opipe,smb_error_t * errp)137 smb_opipe_send_userinfo(smb_request_t *sr, smb_opipe_t *opipe,
138     smb_error_t *errp)
139 {
140 	XDR xdrs;
141 	smb_netuserinfo_t nui;
142 	smb_pipehdr_t phdr;
143 	char *buf;
144 	uint32_t buflen;
145 	uint32_t status;
146 	size_t iocnt = 0;
147 	int rc;
148 
149 	/*
150 	 * Any errors building the XDR message etc.
151 	 */
152 	errp->status = NT_STATUS_INTERNAL_ERROR;
153 
154 	smb_user_netinfo_init(sr->uid_user, &nui);
155 	phdr.ph_magic = SMB_PIPE_HDR_MAGIC;
156 	phdr.ph_uilen = xdr_sizeof(smb_netuserinfo_xdr, &nui);
157 
158 	buflen = sizeof (phdr) + phdr.ph_uilen;
159 	buf = kmem_alloc(buflen, KM_SLEEP);
160 
161 	bcopy(&phdr, buf, sizeof (phdr));
162 	xdrmem_create(&xdrs, buf + sizeof (phdr),
163 	    buflen - (sizeof (phdr)), XDR_ENCODE);
164 	if (!smb_netuserinfo_xdr(&xdrs, &nui))
165 		goto out;
166 
167 	/*
168 	 * If we fail sending the netuserinfo or recv'ing the
169 	 * status reponse, we have probably run into the limit
170 	 * on the number of open pipes.  That's this status:
171 	 */
172 	errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
173 
174 	rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
175 	    &iocnt, sr->user_cr);
176 	if (rc == 0 && iocnt != buflen)
177 		rc = EIO;
178 	if (rc != 0)
179 		goto out;
180 
181 	rc = ksocket_recv(opipe->p_socket, &status, sizeof (status), 0,
182 	    &iocnt, sr->user_cr);
183 	if (rc != 0 || iocnt != sizeof (status))
184 		goto out;
185 
186 	/*
187 	 * Return the status we read from the pipe service,
188 	 * normally NT_STATUS_SUCCESS, but could be something
189 	 * else like NT_STATUS_ACCESS_DENIED.
190 	 */
191 	errp->status = status;
192 
193 out:
194 	xdr_destroy(&xdrs);
195 	kmem_free(buf, buflen);
196 	smb_user_netinfo_fini(&nui);
197 }
198 
199 /*
200  * smb_opipe_open
201  *
202  * Open an RPC named pipe. This routine should be called if
203  * a file open is requested on a share of type STYPE_IPC.
204  * If we recognize the pipe, we setup a new ofile.
205  *
206  * Returns 0 on success, Otherwise an NT status code.
207  */
208 int
smb_opipe_open(smb_request_t * sr,uint32_t uniqid)209 smb_opipe_open(smb_request_t *sr, uint32_t uniqid)
210 {
211 	smb_arg_open_t	*op = &sr->sr_open;
212 	smb_ofile_t *ofile;
213 	smb_opipe_t *opipe;
214 	smb_error_t err;
215 
216 	opipe = smb_opipe_alloc(sr);
217 	if (opipe == NULL)
218 		return (NT_STATUS_INTERNAL_ERROR);
219 
220 	if (smb_opipe_connect(sr, opipe) != 0) {
221 		smb_opipe_dealloc(opipe);
222 		return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
223 	}
224 
225 	smb_opipe_send_userinfo(sr, opipe, &err);
226 	if (err.status != 0) {
227 		smb_opipe_dealloc(opipe);
228 		return (err.status);
229 	}
230 
231 	/*
232 	 * Note: If smb_ofile_open succeeds, the new ofile is
233 	 * in the FID lists can can be used by I/O requests.
234 	 */
235 	op->create_options = 0;
236 	op->pipe = opipe;
237 	ofile = smb_ofile_open(sr, NULL, op,
238 	    SMB_FTYPE_MESG_PIPE, uniqid, &err);
239 	op->pipe = NULL;
240 	if (ofile == NULL) {
241 		smb_opipe_dealloc(opipe);
242 		return (err.status);
243 	}
244 
245 	/* An "up" pointer, for debug. */
246 	opipe->p_ofile = ofile;
247 
248 	op->dsize = 0x01000;
249 	op->dattr = FILE_ATTRIBUTE_NORMAL;
250 	op->ftype = SMB_FTYPE_MESG_PIPE;
251 	op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */
252 	op->devstate = SMB_PIPE_READMODE_MESSAGE
253 	    | SMB_PIPE_TYPE_MESSAGE
254 	    | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
255 	op->fileid = ofile->f_fid;
256 
257 	sr->smb_fid = ofile->f_fid;
258 	sr->fid_ofile = ofile;
259 
260 	return (NT_STATUS_SUCCESS);
261 }
262 
263 /*
264  * smb_opipe_close
265  *
266  * Called by smb_ofile_close for pipes.
267  *
268  * Note: ksocket_close may block while waiting for
269  * any I/O threads with a hold to get out.
270  */
271 void
smb_opipe_close(smb_ofile_t * of)272 smb_opipe_close(smb_ofile_t *of)
273 {
274 	smb_opipe_t *opipe;
275 	ksocket_t sock;
276 
277 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
278 	ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
279 	opipe = of->f_pipe;
280 	SMB_OPIPE_VALID(opipe);
281 
282 	mutex_enter(&opipe->p_mutex);
283 	sock = opipe->p_socket;
284 	opipe->p_socket = NULL;
285 	mutex_exit(&opipe->p_mutex);
286 
287 	(void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr);
288 	(void) ksocket_close(sock, of->f_cr);
289 }
290 
291 /*
292  * smb_opipe_write
293  *
294  * Write RPC request data to the pipe.  The client should call smb_opipe_read
295  * to complete the exchange and obtain the RPC response.
296  *
297  * Returns 0 on success or an errno on failure.
298  */
299 int
smb_opipe_write(smb_request_t * sr,struct uio * uio)300 smb_opipe_write(smb_request_t *sr, struct uio *uio)
301 {
302 	struct nmsghdr msghdr;
303 	smb_ofile_t *ofile;
304 	smb_opipe_t *opipe;
305 	ksocket_t sock;
306 	size_t sent = 0;
307 	int rc = 0;
308 
309 	ofile = sr->fid_ofile;
310 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
311 	opipe = ofile->f_pipe;
312 	SMB_OPIPE_VALID(opipe);
313 
314 	mutex_enter(&opipe->p_mutex);
315 	sock = opipe->p_socket;
316 	if (sock != NULL)
317 		ksocket_hold(sock);
318 	mutex_exit(&opipe->p_mutex);
319 	if (sock == NULL)
320 		return (EBADF);
321 
322 	bzero(&msghdr, sizeof (msghdr));
323 	msghdr.msg_iov = uio->uio_iov;
324 	msghdr.msg_iovlen = uio->uio_iovcnt;
325 
326 	/*
327 	 * This should block until we've sent it all,
328 	 * or given up due to errors (pipe closed).
329 	 */
330 	while (uio->uio_resid > 0) {
331 		rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr);
332 		if (rc != 0)
333 			break;
334 		uio->uio_resid -= sent;
335 	}
336 
337 	ksocket_rele(sock);
338 
339 	return (rc);
340 }
341 
342 /*
343  * smb_opipe_read
344  *
345  * This interface may be called from smb_opipe_transact (write, read)
346  * or from smb_read / smb2_read to get the rest of an RPC response.
347  * The response data (and length) are returned via the uio.
348  */
349 int
smb_opipe_read(smb_request_t * sr,struct uio * uio)350 smb_opipe_read(smb_request_t *sr, struct uio *uio)
351 {
352 	struct nmsghdr msghdr;
353 	smb_ofile_t *ofile;
354 	smb_opipe_t *opipe;
355 	ksocket_t sock;
356 	size_t recvcnt = 0;
357 	int rc;
358 
359 	ofile = sr->fid_ofile;
360 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
361 	opipe = ofile->f_pipe;
362 	SMB_OPIPE_VALID(opipe);
363 
364 	mutex_enter(&opipe->p_mutex);
365 	sock = opipe->p_socket;
366 	if (sock != NULL)
367 		ksocket_hold(sock);
368 	mutex_exit(&opipe->p_mutex);
369 	if (sock == NULL)
370 		return (EBADF);
371 
372 	bzero(&msghdr, sizeof (msghdr));
373 	msghdr.msg_iov = uio->uio_iov;
374 	msghdr.msg_iovlen = uio->uio_iovcnt;
375 
376 	/*
377 	 * This should block only if there's no data.
378 	 * A single call to recvmsg does just that.
379 	 * (Intentionaly no recv loop here.)
380 	 */
381 	rc = ksocket_recvmsg(sock, &msghdr, 0,
382 	    &recvcnt, ofile->f_cr);
383 	if (rc != 0)
384 		goto out;
385 
386 	if (recvcnt == 0) {
387 		/* Other side closed. */
388 		rc = EPIPE;
389 		goto out;
390 	}
391 	uio->uio_resid -= recvcnt;
392 
393 out:
394 	ksocket_rele(sock);
395 
396 	return (rc);
397 }
398 
399 int
smb_opipe_get_nread(smb_request_t * sr,int * nread)400 smb_opipe_get_nread(smb_request_t *sr, int *nread)
401 {
402 	smb_ofile_t *ofile;
403 	smb_opipe_t *opipe;
404 	ksocket_t sock;
405 	int rc, trval;
406 
407 	ofile = sr->fid_ofile;
408 	ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
409 	opipe = ofile->f_pipe;
410 	SMB_OPIPE_VALID(opipe);
411 
412 	mutex_enter(&opipe->p_mutex);
413 	sock = opipe->p_socket;
414 	if (sock != NULL)
415 		ksocket_hold(sock);
416 	mutex_exit(&opipe->p_mutex);
417 	if (sock == NULL)
418 		return (EBADF);
419 
420 	rc = ksocket_ioctl(sock, FIONREAD, (intptr_t)nread, &trval,
421 	    ofile->f_cr);
422 
423 	ksocket_rele(sock);
424 
425 	return (rc);
426 }
427