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