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 *
  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_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
 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
 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
 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
 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
 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
 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
 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
 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 }