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 #include <smbsrv/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 *
smb_opipe_alloc(smb_request_t * sr)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
smb_opipe_dealloc(smb_opipe_t * opipe)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
smb_opipe_connect(smb_request_t * sr,smb_opipe_t * opipe)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
smb_opipe_send_userinfo(smb_request_t * sr,smb_opipe_t * opipe,smb_error_t * errp)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
smb_opipe_open(smb_request_t * sr,uint32_t uniqid)212 smb_opipe_open(smb_request_t *sr, uint32_t uniqid)
213 {
214 smb_arg_open_t *op = &sr->sr_open;
215 smb_ofile_t *ofile;
216 smb_opipe_t *opipe;
217 smb_error_t err;
218
219 opipe = smb_opipe_alloc(sr);
220 if (opipe == NULL)
221 return (NT_STATUS_INTERNAL_ERROR);
222
223 if (smb_opipe_connect(sr, opipe) != 0) {
224 smb_opipe_dealloc(opipe);
225 return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
226 }
227
228 smb_opipe_send_userinfo(sr, opipe, &err);
229 if (err.status != 0) {
230 smb_opipe_dealloc(opipe);
231 return (err.status);
232 }
233
234 /*
235 * Note: If smb_ofile_open succeeds, the new ofile is
236 * in the FID lists can can be used by I/O requests.
237 */
238 op->create_options = 0;
239 op->pipe = opipe;
240 ofile = smb_ofile_open(sr, NULL, op,
241 SMB_FTYPE_MESG_PIPE, uniqid, &err);
242 op->pipe = NULL;
243 if (ofile == NULL) {
244 smb_opipe_dealloc(opipe);
245 return (err.status);
246 }
247
248 /* An "up" pointer, for debug. */
249 opipe->p_ofile = ofile;
250
251 op->dsize = 0x01000;
252 op->dattr = FILE_ATTRIBUTE_NORMAL;
253 op->ftype = SMB_FTYPE_MESG_PIPE;
254 op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */
255 op->devstate = SMB_PIPE_READMODE_MESSAGE
256 | SMB_PIPE_TYPE_MESSAGE
257 | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
258 op->fileid = ofile->f_fid;
259
260 sr->smb_fid = ofile->f_fid;
261 sr->fid_ofile = ofile;
262
263 return (NT_STATUS_SUCCESS);
264 }
265
266 /*
267 * smb_opipe_close
268 *
269 * Called by smb_ofile_close for pipes.
270 *
271 * Note: ksocket_close may block while waiting for
272 * any I/O threads with a hold to get out.
273 */
274 void
smb_opipe_close(smb_ofile_t * of)275 smb_opipe_close(smb_ofile_t *of)
276 {
277 smb_opipe_t *opipe;
278 ksocket_t sock;
279
280 ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
281 ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
282 opipe = of->f_pipe;
283 SMB_OPIPE_VALID(opipe);
284
285 mutex_enter(&opipe->p_mutex);
286 sock = opipe->p_socket;
287 opipe->p_socket = NULL;
288 mutex_exit(&opipe->p_mutex);
289
290 (void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr);
291 (void) ksocket_close(sock, of->f_cr);
292 }
293
294 /*
295 * smb_opipe_write
296 *
297 * Write RPC request data to the pipe. The client should call smb_opipe_read
298 * to complete the exchange and obtain the RPC response.
299 *
300 * Returns 0 on success or an errno on failure.
301 */
302 int
smb_opipe_write(smb_request_t * sr,struct uio * uio)303 smb_opipe_write(smb_request_t *sr, struct uio *uio)
304 {
305 struct nmsghdr msghdr;
306 smb_ofile_t *ofile;
307 smb_opipe_t *opipe;
308 ksocket_t sock;
309 size_t sent = 0;
310 int rc = 0;
311
312 ofile = sr->fid_ofile;
313 ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
314 opipe = ofile->f_pipe;
315 SMB_OPIPE_VALID(opipe);
316
317 mutex_enter(&opipe->p_mutex);
318 sock = opipe->p_socket;
319 if (sock != NULL)
320 ksocket_hold(sock);
321 mutex_exit(&opipe->p_mutex);
322 if (sock == NULL)
323 return (EBADF);
324
325 bzero(&msghdr, sizeof (msghdr));
326 msghdr.msg_iov = uio->uio_iov;
327 msghdr.msg_iovlen = uio->uio_iovcnt;
328
329 /*
330 * This should block until we've sent it all,
331 * or given up due to errors (pipe closed).
332 */
333 while (uio->uio_resid > 0) {
334 rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr);
335 if (rc != 0)
336 break;
337 uio->uio_resid -= sent;
338 }
339
340 ksocket_rele(sock);
341
342 return (rc);
343 }
344
345 /*
346 * smb_opipe_read
347 *
348 * This interface may be called from smb_opipe_transact (write, read)
349 * or from smb_read / smb2_read to get the rest of an RPC response.
350 * The response data (and length) are returned via the uio.
351 */
352 int
smb_opipe_read(smb_request_t * sr,struct uio * uio)353 smb_opipe_read(smb_request_t *sr, struct uio *uio)
354 {
355 struct nmsghdr msghdr;
356 smb_ofile_t *ofile;
357 smb_opipe_t *opipe;
358 ksocket_t sock;
359 size_t recvcnt = 0;
360 int rc;
361
362 ofile = sr->fid_ofile;
363 ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
364 opipe = ofile->f_pipe;
365 SMB_OPIPE_VALID(opipe);
366
367 mutex_enter(&opipe->p_mutex);
368 sock = opipe->p_socket;
369 if (sock != NULL)
370 ksocket_hold(sock);
371 mutex_exit(&opipe->p_mutex);
372 if (sock == NULL)
373 return (EBADF);
374
375 bzero(&msghdr, sizeof (msghdr));
376 msghdr.msg_iov = uio->uio_iov;
377 msghdr.msg_iovlen = uio->uio_iovcnt;
378
379 /*
380 * This should block only if there's no data.
381 * A single call to recvmsg does just that.
382 * (Intentionaly no recv loop here.)
383 */
384 rc = ksocket_recvmsg(sock, &msghdr, 0,
385 &recvcnt, ofile->f_cr);
386 if (rc != 0)
387 goto out;
388
389 if (recvcnt == 0) {
390 /* Other side closed. */
391 rc = EPIPE;
392 goto out;
393 }
394 uio->uio_resid -= recvcnt;
395
396 out:
397 ksocket_rele(sock);
398
399 return (rc);
400 }
401
402 int
smb_opipe_ioctl(smb_request_t * sr,int cmd,void * arg,int * rvalp)403 smb_opipe_ioctl(smb_request_t *sr, int cmd, void *arg, int *rvalp)
404 {
405 smb_ofile_t *ofile;
406 smb_opipe_t *opipe;
407 ksocket_t sock;
408 int rc;
409
410 ofile = sr->fid_ofile;
411 ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
412 opipe = ofile->f_pipe;
413 SMB_OPIPE_VALID(opipe);
414
415 mutex_enter(&opipe->p_mutex);
416 sock = opipe->p_socket;
417 if (sock != NULL)
418 ksocket_hold(sock);
419 mutex_exit(&opipe->p_mutex);
420 if (sock == NULL)
421 return (EBADF);
422
423 rc = ksocket_ioctl(sock, cmd, (intptr_t)arg, rvalp, ofile->f_cr);
424
425 ksocket_rele(sock);
426
427 return (rc);
428 }
429
430 /*
431 * Get the smb_attr_t for a named pipe.
432 * Caller has already cleared to zero.
433 */
434 int
smb_opipe_getattr(smb_ofile_t * of,smb_attr_t * ap)435 smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
436 {
437
438 if (of->f_pipe == NULL)
439 return (EINVAL);
440
441 ap->sa_vattr.va_type = VFIFO;
442 ap->sa_vattr.va_nlink = 1;
443 ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
444 ap->sa_allocsz = 0x1000LL;
445
446 return (0);
447 }
448
449 int
smb_opipe_getname(smb_ofile_t * of,char * buf,size_t buflen)450 smb_opipe_getname(smb_ofile_t *of, char *buf, size_t buflen)
451 {
452 smb_opipe_t *opipe;
453
454 if ((opipe = of->f_pipe) == NULL)
455 return (EINVAL);
456
457 (void) snprintf(buf, buflen, "\\%s", opipe->p_name);
458 return (0);
459 }
460
461 /*
462 * Handler for smb2_ioctl
463 */
464 /* ARGSUSED */
465 uint32_t
smb_opipe_fsctl(smb_request_t * sr,smb_fsctl_t * fsctl)466 smb_opipe_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
467 {
468 uint32_t status;
469
470 switch (fsctl->CtlCode) {
471 case FSCTL_PIPE_TRANSCEIVE:
472 status = smb_opipe_transceive(sr, fsctl);
473 break;
474
475 case FSCTL_PIPE_PEEK:
476 case FSCTL_PIPE_WAIT:
477 /* XXX todo */
478 status = NT_STATUS_NOT_SUPPORTED;
479 break;
480
481 default:
482 ASSERT(!"CtlCode");
483 status = NT_STATUS_INTERNAL_ERROR;
484 break;
485 }
486
487 return (status);
488 }
489
490 static uint32_t
smb_opipe_transceive(smb_request_t * sr,smb_fsctl_t * fsctl)491 smb_opipe_transceive(smb_request_t *sr, smb_fsctl_t *fsctl)
492 {
493 smb_vdb_t vdb;
494 smb_ofile_t *ofile;
495 struct mbuf *mb;
496 uint32_t status;
497 int len, rc;
498
499 /*
500 * Caller checked that this is the IPC$ share,
501 * and that this call has a valid open handle.
502 * Just check the type.
503 */
504 ofile = sr->fid_ofile;
505 if (ofile->f_ftype != SMB_FTYPE_MESG_PIPE)
506 return (NT_STATUS_INVALID_HANDLE);
507
508 rc = smb_mbc_decodef(fsctl->in_mbc, "#B",
509 fsctl->InputCount, &vdb);
510 if (rc != 0) {
511 /* Not enough data sent. */
512 return (NT_STATUS_INVALID_PARAMETER);
513 }
514
515 rc = smb_opipe_write(sr, &vdb.vdb_uio);
516 if (rc != 0)
517 return (smb_errno2status(rc));
518
519 vdb.vdb_tag = 0;
520 vdb.vdb_uio.uio_iov = &vdb.vdb_iovec[0];
521 vdb.vdb_uio.uio_iovcnt = MAX_IOVEC;
522 vdb.vdb_uio.uio_segflg = UIO_SYSSPACE;
523 vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
524 vdb.vdb_uio.uio_loffset = (offset_t)0;
525 vdb.vdb_uio.uio_resid = fsctl->MaxOutputResp;
526 mb = smb_mbuf_allocate(&vdb.vdb_uio);
527
528 rc = smb_opipe_read(sr, &vdb.vdb_uio);
529 if (rc != 0) {
530 m_freem(mb);
531 return (smb_errno2status(rc));
532 }
533
534 len = fsctl->MaxOutputResp - vdb.vdb_uio.uio_resid;
535 smb_mbuf_trim(mb, len);
536 MBC_ATTACH_MBUF(fsctl->out_mbc, mb);
537
538 /*
539 * If the output buffer holds a partial pipe message,
540 * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
541 * As we don't have message boundary markers, the best
542 * we can do is return that status when we have ALL of:
543 * Output buffer was < SMB_PIPE_MAX_MSGSIZE
544 * We filled the output buffer (resid==0)
545 * There's more data (ioctl FIONREAD)
546 */
547 status = NT_STATUS_SUCCESS;
548 if (fsctl->MaxOutputResp < SMB_PIPE_MAX_MSGSIZE &&
549 vdb.vdb_uio.uio_resid == 0) {
550 int nread = 0, trval;
551 rc = smb_opipe_ioctl(sr, FIONREAD, &nread, &trval);
552 if (rc == 0 && nread != 0)
553 status = NT_STATUS_BUFFER_OVERFLOW;
554 }
555
556 return (status);
557 }
558