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 }