summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg.c1
-rw-r--r--usr/src/uts/common/inet/kssl/ksslapi.c67
-rw-r--r--usr/src/uts/common/inet/kssl/ksslfilter.c37
-rw-r--r--usr/src/uts/common/inet/kssl/ksslproto.h4
-rw-r--r--usr/src/uts/common/inet/kssl/ksslrec.c10
5 files changed, 101 insertions, 18 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg.c b/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg.c
index a8ab53d02b..1fb7788eff 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg.c
@@ -202,6 +202,7 @@ create_instance_name(const char *arg, char **inaddr_any_name,
if ((*inaddr_any_name = malloc(len)) == NULL) {
(void) fprintf(stderr,
gettext("Error: memory allocation failure.\n"));
+ free(instance_name);
free(cname);
return (NULL);
}
diff --git a/usr/src/uts/common/inet/kssl/ksslapi.c b/usr/src/uts/common/inet/kssl/ksslapi.c
index 57d6970a9b..9110c959b5 100644
--- a/usr/src/uts/common/inet/kssl/ksslapi.c
+++ b/usr/src/uts/common/inet/kssl/ksslapi.c
@@ -345,7 +345,7 @@ kssl_input(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp, boolean_t *more,
mutex_enter(&ssl->kssl_lock);
- if (ssl->close_notify == B_TRUE) {
+ if (ssl->close_notify_clnt == B_TRUE) {
DTRACE_PROBE(kssl_err__close_notify);
goto sendnewalert;
}
@@ -1052,7 +1052,7 @@ kssl_handle_any_record(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp,
error = EBADMSG;
goto error;
} else {
- ssl->close_notify = B_TRUE;
+ ssl->close_notify_clnt = B_TRUE;
ssl->activeinput = B_FALSE;
freeb(mp);
return (KSSL_CMD_NONE);
@@ -1187,7 +1187,31 @@ kssl_build_record(kssl_ctx_t ctx, mblk_t *mp)
mblk_t *retmp = mp, *bp = mp, *prevbp = mp, *copybp;
ASSERT(ssl != NULL);
+
+ /*
+ * Produce new close_notify message. This is necessary to perform
+ * proper cleanup w.r.t. SSL protocol spec by sending close_notify SSL
+ * alert record if running with KSSL proxy.
+ * This should be done prior to sending the FIN so the client side can
+ * attempt to do graceful cleanup. Ideally, we should wait for client's
+ * close_notify but not all clients send it which would hang the
+ * connection. This way of closing the SSL session (Incomplete Close)
+ * prevents truncation attacks for protocols without end-of-data
+ * markers (as opposed to the Premature Close).
+ * Checking the close_notify_srvr flag will prevent from sending the
+ * close_notify message twice in case of duplicate shutdown() calls.
+ */
+ if (mp == NULL && !ssl->close_notify_srvr) {
+ kssl_send_alert(ssl, alert_warning, close_notify);
+ if (ssl->alert_sendbuf == NULL)
+ return (NULL);
+ mp = bp = retmp = prevbp = ssl->alert_sendbuf;
+ ssl->alert_sendbuf = NULL;
+ ssl->close_notify_srvr = B_TRUE;
+ }
+
ASSERT(mp != NULL);
+ ASSERT(bp != NULL);
do {
if (DB_REF(bp) > 1) {
@@ -1220,8 +1244,14 @@ kssl_build_record(kssl_ctx_t ctx, mblk_t *mp)
}
/*
- * Builds a single SSL record.
- * In-line encryption of the record.
+ * Builds a single SSL record by prepending SSL header (optional) and performing
+ * encryption and MAC. The encryption of the record is done in-line.
+ * Expects an mblk with associated dblk's base to have space for the SSL header
+ * or an mblk which already has the header present. In both cases it presumes
+ * that the mblk's dblk limit has space for the MAC + padding.
+ * If the close_notify_srvr flag is set it is presumed that the mblk already
+ * contains SSL header in which case only the record length field will be
+ * adjusted with the MAC/padding size.
*/
static kssl_status_t
kssl_build_single_record(ssl_t *ssl, mblk_t *mp)
@@ -1237,19 +1267,28 @@ kssl_build_single_record(ssl_t *ssl, mblk_t *mp)
mac_sz = spec->mac_hashsz;
ASSERT(DB_REF(mp) == 1);
- ASSERT((mp->b_rptr - mp->b_datap->db_base >= SSL3_HDR_LEN) &&
- (mp->b_datap->db_lim - mp->b_wptr >= mac_sz + spec->cipher_bsize));
+ /* The dblk must always have space for the padding and MAC suffix. */
+ ASSERT(mp->b_datap->db_lim - mp->b_wptr >= mac_sz + spec->cipher_bsize);
- len = MBLKL(mp);
+ /* kssl_send_alert() constructs the SSL header by itself. */
+ if (!ssl->close_notify_srvr)
+ len = MBLKL(mp) - SSL3_HDR_LEN;
+ else
+ len = MBLKL(mp);
ASSERT(len > 0);
mutex_enter(&ssl->kssl_lock);
- recstart = mp->b_rptr = mp->b_rptr - SSL3_HDR_LEN;
- recstart[0] = content_application_data;
- recstart[1] = ssl->major_version;
- recstart[2] = ssl->minor_version;
+ recstart = mp->b_rptr;
+ if (!ssl->close_notify_srvr) {
+ /* The dblk must have space for the SSL header prefix. */
+ ASSERT(mp->b_rptr - mp->b_datap->db_base >= SSL3_HDR_LEN);
+ recstart = mp->b_rptr = mp->b_rptr - SSL3_HDR_LEN;
+ recstart[0] = content_application_data;
+ recstart[1] = ssl->major_version;
+ recstart[2] = ssl->minor_version;
+ }
versionp = &recstart[1];
reclen = len + mac_sz;
@@ -1263,14 +1302,16 @@ kssl_build_single_record(ssl_t *ssl, mblk_t *mp)
recstart[3] = (reclen >> 8) & 0xff;
recstart[4] = reclen & 0xff;
- if (kssl_mac_encrypt_record(ssl, content_application_data, versionp,
+ if (kssl_mac_encrypt_record(ssl, recstart[0], versionp,
recstart, mp) != 0) {
/* Do we need an internal_error Alert here? */
mutex_exit(&ssl->kssl_lock);
return (KSSL_STS_ERR);
}
- KSSL_COUNTER(appdata_record_outs, 1);
+ /* Alert messages are accounted in kssl_send_alert(). */
+ if (recstart[0] == content_application_data)
+ KSSL_COUNTER(appdata_record_outs, 1);
mutex_exit(&ssl->kssl_lock);
return (KSSL_STS_OK);
}
diff --git a/usr/src/uts/common/inet/kssl/ksslfilter.c b/usr/src/uts/common/inet/kssl/ksslfilter.c
index 7e35a90066..208fa3e0aa 100644
--- a/usr/src/uts/common/inet/kssl/ksslfilter.c
+++ b/usr/src/uts/common/inet/kssl/ksslfilter.c
@@ -306,6 +306,42 @@ kssl_data_out_cb(sof_handle_t handle, void *cookie, mblk_t *mp,
}
/*
+ * Called from shutdown() processing. This will produce close_notify message
+ * to indicate the end of data to the client.
+ */
+sof_rval_t
+kssl_shutdown_cb(sof_handle_t handle, void *cookie, int *howp, cred_t *cr)
+{
+ ksslf_t *kssl = (ksslf_t *)cookie;
+ kssl_ctx_t kssl_ctx = kssl->ksslf_ctx;
+ mblk_t *outmp;
+ boolean_t flowctrld;
+ struct nmsghdr msg;
+
+ _NOTE(ARGUNUSED(cr));
+
+ if (kssl_ctx == NULL)
+ return (SOF_RVAL_EINVAL);
+
+ /*
+ * We only want to send close_notify when doing SHUT_WR/SHUT_RDWR
+ * because it signals that server is done writing data.
+ */
+ if (*howp == SHUT_RD)
+ return (SOF_RVAL_CONTINUE);
+
+ /* Go on if we fail to build the record. */
+ if ((outmp = kssl_build_record(kssl_ctx, NULL)) == NULL)
+ return (SOF_RVAL_CONTINUE);
+
+ bzero(&msg, sizeof (msg));
+ (void) sof_inject_data_out(handle, outmp, &msg,
+ &flowctrld);
+
+ return (SOF_RVAL_CONTINUE);
+}
+
+/*
* Called for each incoming segment.
*
* A packet may carry multiple SSL records, so the function calls
@@ -544,6 +580,7 @@ sof_ops_t ksslf_ops = {
.sofop_data_out = kssl_data_out_cb,
.sofop_mblk_prop = kssl_mblk_prop_cb,
.sofop_getsockname = kssl_getsockname_cb,
+ .sofop_shutdown = kssl_shutdown_cb,
};
int
diff --git a/usr/src/uts/common/inet/kssl/ksslproto.h b/usr/src/uts/common/inet/kssl/ksslproto.h
index 35e01f2872..c982fe9dfd 100644
--- a/usr/src/uts/common/inet/kssl/ksslproto.h
+++ b/usr/src/uts/common/inet/kssl/ksslproto.h
@@ -42,6 +42,7 @@ extern "C" {
#define SSL3_RANDOM_LENGTH 32
#define SSL3_SESSIONID_BYTES 32
#define SSL3_HDR_LEN 5
+#define SSL3_ALERT_LEN 2
#define SSL3_MAX_RECORD_LENGTH 16384
#define SSL3_PRE_MASTER_SECRET_LEN 48
#define SSL3_MASTER_SECRET_LEN 48
@@ -286,7 +287,8 @@ typedef struct ssl_s {
uint32_t tcp_mss;
SSL3WaitState hs_waitstate;
boolean_t resumed;
- boolean_t close_notify;
+ boolean_t close_notify_clnt;
+ boolean_t close_notify_srvr;
boolean_t fatal_alert;
boolean_t fatal_error;
boolean_t alert_sent;
diff --git a/usr/src/uts/common/inet/kssl/ksslrec.c b/usr/src/uts/common/inet/kssl/ksslrec.c
index 4ae26e5cb1..f6de3fbb82 100644
--- a/usr/src/uts/common/inet/kssl/ksslrec.c
+++ b/usr/src/uts/common/inet/kssl/ksslrec.c
@@ -1796,10 +1796,12 @@ kssl_send_alert(ssl_t *ssl, SSL3AlertLevel level, SSL3AlertDescription desc)
spec = &ssl->spec[KSSL_WRITE];
ASSERT(ssl->alert_sendbuf == NULL);
- if (ssl->major_version == 0x03)
- len = 7;
- else
+ if (ssl->major_version == 0x03) {
+ len = SSL3_HDR_LEN + SSL3_ALERT_LEN;
+ } else {
+ /* KSSL generates 5 byte SSLv2 alert messages only. */
len = 5;
+ }
ssl->alert_sendbuf = mp = allocb(len + spec->mac_hashsz +
spec->cipher_bsize, BPRI_HI);
if (mp == NULL) {
@@ -1821,7 +1823,7 @@ kssl_send_alert(ssl_t *ssl, SSL3AlertLevel level, SSL3AlertDescription desc)
/* alert contents */
buf[0] = (uchar_t)level;
buf[1] = (uchar_t)desc;
- buf += 2;
+ buf += SSL3_ALERT_LEN;
} else {
/* SSLv2 has different encoding. */
/* 2-byte encoding of the length */