/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <sys/socketvar.h>
#include <sys/sockfilter.h>
/*
* Name of the KSSL filter
*/
"Kernel SSL socket filter"
};
};
/*
* kssl filter cookie
*/
typedef struct ksslf {
} ksslf_t;
/*
* Allocate kssl state
*/
{
return (SOF_RVAL_DETACH);
/*
* Only way for a fallback listener to receive connections is when
* a handshake fails and socket is moved from the proxy to the fallback.
* Connections that come in directly on the fallback are denied.
*/
return (SOF_RVAL_EACCES);
/* Allocate the SSL context for the new connection */
return (SOF_RVAL_ENOMEM);
/*
* The mss is initialized to SSL3_MAX_RECORD_LEN, but might be
* updated by the mblk_prop callback.
*/
return (SOF_RVAL_ENOMEM);
/*
* We are in handshake, defer the notification of this connection
* until it is completed.
*/
return (SOF_RVAL_DEFER);
}
void
{
return;
}
}
}
{
return (SOF_RVAL_EINVAL);
if (*namelen < sizeof (struct sockaddr_in)) {
return (SOF_RVAL_CONTINUE);
}
/* Check if KSSL has been configured for this address */
switch (type) {
case KSSL_NO_PROXY:
break;
case KSSL_HAS_PROXY:
case KSSL_IS_PROXY:
/*
* In the unlikely event that there are multiple simultaneous
* bind requests, and the cookie was already swapped out, then
* just drop this cookie and let the bind continue unmodified.
*/
break;
}
/*
* kssl_check_proxy updated the sockaddr, so just
* pass it along to the protocol.
*/
}
return (SOF_RVAL_CONTINUE);
}
{
/*
* The cookie can be NULL in the unlikely event of an application doing
* listen() without binding to an address. Those listeners are of no
* interest.
*/
return (SOF_RVAL_CONTINUE);
}
return (SOF_RVAL_CONTINUE);
}
/*
* Outgoing connections are not of interest, so just bypass the filter.
*/
{
return (SOF_RVAL_CONTINUE);
}
static void
{
/* only care about passively opened sockets */
return;
/*
* If this is endpoint is handling SSL, then reserve extra
* offset and space at the end. Also have sockfs allocate
* SSL3_MAX_RECORD_LEN packets, overriding the previous setting.
* The extra cost of signing and encrypting multiple MSS-size
* records (12 of them with Ethernet), instead of a single
* contiguous one by the stream head largely outweighs the
* statistical reduction of ACKs, when applicable. The peer
* will also save on decryption and verification costs.
*/
else
*wroff += SSL3_WROFFSET;
*tail += SSL3_MAX_TAIL_LEN;
}
{
return (SOF_RVAL_CONTINUE);
return (SOF_RVAL_EINVAL);
return (SOF_RVAL_RETURN);
}
/*
* Called for every packet sent to the protocol.
* If the message is successfully processed, then it is returned.
*/
mblk_t *
{
*rv = SOF_RVAL_CONTINUE;
return (mp);
*rv = SOF_RVAL_EINVAL;
return (NULL);
}
return (recmp);
}
/*
* Called from shutdown() processing. This will produce close_notify message
* to indicate the end of data to the client.
*/
{
return (SOF_RVAL_CONTINUE);
/*
* because it signals that server is done writing data.
*/
return (SOF_RVAL_CONTINUE);
/* Go on if we fail to build the record. */
return (SOF_RVAL_CONTINUE);
&flowctrld);
return (SOF_RVAL_CONTINUE);
}
/*
* Called for each incoming segment.
*
* A packet may carry multiple SSL records, so the function calls
* kssl_input() in a loop, until all records are handled.
*/
mblk_t *
{
return (mp);
}
*lenp = 0;
do {
switch (kssl_cmd) {
case KSSL_CMD_SEND: {
&flowctrld);
}
/* FALLTHROUGH */
case KSSL_CMD_NONE:
if (kssl->ksslf_pending) {
}
break;
case KSSL_CMD_QUEUED:
break;
case KSSL_CMD_DELIVER_PROXY:
case KSSL_CMD_DELIVER_SSL:
/*
* We're at a phase where records are sent upstreams,
* past the handshake
*/
}
break;
case KSSL_CMD_NOT_SUPPORTED: {
/*
* Stop the SSL processing by the proxy, and
* switch to the userland SSL
*/
if (kssl->ksslf_pending) {
handle);
fallback =
/*
* No fallback: the remote will timeout and
* disconnect.
*/
}
}
}
break;
}
}
} while (more);
return (retmp);
}
/*
* Process queued data before it's copied by the user.
*
* If the message is successfully processed, then it is returned.
* A failed message will be freed.
*/
mblk_t *
{
return (mp);
*lenp = 0;
switch (kssl_cmd) {
case KSSL_CMD_NONE:
return (NULL);
case KSSL_CMD_DELIVER_PROXY:
return (mp);
case KSSL_CMD_SEND: {
&flowctrld);
return (NULL);
}
default:
/* transient error. */
return (NULL);
}
}
/*
* Continue processing the incoming flow after an asynchronous callback.
*/
static void
{
}
}
/*
* Callback function for the cases kssl_input() had to submit an asynchronous
* job and need to come back when done to carry on the input processing.
* This routine follows the conentions of timeout and interrupt handlers.
* (no blocking, ...)
*/
static void
{
switch (kssl_cmd) {
case KSSL_CMD_SEND: {
break;
}
/* FALLTHROUGH */
case KSSL_CMD_NONE:
break;
case KSSL_CMD_DELIVER_PROXY:
case KSSL_CMD_DELIVER_SSL:
&flowctrld);
break;
case KSSL_CMD_NOT_SUPPORTED:
/* Stop the SSL processing */
}
/*
* Process any input that may have accumulated while we're waiting for
* the call-back. This must be done by a taskq because kssl_input might
* block when handling client_finish messages.
*/
TQ_NOSLEEP) == NULL) {
}
}
};
int
_init(void)
{
int error;
&ksslf_ops, 0)) != 0)
return (error);
(void) sof_unregister(KSSL_FILNAME);
return (error);
}
int
_fini(void)
{
int error;
return (error);
return (mod_remove(&ksslf_modlinkage));
}
int
{
}