usr/src/uts/common/fs/sockfs/socktpi.c
changeset 898 64b2a371a6bd
parent 741 40027a3621ac
child 1092 11ac87ff53c2
--- a/usr/src/uts/common/fs/sockfs/socktpi.c	Sat Nov 12 07:57:48 2005 -0800
+++ b/usr/src/uts/common/fs/sockfs/socktpi.c	Sat Nov 12 18:58:05 2005 -0800
@@ -78,6 +78,8 @@
 #include <fs/sockfs/nl7c.h>
 #include <sys/zone.h>
 
+#include <inet/kssl/ksslapi.h>
+
 /*
  * Possible failures when memory can't be allocated. The documented behavior:
  *
@@ -174,6 +176,12 @@
 extern	void *nl7c_add_addr(void *, t_uscalar_t);
 extern	void nl7c_listener_addr(void *, queue_t *);
 
+/* Sockets acting as an in-kernel SSL proxy */
+extern mblk_t	*strsock_kssl_input(vnode_t *, mblk_t *, strwakeup_t *,
+		    strsigset_t *, strsigset_t *, strpollset_t *);
+extern mblk_t	*strsock_kssl_output(vnode_t *, mblk_t *, strwakeup_t *,
+		    strsigset_t *, strsigset_t *, strpollset_t *);
+
 static int	sotpi_unbind(struct sonode *, int);
 
 /* TPI sockfs sonode operations */
@@ -289,6 +297,12 @@
 		version = so_default_version;
 
 	so->so_version = (short)version;
+
+	/* Initialize the kernel SSL proxy fields */
+	so->so_kssl_type = KSSL_NO_PROXY;
+	so->so_kssl_ent = NULL;
+	so->so_kssl_ctx = NULL;
+
 	return (so);
 }
 
@@ -773,9 +787,37 @@
 	mp = soallocproto2(&bind_req, sizeof (bind_req),
 				addr, addrlen, 0, _ALLOC_SLEEP);
 	so->so_state &= ~SS_LADDR_VALID;
+
 	/* Done using so_laddr_sa - can drop the lock */
 	mutex_exit(&so->so_lock);
 
+	/*
+	 * Intercept the bind_req message here to check if this <address/port>
+	 * was configured as an SSL proxy server, or if another endpoint was
+	 * already configured to act as a proxy for us.
+	 */
+	if ((so->so_family == AF_INET || so->so_family == AF_INET6) &&
+	    so->so_type == SOCK_STREAM) {
+
+		if (so->so_kssl_ent != NULL) {
+			kssl_release_ent(so->so_kssl_ent, so, so->so_kssl_type);
+			so->so_kssl_ent = NULL;
+		}
+
+		so->so_kssl_type = kssl_check_proxy(mp, so, &so->so_kssl_ent);
+		switch (so->so_kssl_type) {
+		case KSSL_NO_PROXY:
+			break;
+
+		case KSSL_HAS_PROXY:
+			mutex_enter(&so->so_lock);
+			goto skip_transport;
+
+		case KSSL_IS_PROXY:
+			break;
+		}
+	}
+
 	error = kstrputmsg(SOTOV(so), mp, NULL, 0, 0,
 			MSG_BAND|MSG_HOLDSIG|MSG_IGNERROR, 0);
 	if (error) {
@@ -791,6 +833,7 @@
 		eprintsoline(so, error);
 		goto done;
 	}
+skip_transport:
 	ASSERT(mp);
 	/*
 	 * Even if some TPI message (e.g. T_DISCON_IND) was received in
@@ -1155,7 +1198,18 @@
 		vnode_t *vp;
 
 		if ((vp = so->so_ux_bound_vp) != NULL) {
-			ASSERT(vp->v_stream);
+
+			/* Undo any SSL proxy setup */
+			if ((so->so_family == AF_INET ||
+			    so->so_family == AF_INET6) &&
+			    (so->so_type == SOCK_STREAM) &&
+			    (so->so_kssl_ent != NULL)) {
+				kssl_release_ent(so->so_kssl_ent, so,
+				    so->so_kssl_type);
+				so->so_kssl_ent = NULL;
+				so->so_kssl_type = KSSL_NO_PROXY;
+			}
+
 			so->so_ux_bound_vp = NULL;
 			vn_rele_stream(vp);
 		}
