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) 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 #include <sys/systm.h>
  26 #include <sys/cmn_err.h>
  27 #include <sys/stropts.h>
  28 #include <sys/strsun.h>
  29 #include <sys/socketvar.h>
  30 #include <sys/sockfilter.h>
  31 #include <inet/kssl/ksslapi.h>
  32 #include <sys/note.h>
  33 #include <sys/taskq.h>
  34 
  35 /*
  36  * Name of the KSSL filter
  37  */
  38 #define KSSL_FILNAME    "ksslf"
  39 
  40 static struct modlmisc ksslf_modlmisc = {
  41         &mod_miscops,
  42         "Kernel SSL socket filter"
  43 };
  44 
  45 static struct modlinkage ksslf_modlinkage = {
  46         MODREV_1,
  47         { &ksslf_modlmisc, NULL }
  48 };
  49 
  50 /*
  51  * kssl filter cookie
  52  */
  53 typedef struct ksslf {
  54         boolean_t       ksslf_pending;          /* waiting for 1st SSL rec. */
  55         boolean_t       ksslf_inhandshake;      /* during SSL handshake */
  56         kssl_ent_t      ksslf_ent;              /* SSL table entry */
  57         kssl_ctx_t      ksslf_ctx;              /* SSL session */
  58         kssl_endpt_type_t ksslf_type;           /* is proxy/is proxied/none */
  59         struct sockaddr_in6 ksslf_laddr;        /* local address */
  60         socklen_t       ksslf_laddrlen;
  61         struct ksslf    *ksslf_listener;
  62 } ksslf_t;
  63 
  64 static void kssl_input_callback(void *, mblk_t *, kssl_cmd_t);
  65 
  66 /*
  67  * Allocate kssl state
  68  */
  69 sof_rval_t
  70 kssl_attach_passive_cb(sof_handle_t handle, sof_handle_t ph,
  71     void *parg, struct sockaddr *laddr, socklen_t laddrlen,
  72     struct sockaddr *faddr, socklen_t faddrlen, void **cookiep)
  73 {
  74         ksslf_t *listener = (ksslf_t *)parg;
  75         ksslf_t *new;
  76 
  77         _NOTE(ARGUNUSED(handle, ph, faddrlen, laddr, laddrlen));
  78 
  79         if (listener == NULL || listener->ksslf_ent == NULL)
  80                 return (SOF_RVAL_DETACH);
  81         /*
  82          * Only way for a fallback listener to receive connections is when
  83          * a handshake fails and socket is moved from the proxy to the fallback.
  84          * Connections that come in directly on the fallback are denied.
  85          */
  86         if (listener->ksslf_type == KSSL_HAS_PROXY)
  87                 return (SOF_RVAL_EACCES);
  88 
  89         /* Allocate the SSL context for the new connection */
  90         new = kmem_zalloc(sizeof (ksslf_t), KM_NOSLEEP);
  91         if (new == NULL)
  92                 return (SOF_RVAL_ENOMEM);
  93 
  94         /*
  95          * The mss is initialized to SSL3_MAX_RECORD_LEN, but might be
  96          * updated by the mblk_prop callback.
  97          */
  98         if (kssl_init_context(listener->ksslf_ent, faddr, SSL3_MAX_RECORD_LEN,
  99             &new->ksslf_ctx) != KSSL_STS_OK)
 100                 return (SOF_RVAL_ENOMEM);
 101 
 102         new->ksslf_pending = B_TRUE;
 103         new->ksslf_inhandshake = B_TRUE;
 104         ASSERT(laddrlen <= sizeof (new->ksslf_laddr));
 105         new->ksslf_laddrlen = laddrlen;
 106         bcopy(laddr, &new->ksslf_laddr, laddrlen);
 107         new->ksslf_laddr.sin6_port = listener->ksslf_laddr.sin6_port;
 108         new->ksslf_listener = listener;
 109 
 110         *cookiep = new;
 111         /*
 112          * We are in handshake, defer the notification of this connection
 113          * until it is completed.
 114          */
 115         return (SOF_RVAL_DEFER);
 116 }
 117 
 118 void
 119 kssl_detach_cb(sof_handle_t handle, void *cookie, cred_t *cr)
 120 {
 121         ksslf_t *kssl = (ksslf_t *)cookie;
 122 
 123         _NOTE(ARGUNUSED(handle, cr));
 124 
 125         if (kssl == NULL)
 126                 return;
 127 
 128         if (kssl->ksslf_ent != NULL) {
 129                 kssl_release_ent(kssl->ksslf_ent, handle, kssl->ksslf_type);
 130                 kssl->ksslf_ent = NULL;
 131         }
 132         if (kssl->ksslf_ctx != NULL) {
 133                 kssl_release_ctx(kssl->ksslf_ctx);
 134                 kssl->ksslf_ctx = NULL;
 135         }
 136 
 137         kmem_free(kssl, sizeof (ksslf_t));
 138 }
 139 
 140 sof_rval_t
 141 kssl_bind_cb(sof_handle_t handle, void *cookie, struct sockaddr *name,
 142     socklen_t *namelen, cred_t *cr)
 143 {
 144         kssl_ent_t ent;
 145         kssl_endpt_type_t type;
 146         ksslf_t *kssl;
 147         in_port_t origport;
 148 
 149         _NOTE(ARGUNUSED(cr));
 150 
 151         if (cookie != NULL)
 152                 return (SOF_RVAL_EINVAL);
 153 
 154         if (*namelen < sizeof (struct sockaddr_in)) {
 155                 sof_bypass(handle);
 156                 return (SOF_RVAL_CONTINUE);
 157         }
 158 
 159         origport = ((struct sockaddr_in *)name)->sin_port;
 160         /* Check if KSSL has been configured for this address */
 161         type = kssl_check_proxy(name, *namelen, handle, &ent);
 162 
 163         switch (type) {
 164         case KSSL_NO_PROXY:
 165                 sof_bypass(handle);
 166                 break;
 167         case KSSL_HAS_PROXY:
 168         case KSSL_IS_PROXY:
 169                 kssl = kmem_zalloc(sizeof (ksslf_t), KM_SLEEP);
 170                 kssl->ksslf_type = type;
 171                 kssl->ksslf_ent = ent;
 172 
 173                 /*
 174                  * In the unlikely event that there are multiple simultaneous
 175                  * bind requests, and the cookie was already swapped out, then
 176                  * just drop this cookie and let the bind continue unmodified.
 177                  */
 178                 if (sof_cas_cookie(handle, cookie, kssl) != cookie) {
 179                         kssl_release_ent(ent, handle, type);
 180                         kmem_free(kssl, sizeof (ksslf_t));
 181                         ((struct sockaddr_in *)name)->sin_port = origport;
 182                         break;
 183                 }
 184 
 185                 kssl->ksslf_laddrlen = *namelen;
 186                 bcopy(name, &kssl->ksslf_laddr, kssl->ksslf_laddrlen);
 187                 kssl->ksslf_laddr.sin6_port = origport;
 188                 /*
 189                  * kssl_check_proxy updated the sockaddr, so just
 190                  * pass it along to the protocol.
 191                  */
 192                 return ((type == KSSL_HAS_PROXY) ? SOF_RVAL_RETURN :
 193                     SOF_RVAL_CONTINUE);
 194         }
 195         return (SOF_RVAL_CONTINUE);
 196 }
 197 
 198 sof_rval_t
 199 kssl_listen_cb(sof_handle_t handle, void *cookie, int *backlog, cred_t *cr)
 200 {
 201         ksslf_t *kssl = (ksslf_t *)cookie;
 202 
 203         _NOTE(ARGUNUSED(backlog, cr));
 204 
 205         /*
 206          * The cookie can be NULL in the unlikely event of an application doing
 207          * listen() without binding to an address. Those listeners are of no
 208          * interest.
 209          */
 210         if (kssl == NULL) {
 211                 sof_bypass(handle);
 212                 return (SOF_RVAL_CONTINUE);
 213         }
 214 
 215         return (SOF_RVAL_CONTINUE);
 216 
 217 }
 218 
 219 /*
 220  * Outgoing connections are not of interest, so just bypass the filter.
 221  */
 222 sof_rval_t
 223 kssl_connect_cb(sof_handle_t handle, void *cookie, struct sockaddr *name,
 224     socklen_t *namelen, cred_t *cr)
 225 {
 226         _NOTE(ARGUNUSED(cookie, name, namelen, cr));
 227 
 228         sof_bypass(handle);
 229         return (SOF_RVAL_CONTINUE);
 230 }
 231 
 232 static void
 233 kssl_mblk_prop_cb(sof_handle_t handle, void *cookie, ssize_t *maxblk,
 234     ushort_t *wroff, ushort_t *tail)
 235 {
 236         ksslf_t *kssl = (ksslf_t *)cookie;
 237 
 238         _NOTE(ARGUNUSED(handle));
 239 
 240         /* only care about passively opened sockets */
 241         if (kssl == NULL || !kssl->ksslf_pending)
 242                 return;
 243         /*
 244          * If this is endpoint is handling SSL, then reserve extra
 245          * offset and space at the end. Also have sockfs allocate
 246          * SSL3_MAX_RECORD_LEN packets, overriding the previous setting.
 247          * The extra cost of signing and encrypting multiple MSS-size
 248          * records (12 of them with Ethernet), instead of a single
 249          * contiguous one by the stream head largely outweighs the
 250          * statistical reduction of ACKs, when applicable. The peer
 251          * will also save on decryption and verification costs.
 252          */
 253         if (*maxblk == INFPSZ || *maxblk > SSL3_MAX_RECORD_LEN)
 254                 *maxblk = SSL3_MAX_RECORD_LEN;
 255         else
 256                 kssl_set_mss(kssl->ksslf_ctx, *maxblk);
 257         *wroff += SSL3_WROFFSET;
 258         *tail += SSL3_MAX_TAIL_LEN;
 259 }
 260 
 261 sof_rval_t
 262 kssl_getsockname_cb(sof_handle_t handle, void *cookie, struct sockaddr *addr,
 263     socklen_t *addrlen, cred_t *cr)
 264 {
 265         ksslf_t *kssl = (ksslf_t *)cookie;
 266 
 267         _NOTE(ARGUNUSED(handle, cr));
 268 
 269         if (kssl == NULL)
 270                 return (SOF_RVAL_CONTINUE);
 271 
 272         if (*addrlen < kssl->ksslf_laddrlen)
 273                 return (SOF_RVAL_EINVAL);
 274 
 275         *addrlen = kssl->ksslf_laddrlen;
 276         bcopy(&kssl->ksslf_laddr, addr, kssl->ksslf_laddrlen);
 277 
 278         return (SOF_RVAL_RETURN);
 279 }
 280 
 281 /*
 282  * Called for every packet sent to the protocol.
 283  * If the message is successfully processed, then it is returned.
 284  */
 285 mblk_t *
 286 kssl_data_out_cb(sof_handle_t handle, void *cookie, mblk_t *mp,
 287     struct nmsghdr *msg, cred_t *cr, sof_rval_t *rv)
 288 {
 289         ksslf_t *kssl = (ksslf_t *)cookie;
 290         mblk_t *recmp;
 291 
 292         _NOTE(ARGUNUSED(handle, msg, cr));
 293 
 294         *rv = SOF_RVAL_CONTINUE;
 295         if (kssl == NULL || kssl->ksslf_ctx == NULL)
 296                 return (mp);
 297 
 298         if ((recmp = kssl_build_record(kssl->ksslf_ctx, mp)) == NULL) {
 299                 freemsg(mp);
 300                 *rv = SOF_RVAL_EINVAL;
 301                 return (NULL);
 302         }
 303         return (recmp);
 304 }
 305 
 306 /*
 307  * Called from shutdown() processing. This will produce close_notify message
 308  * to indicate the end of data to the client.
 309  */
 310 sof_rval_t
 311 kssl_shutdown_cb(sof_handle_t handle, void *cookie, int *howp, cred_t *cr)
 312 {
 313         ksslf_t *kssl = (ksslf_t *)cookie;
 314         mblk_t *outmp;
 315         boolean_t flowctrld;
 316         struct nmsghdr msg;
 317 
 318         _NOTE(ARGUNUSED(cr));
 319 
 320         if (kssl == NULL || kssl->ksslf_ctx == NULL)
 321                 return (SOF_RVAL_CONTINUE);
 322 
 323         /*
 324          * We only want to send close_notify when doing SHUT_WR/SHUT_RDWR
 325          * because it signals that server is done writing data.
 326          */
 327         if (*howp == SHUT_RD)
 328                 return (SOF_RVAL_CONTINUE);
 329 
 330         /* Go on if we fail to build the record. */
 331         if ((outmp = kssl_build_record(kssl->ksslf_ctx, NULL)) == NULL)
 332                 return (SOF_RVAL_CONTINUE);
 333 
 334         bzero(&msg, sizeof (msg));
 335         (void) sof_inject_data_out(handle, outmp, &msg,
 336             &flowctrld);
 337 
 338         return (SOF_RVAL_CONTINUE);
 339 }
 340 
 341 /*
 342  * Called for each incoming segment.
 343  *
 344  * A packet may carry multiple SSL records, so the function calls
 345  * kssl_input() in a loop, until all records are handled.
 346  */
 347 mblk_t *
 348 kssl_data_in_cb(sof_handle_t handle, void *cookie, mblk_t *mp, int flags,
 349     size_t *lenp)
 350 {
 351         ksslf_t         *kssl = cookie;
 352         kssl_cmd_t      kssl_cmd;
 353         mblk_t          *outmp, *retmp = NULL, **tail = &retmp;
 354         boolean_t       more = B_FALSE;
 355         boolean_t       flowctrld;
 356 
 357         _NOTE(ARGUNUSED(flags));
 358 
 359         if (kssl == NULL || kssl->ksslf_ctx == NULL) {
 360                 sof_bypass(handle);
 361                 return (mp);
 362         }
 363 
 364         *lenp = 0;
 365         do {
 366                 kssl_cmd = kssl_input(kssl->ksslf_ctx, mp, &outmp,
 367                     &more, kssl_input_callback, (void *)handle);
 368 
 369                 switch (kssl_cmd) {
 370                 case KSSL_CMD_SEND: {
 371                         struct nmsghdr msg;
 372 
 373                         DTRACE_PROBE(kssl_cmd_send);
 374                         bzero(&msg, sizeof (msg));
 375                         (void) sof_inject_data_out(handle, outmp, &msg,
 376                             &flowctrld);
 377                 }
 378                 /* FALLTHROUGH */
 379                 case KSSL_CMD_NONE:
 380                         DTRACE_PROBE(kssl_cmd_none);
 381                         if (kssl->ksslf_pending) {
 382                                 kssl->ksslf_pending = B_FALSE;
 383                                 sof_newconn_ready(handle);
 384                         }
 385                         break;
 386 
 387                 case KSSL_CMD_QUEUED:
 388                         DTRACE_PROBE(kssl_cmd_queued);
 389                         break;
 390 
 391                 case KSSL_CMD_DELIVER_PROXY:
 392                 case KSSL_CMD_DELIVER_SSL:
 393                         DTRACE_PROBE(kssl_cmd_proxy__ssl);
 394                         /*
 395                          * We're at a phase where records are sent upstreams,
 396                          * past the handshake
 397                          */
 398                         kssl->ksslf_inhandshake = B_FALSE;
 399 
 400                         *tail = outmp;
 401                         *lenp += MBLKL(outmp);
 402                         while (outmp->b_cont != NULL) {
 403                                 outmp = outmp->b_cont;
 404                                 *lenp += MBLKL(outmp);
 405                         }
 406                         tail = &outmp->b_cont;
 407                         break;
 408 
 409                 case KSSL_CMD_NOT_SUPPORTED: {
 410                         ksslf_t *listener = kssl->ksslf_listener;
 411                         sof_handle_t fallback;
 412 
 413                         DTRACE_PROBE(kssl_cmd_not_supported);
 414                         /*
 415                          * Stop the SSL processing by the proxy, and
 416                          * switch to the userland SSL
 417                          */
 418                         if (kssl->ksslf_pending) {
 419                                 kssl->ksslf_pending = B_FALSE;
 420 
 421                                 DTRACE_PROBE1(kssl_no_can_do, sof_handle_t,
 422                                     handle);
 423 
 424                                 sof_bypass(handle);
 425 
 426                                 ASSERT(listener->ksslf_ent != NULL);
 427                                 fallback =
 428                                     kssl_find_fallback(listener->ksslf_ent);
 429                                 /*
 430                                  * No fallback: the remote will timeout and
 431                                  * disconnect.
 432                                  */
 433                                 if (fallback != NULL &&
 434                                     sof_newconn_move(handle, fallback))
 435                                         sof_newconn_ready(handle);
 436                         }
 437                         if (mp != NULL) {
 438                                 *tail = mp;
 439                                 *lenp += MBLKL(mp);
 440                                 while (mp->b_cont != NULL) {
 441                                         mp = mp->b_cont;
 442                                         *lenp += MBLKL(mp);
 443                                 }
 444                                 tail = &mp->b_cont;
 445                         }
 446                         break;
 447                 }
 448                 }
 449                 mp = NULL;
 450         } while (more);
 451 
 452         return (retmp);
 453 }
 454 
 455 /*
 456  * Process queued data before it's copied by the user.
 457  *
 458  * If the message is successfully processed, then it is returned.
 459  * A failed message will be freed.
 460  */
 461 mblk_t *
 462 kssl_data_in_proc_cb(sof_handle_t handle, void *cookie, mblk_t *mp,
 463     cred_t *cr, size_t *lenp)
 464 {
 465         ksslf_t *kssl = (ksslf_t *)cookie;
 466         kssl_cmd_t kssl_cmd;
 467         mblk_t *out;
 468 
 469         _NOTE(ARGUNUSED(cr));
 470 
 471         if (kssl == NULL || kssl->ksslf_ctx)
 472                 return (mp);
 473 
 474         *lenp = 0;
 475 
 476         kssl_cmd = kssl_handle_mblk(kssl->ksslf_ctx, &mp, &out);
 477 
 478         switch (kssl_cmd) {
 479         case KSSL_CMD_NONE:
 480                 return (NULL);
 481         case KSSL_CMD_DELIVER_PROXY:
 482                 *lenp = msgdsize(mp);
 483                 return (mp);
 484         case KSSL_CMD_SEND: {
 485                 struct nmsghdr msg;
 486                 boolean_t flowctrld;
 487 
 488                 ASSERT(out != NULL);
 489                 bzero(&msg, sizeof (msg));
 490 
 491                 (void) sof_inject_data_out(handle, out, &msg,
 492                     &flowctrld);
 493                 return (NULL);
 494         }
 495         default:
 496                 /* transient error. */
 497                 return (NULL);
 498         }
 499 }
 500 
 501 /*
 502  * Continue processing the incoming flow after an asynchronous callback.
 503  */
 504 static void
 505 kssl_input_asynch(void *arg)
 506 {
 507         sof_handle_t handle = (sof_handle_t)arg;
 508         ksslf_t *kssl = (ksslf_t *)sof_get_cookie(handle);
 509         size_t len = 0;
 510         boolean_t flowctrld;
 511         mblk_t *mp;
 512 
 513         if ((mp = kssl_data_in_cb(handle, kssl, NULL, 0, &len)) != NULL) {
 514                 ASSERT(len != 0);
 515                 (void) sof_inject_data_in(handle, mp, len, 0, &flowctrld);
 516         }
 517         kssl_async_done(kssl->ksslf_ctx);
 518 }
 519 
 520 /*
 521  * Callback function for the cases kssl_input() had to submit an asynchronous
 522  * job and need to come back when done to carry on the input processing.
 523  * This routine follows the conentions of timeout and interrupt handlers.
 524  * (no blocking, ...)
 525  */
 526 static void
 527 kssl_input_callback(void *arg, mblk_t *mp, kssl_cmd_t kssl_cmd)
 528 {
 529         sof_handle_t handle = (sof_handle_t)arg;
 530         ksslf_t *kssl = (ksslf_t *)sof_get_cookie(handle);
 531         boolean_t flowctrld;
 532 
 533         ASSERT(kssl != NULL);
 534 
 535         switch (kssl_cmd) {
 536         case KSSL_CMD_SEND: {
 537                 struct nmsghdr msg;
 538 
 539                 if (mp == NULL)
 540                         break;
 541                 bzero(&msg, sizeof (msg));
 542 
 543                 (void) sof_inject_data_out(handle, mp, &msg, &flowctrld);
 544         }
 545         /* FALLTHROUGH */
 546         case KSSL_CMD_NONE:
 547                 break;
 548 
 549         case KSSL_CMD_DELIVER_PROXY:
 550         case KSSL_CMD_DELIVER_SSL:
 551                 (void) sof_inject_data_in(handle, mp, msgdsize(mp), 0,
 552                     &flowctrld);
 553                 break;
 554 
 555         case KSSL_CMD_NOT_SUPPORTED:
 556                 /* Stop the SSL processing */
 557                 sof_bypass(handle);
 558         }
 559         /*
 560          * Process any input that may have accumulated while we're waiting for
 561          * the call-back. This must be done by a taskq because kssl_input might
 562          * block when handling client_finish messages.
 563          */
 564         if (taskq_dispatch(system_taskq, kssl_input_asynch, handle,
 565             TQ_NOSLEEP) == NULL) {
 566                 DTRACE_PROBE(kssl_err__taskq_dispatch_failed);
 567                 kssl_async_done(kssl->ksslf_ctx);
 568         }
 569 }
 570 
 571 sof_ops_t ksslf_ops = {
 572         .sofop_attach_passive = kssl_attach_passive_cb,
 573         .sofop_detach = kssl_detach_cb,
 574         .sofop_bind = kssl_bind_cb,
 575         .sofop_connect = kssl_connect_cb,
 576         .sofop_listen = kssl_listen_cb,
 577         .sofop_data_in = kssl_data_in_cb,
 578         .sofop_data_in_proc = kssl_data_in_proc_cb,
 579         .sofop_data_out = kssl_data_out_cb,
 580         .sofop_mblk_prop = kssl_mblk_prop_cb,
 581         .sofop_getsockname = kssl_getsockname_cb,
 582         .sofop_shutdown = kssl_shutdown_cb,
 583 };
 584 
 585 int
 586 _init(void)
 587 {
 588         int error;
 589 
 590         if ((error = sof_register(SOF_VERSION, KSSL_FILNAME,
 591             &ksslf_ops, 0)) != 0)
 592                 return (error);
 593         if ((error = mod_install(&ksslf_modlinkage)) != 0)
 594                 (void) sof_unregister(KSSL_FILNAME);
 595 
 596         return (error);
 597 }
 598 
 599 int
 600 _fini(void)
 601 {
 602         int error;
 603 
 604         if ((error = sof_unregister(KSSL_FILNAME)) != 0)
 605                 return (error);
 606 
 607         return (mod_remove(&ksslf_modlinkage));
 608 }
 609 
 610 int
 611 _info(struct modinfo *modinfop)
 612 {
 613         return (mod_info(&ksslf_modlinkage, modinfop));
 614 }