@@ -1164,6 +1218,7 @@
 	}
 	so->so_state &= ~(SS_ISBOUND|SS_ACCEPTCONN|SS_LADDR_VALID);
 done:
+
 	/* If the caller held the lock don't release it here */
 	ASSERT(MUTEX_HELD(&so->so_lock));
 	ASSERT(so->so_flag & SOLOCKED);
@@ -1356,7 +1411,7 @@
 	struct T_conn_ind	*conn_ind;
 	struct T_conn_res	*conn_res;
 	int			error = 0;
-	mblk_t			*mp;
+	mblk_t			*mp, *ctxmp;
 	struct sonode		*nso;
 	vnode_t			*nvp;
 	void			*src;
@@ -1384,6 +1439,8 @@
 
 	ASSERT(mp);
 	conn_ind = (struct T_conn_ind *)mp->b_rptr;
+	ctxmp = mp->b_cont;
+
 	/*
 	 * Save SEQ_number for error paths.
 	 */
@@ -1476,6 +1533,23 @@
 	}
 	nvp = SOTOV(nso);
 
+	/*
+	 * If the transport sent up an SSL connection context, then attach
+	 * it the new socket, and set the (sd_wputdatafunc)() and
+	 * (sd_rputdatafunc)() stream head hooks to intercept and process
+	 * SSL records.
+	 */
+	if (ctxmp != NULL) {
+		/*
+		 * This kssl_ctx_t is already held for us by the transport.
+		 * So, we don't need to do a kssl_hold_ctx() here.
+		 */
+		nso->so_kssl_ctx = *((kssl_ctx_t *)ctxmp->b_rptr);
+		freemsg(ctxmp);
+		mp->b_cont = NULL;
+		strsetrwputdatahooks(nvp, strsock_kssl_input,
+		    strsock_kssl_output);
+	}
 #ifdef DEBUG
 	/*
 	 * SO_DEBUG is used to trigger the dprint* and eprint* macros thus
@@ -4288,6 +4362,7 @@
 	struct stdata *stp = SOTOV(so)->v_stream;
 	ssize_t iosize, rmax, maxblk;
 	queue_t *tcp_wq = stp->sd_wrq->q_next;
+	mblk_t *newmp;
 	int error = 0, wflag = 0;
 
 	ASSERT(so->so_mode & SM_BYTESTREAM);
@@ -4305,6 +4380,15 @@
 		 * data to tcp.
 		 */
 		ASSERT(mp != NULL);
+		if (stp->sd_wputdatafunc != NULL) {
+			newmp = (stp->sd_wputdatafunc)(SOTOV(so), mp, NULL,
+			    NULL, NULL, NULL);
+			if (newmp == NULL) {
+				/* The caller will free mp */
+				return (ECOMM);
+			}
+			mp = newmp;
+		}
 		tcp_wput(tcp_wq, mp);
 		return (0);
 	}
@@ -4347,6 +4431,15 @@
 		 * to tcp and let the rest be handled in strwrite().
 		 */
 		ASSERT(error == 0 || error == ENOMEM);
+		if (stp->sd_wputdatafunc != NULL) {
+			newmp = (stp->sd_wputdatafunc)(SOTOV(so), mp, NULL,
+			    NULL, NULL, NULL);
+			if (newmp == NULL) {
+				/* The caller will free mp */
+				return (ECOMM);
+			}
+			mp = newmp;
+		}
 		tcp_wput(tcp_wq, mp);
 
 		wflag |= NOINTR;