summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2017-05-27 08:33:26 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2017-05-27 08:33:26 +0000
commit460b984bd245edf6c33f3e2a4f4c1f75cde903d3 (patch)
tree344c5c23e40425bf4eff1021ea92cf67231e6a51 /usr.sbin/relayd
parent1b5fd98198f2adb6d2d152c115dca82f396d1c11 (diff)
Migrate relayd to use libtls for TLS. Still does the TLS privsep via the
engine but at least we can use a sane API for new features. Going in now so it is possible to work with this in tree. General agreement at d2k17.
Diffstat (limited to 'usr.sbin/relayd')
-rw-r--r--usr.sbin/relayd/Makefile8
-rw-r--r--usr.sbin/relayd/boguskeys.h200
-rw-r--r--usr.sbin/relayd/ca.c88
-rw-r--r--usr.sbin/relayd/check_tcp.c4
-rw-r--r--usr.sbin/relayd/check_tls.c226
-rw-r--r--usr.sbin/relayd/config.c12
-rw-r--r--usr.sbin/relayd/hce.c8
-rw-r--r--usr.sbin/relayd/parse.y100
-rw-r--r--usr.sbin/relayd/relay.c813
-rw-r--r--usr.sbin/relayd/relay_http.c7
-rw-r--r--usr.sbin/relayd/relayd.c39
-rw-r--r--usr.sbin/relayd/relayd.h72
-rw-r--r--usr.sbin/relayd/ssl.c413
13 files changed, 1094 insertions, 896 deletions
diff --git a/usr.sbin/relayd/Makefile b/usr.sbin/relayd/Makefile
index b61a0e5f45f..ee84780d4f6 100644
--- a/usr.sbin/relayd/Makefile
+++ b/usr.sbin/relayd/Makefile
@@ -1,15 +1,15 @@
-# $OpenBSD: Makefile,v 1.30 2016/09/28 15:03:03 reyk Exp $
+# $OpenBSD: Makefile,v 1.31 2017/05/27 08:33:25 claudio Exp $
PROG= relayd
SRCS= parse.y
SRCS+= agentx.c ca.c carp.c check_icmp.c check_script.c \
- check_tcp.c config.c control.c hce.c log.c name2id.c \
- pfe.c pfe_filter.c pfe_route.c proc.c \
+ check_tcp.c check_tls.c config.c control.c hce.c log.c \
+ name2id.c pfe.c pfe_filter.c pfe_route.c proc.c \
relay.c relay_http.c relay_udp.c relayd.c \
shuffle.c snmp.c ssl.c util.c
MAN= relayd.8 relayd.conf.5
-LDADD= -levent -lssl -lcrypto -lutil
+LDADD= -levent -ltls -lssl -lcrypto -lutil
DPADD= ${LIBEVENT} ${LIBSSL} ${LIBCRYPTO} ${LIBUTIL}
CFLAGS+= -Wall -I${.CURDIR} -I${.CURDIR}/../snmpd
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
diff --git a/usr.sbin/relayd/boguskeys.h b/usr.sbin/relayd/boguskeys.h
new file mode 100644
index 00000000000..2e407312e85
--- /dev/null
+++ b/usr.sbin/relayd/boguskeys.h
@@ -0,0 +1,200 @@
+/* $OpenBSD: boguskeys.h,v 1.1 2017/05/27 08:33:25 claudio Exp $ */
+
+/*
+ * Placed in the public domain by Claudio Jeker <claudio@openbsd.org>
+ * on March 26, 2017.
+ */
+
+/* Bogus private key since the private key is privseped away */
+const char bogus_1024[] = "-----BEGIN RSA PRIVATE KEY-----\n"
+ "MIICXQIBAAKBgQDXEA8QOA7tgvV0UN50pAf34b0vKD95svTuFNuCn7esdTUly/hF\n"
+ "wDckkEznfbGj6o1otpMVaPNwRhhwikF7x9IWPjXw7sfbgvQoa2gkMUMkUr/X49KA\n"
+ "7Uu0xqOaKn/IM4yA/ZaTuL99zdn8EBCRyrDVF8iDnVTPMrsLTyg2bE1qhwIDAQAB\n"
+ "AoGAHvv/T5TkAbAWcPWdtyxSwZHSUdL4oi34P7zdi0o7iiswxwtF77aruybXDZr8\n"
+ "VuNaEDYNps4CFLDkoIIqwQye5bWktBLL9Bv0ZDmR8u1PkQPjwRblg7jPtk46aiWQ\n"
+ "9NEVkr2V1GUrzAPDcC23R5PKx//PveTiwrfmo6j+sWkxTxECQQD+9LevrDATY1nt\n"
+ "Ce9R1KnduwueeDRRByS+8or8dyGXUR1wZjm2M4pBpigTfPQiSA9O6nixV3xpwNUN\n"
+ "G9XpWGO1AkEA1/GE9ZPBWHOut+WYSerq76gZeIaH3tF3FnnLBLzw8+ePf0qm0h4q\n"
+ "i2dl/EQV9LH7q0Rf7k2yXgHeo5dK4OkyywJBAM49+kWSvcVBTmJw8fa5WLw0bf7A\n"
+ "cFnHtJL+sy3t1O+KP41INJFOeh4HIk45e2gr8K4/AGk9QzhtNCuJg+5igS0CQQDM\n"
+ "AyW2TW2w/znmC0ehLgvfd1T5BUCARizYUyB2zXpnNDHh9Mk+YbmYEovLlReZIj2+\n"
+ "RM7M+SK2pdWNgHYBns+ZAkAT7fZsAeOxNjM7h2kA0AriUvc2IuDqVGiFKAFCVacF\n"
+ "mSQSIplSJU117YTqbVGf++SEj/WFYOTS8G+jjBuMr1d9\n"
+ "-----END RSA PRIVATE KEY-----\n";
+const char bogus_2048[] = "-----BEGIN RSA PRIVATE KEY-----\n"
+ "MIIEpAIBAAKCAQEA2qsShCATc5n25suEmB+1zaxbrVbSqaEWZ+qizKTLlybJ0TOD\n"
+ "Nl/6lo9hIZ+gTqf0GwJRTUwtkjlovrn5p8IWtZUceG0S+ijh7DybzGCVlOFN0JRx\n"
+ "z+zTr9eNPkvrJLwYavSzV4BpjelBKManE8sHA6pqXCDi5PfJ0iKfWtHQk2S5ukWA\n"
+ "WE33ANLQVW0ATPvtNpHSacNIzWEW7h/66sPJu+iNcekx/Q+1kI+0Msf7m1HFN464\n"
+ "eRrm3kqncPsJ6o3Kbu2aoJFk7oO6+HfSyXmxLywuUgyPnqW6zN8pj7jaq33fmHzo\n"
+ "3s95Nbk/cYOtYHPzaT5eQWXy120aZ/scuY1laQIDAQABAoIBAClEP6pPo1wdokrL\n"
+ "/an30geOj36W9AqvK9tQnIiiUQmleFDSt+B7HH9tb5c42Lf/WkH+nflIdxExZGMa\n"
+ "FdNi/YYnLchMTViIfppmlcBsOc5u9pB2c0QaHZkBxNYM3cOA+9qzc2UABuuRKYrY\n"
+ "co95sUkv0AKy8h7j5GKTxh8NmZ82+YRkkkMkk7bvXhGppR+jiqeQ4KsZbYWFPAG9\n"
+ "WJA+sFVn8WS0oMePfqmeIPY+BiddU0ITn02Hafn9jBhhXI5LKbiiwC8sFDICxPSm\n"
+ "moDpmexe1s7jNuSxueEM5XPQP7v2QmnH9KDxDcPEC5Lz8qFa6wkiLBpQ9CRmPlDV\n"
+ "pEfF8kECgYEA/5jiItxbt+kEDMm6GuAGy02Zq/9Eb3u1J7szjvvGrL6L0S5FcDic\n"
+ "S8M5A5hTvbxQfohr6AEzqog5IQ2EiyxghIfYOs5E+rYVnN4py1ErzR3LoC45bIiO\n"
+ "tRbgYGMqFzD+uGaePpCwz/Ptn9KqCoH4hhfCJPMgOSNUvh8EAJfh7HcCgYEA2wNK\n"
+ "Y53qfMjsd1qGYMM3J6QtTJWrteejSspouyKAlCD1RHKKzhmOxa5GPkG4NSYi1hij\n"
+ "nRywxGvFOm0eoYYMUhPdjdC4Txp646l3HNdEZMWv+NN47+vaHX+KvTyq1xis46JB\n"
+ "Y5SK+57RmS7sEQqUVwuqJiuPR1YoM2daBqiUFR8CgYEAymyLE67PGLz7TyFoOaaY\n"
+ "2uQPQ098JIqlstyofaHa+65Azx7FMZYz+jCXc8hs8cQ1P7DNPMXO5EzUad/py8sO\n"
+ "eYeYcSIxMRmJzl2IXhRgCyeAv9A7/D++PZ7rfoqqqAlOgj4LL2OqFFeMJtpRftbm\n"
+ "O1SPlnHSYE4h7BxmMA4ZiAsCgYAeG0Cxmvat+qzO52nLiWpej6oOehClq9b9o/9r\n"
+ "oh2Mv08X/qroFAlVUVSkoEIjRD/LsI1lPplqFuqA0plAWP3+lm6BXSzI6vnzq8sM\n"
+ "8uaa97Xt/ZwFVyWfonW+98UAVosFq7tTZgsI9dcYOKQI36xuntLf9mL2yngyQMXW\n"
+ "XnwkvwKBgQCCoZxoF0o6QWbEowJf/BrozjYa2D0tVokxRr7kfVXt9TTQez5LQ1u4\n"
+ "/w6oCEKldPe/6tzO12i9BITmAmoZzswO/ms7J3cRnvoLWM1tPHh3zrGZgIaMdTyv\n"
+ "n0QebhOEKeXrhwZVmyhBFgI/4bTZJWByAnr6p3jLywK2NdxJIXZ5cg==\n"
+ "-----END RSA PRIVATE KEY-----\n";
+const char bogus_4096[] = "-----BEGIN RSA PRIVATE KEY-----\n"
+ "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\n"
+ "-----END RSA PRIVATE KEY-----\n";
+const char bogus_8192[] = "-----BEGIN RSA PRIVATE KEY-----\n"
+ "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\n"
+ "-----END RSA PRIVATE KEY-----\n";
diff --git a/usr.sbin/relayd/ca.c b/usr.sbin/relayd/ca.c
index 45bd5f3224b..f5cc3be8957 100644
--- a/usr.sbin/relayd/ca.c
+++ b/usr.sbin/relayd/ca.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ca.c,v 1.24 2017/04/06 12:20:48 gsoares Exp $ */
+/* $OpenBSD: ca.c,v 1.25 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
@@ -82,17 +82,57 @@ ca_init(struct privsep *ps, struct privsep_proc *p, void *arg)
env->sc_id = getpid() & 0xffff;
}
+static void
+hash_string(char *d, size_t dlen, char *hash, size_t hashlen)
+{
+ static const char hex[] = "0123456789abcdef";
+ size_t off, i;
+
+ if (hashlen < 2 * dlen + sizeof("SHA256:"))
+ fatalx("%s hash buffer to small", __func__);
+
+ off = strlcpy(hash, "SHA256:", hashlen);
+
+ for (i = 0; i < dlen; i++) {
+ hash[off++] = hex[(d[i] >> 4) & 0x0f];
+ hash[off++] = hex[d[i] & 0x0f];
+ }
+ hash[off] = 0;
+}
+
void
ca_launch(void)
{
+ char d[EVP_MAX_MD_SIZE], hash[TLS_CERT_HASH_SIZE];
BIO *in = NULL;
EVP_PKEY *pkey = NULL;
struct relay *rlay;
+ X509 *cert = NULL;
+ int dlen;
TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) == 0)
continue;
+ if (rlay->rl_conf.tls_cert_len) {
+ if ((in = BIO_new_mem_buf(rlay->rl_tls_cert,
+ rlay->rl_conf.tls_cert_len)) == NULL)
+ fatalx("ca_launch: cert");
+
+ if ((cert = PEM_read_bio_X509(in, NULL,
+ NULL, NULL)) == NULL)
+ fatalx("ca_launch: cert");
+
+ if (X509_digest(cert, EVP_sha256(), d, &dlen) != 1)
+ fatalx("ca_launch: cert");
+
+ hash_string(d, dlen, hash, sizeof(hash));
+
+ BIO_free(in);
+ X509_free(cert);
+ purge_key(&rlay->rl_tls_cert,
+ rlay->rl_conf.tls_cert_len);
+ }
if (rlay->rl_conf.tls_key_len) {
if ((in = BIO_new_mem_buf(rlay->rl_tls_key,
rlay->rl_conf.tls_key_len)) == NULL)
@@ -105,16 +145,31 @@ ca_launch(void)
rlay->rl_tls_pkey = pkey;
- if (pkey_add(env, pkey,
- rlay->rl_conf.tls_keyid) == NULL)
+ if (pkey_add(env, pkey, hash) == NULL)
fatalx("tls pkey");
purge_key(&rlay->rl_tls_key,
rlay->rl_conf.tls_key_len);
}
- if (rlay->rl_conf.tls_cert_len) {
- purge_key(&rlay->rl_tls_cert,
- rlay->rl_conf.tls_cert_len);
+
+ if (rlay->rl_conf.tls_cacert_len) {
+ if ((in = BIO_new_mem_buf(rlay->rl_tls_cacert,
+ rlay->rl_conf.tls_cacert_len)) == NULL)
+ fatalx("ca_launch: cacert");
+
+ if ((cert = PEM_read_bio_X509(in, NULL,
+ NULL, NULL)) == NULL)
+ fatalx("ca_launch: cacert");
+
+ if (X509_digest(cert, EVP_sha256(), d, &dlen) != 1)
+ fatalx("ca_launch: cacert");
+
+ hash_string(d, dlen, hash, sizeof(hash));
+
+ BIO_free(in);
+ X509_free(cert);
+ purge_key(&rlay->rl_tls_cacert,
+ rlay->rl_conf.tls_cacert_len);
}
if (rlay->rl_conf.tls_cakey_len) {
if ((in = BIO_new_mem_buf(rlay->rl_tls_cakey,
@@ -128,17 +183,12 @@ ca_launch(void)
rlay->rl_tls_capkey = pkey;
- if (pkey_add(env, pkey,
- rlay->rl_conf.tls_cakeyid) == NULL)
+ if (pkey_add(env, pkey, hash) == NULL)
fatalx("ca pkey");
purge_key(&rlay->rl_tls_cakey,
rlay->rl_conf.tls_cakey_len);
}
- if (rlay->rl_conf.tls_cacert_len) {
- purge_key(&rlay->rl_tls_cacert,
- rlay->rl_conf.tls_cacert_len);
- }
}
}
@@ -186,12 +236,13 @@ ca_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
if (IMSG_DATA_SIZE(imsg) != (sizeof(cko) + cko.cko_flen))
fatalx("ca_dispatch_relay: "
"invalid key operation");
- if ((pkey = pkey_find(env, cko.cko_id)) == NULL ||
+ if ((pkey = pkey_find(env, cko.cko_hash)) == NULL ||
(rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
fatalx("ca_dispatch_relay: "
"invalid relay key or id");
- DPRINTF("%s:%d: key id %d", __func__, __LINE__, cko.cko_id);
+ DPRINTF("%s:%d: key hash %s proc %d",
+ __func__, __LINE__, cko.cko_hash, cko.cko_proc);
from = (u_char *)imsg->data + sizeof(cko);
if ((to = calloc(1, cko.cko_tlen)) == NULL)
@@ -259,7 +310,7 @@ rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa,
struct pollfd pfd[1];
struct ctl_keyop cko;
int ret = 0;
- objid_t *id;
+ char *hash;
struct iovec iov[2];
struct imsgbuf *ibuf;
struct imsgev *iev;
@@ -267,7 +318,7 @@ rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa,
int n, done = 0, cnt = 0;
u_char *toptr;
- if ((id = RSA_get_ex_data(rsa, 0)) == NULL)
+ if ((hash = RSA_get_ex_data(rsa, 0)) == NULL)
return (0);
iev = proc_iev(ps, PROC_CA, ps->ps_instance);
@@ -277,7 +328,7 @@ rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa,
* XXX this could be nicer...
*/
- cko.cko_id = *id;
+ (void)strlcpy(cko.cko_hash, hash, sizeof(cko.cko_hash));
cko.cko_proc = ps->ps_instance;
cko.cko_flen = flen;
cko.cko_tlen = RSA_size(rsa);
@@ -490,6 +541,5 @@ ca_engine_init(struct relayd *x_env)
return;
fail:
- ssl_error(__func__, errstr);
- fatalx("%s", errstr);
+ fatalx("%s: %s", __func__, errstr);
}
diff --git a/usr.sbin/relayd/check_tcp.c b/usr.sbin/relayd/check_tcp.c
index bbf3258f70c..cf3a97c3f23 100644
--- a/usr.sbin/relayd/check_tcp.c
+++ b/usr.sbin/relayd/check_tcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_tcp.c,v 1.52 2017/02/09 11:16:22 reyk Exp $ */
+/* $OpenBSD: check_tcp.c,v 1.53 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -170,7 +170,7 @@ tcp_host_up(struct ctl_tcp_event *cte)
}
if (cte->table->conf.flags & F_TLS) {
- ssl_transaction(cte);
+ check_tls(cte);
return;
}
diff --git a/usr.sbin/relayd/check_tls.c b/usr.sbin/relayd/check_tls.c
new file mode 100644
index 00000000000..eb453507c82
--- /dev/null
+++ b/usr.sbin/relayd/check_tls.c
@@ -0,0 +1,226 @@
+/* $OpenBSD: check_tls.c,v 1.1 2017/05/27 08:33:25 claudio Exp $ */
+
+/*
+ * Copyright (c) 2017 Claudio Jeker <claudio@openbsd.org>
+ * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+
+#include <limits.h>
+#include <event.h>
+#include <unistd.h>
+#include <string.h>
+#include <imsg.h>
+
+#include "relayd.h"
+
+void check_tls_read(int, short, void *);
+void check_tls_write(int, short, void *);
+void check_tls_handshake(int, short, void *);
+void check_tls_cleanup(struct ctl_tcp_event *);
+void check_tls_error(struct ctl_tcp_event *, const char *, const char *);
+
+void
+check_tls_read(int s, short event, void *arg)
+{
+ char rbuf[SMALL_READ_BUF_SIZE];
+ struct ctl_tcp_event *cte = arg;
+ int retry_flag = EV_READ;
+ int ret;
+
+ if (event == EV_TIMEOUT) {
+ cte->host->up = HOST_DOWN;
+ check_tls_cleanup(cte);
+ hce_notify_done(cte->host, HCE_TLS_READ_TIMEOUT);
+ return;
+ }
+
+ bzero(rbuf, sizeof(rbuf));
+
+ ret = tls_read(cte->tls, rbuf, sizeof(rbuf));
+ if (ret > 0) {
+ if (ibuf_add(cte->buf, rbuf, ret) == -1)
+ fatal("check_tls_read: buf_add error");
+ if (cte->validate_read != NULL &&
+ cte->validate_read(cte) == 0) {
+ check_tls_cleanup(cte);
+ hce_notify_done(cte->host, cte->host->he);
+ return;
+ }
+ } else if (ret == 0) {
+ cte->host->up = HOST_DOWN;
+ (void)cte->validate_close(cte);
+ check_tls_cleanup(cte);
+ hce_notify_done(cte->host, cte->host->he);
+ return;
+ } else if (ret == TLS_WANT_POLLIN) {
+ retry_flag = EV_READ;
+ } else if (ret == TLS_WANT_POLLOUT) {
+ retry_flag = EV_WRITE;
+ } else {
+ cte->host->up = HOST_DOWN;
+ check_tls_error(cte, cte->host->conf.name, "cannot read");
+ check_tls_cleanup(cte);
+ hce_notify_done(cte->host, HCE_TLS_READ_ERROR);
+ return;
+ }
+
+ event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, check_tls_read,
+ &cte->tv_start, &cte->table->conf.timeout, cte);
+ return;
+}
+
+void
+check_tls_write(int s, short event, void *arg)
+{
+ struct ctl_tcp_event *cte = arg;
+ int retry_flag = EV_WRITE;
+ int len;
+ int ret;
+
+ if (event == EV_TIMEOUT) {
+ cte->host->up = HOST_DOWN;
+ check_tls_cleanup(cte);
+ hce_notify_done(cte->host, HCE_TLS_WRITE_TIMEOUT);
+ return;
+ }
+
+ len = strlen(cte->table->sendbuf);
+
+ ret = tls_write(cte->tls, cte->table->sendbuf, len);
+ if (ret > 0) {
+ if ((cte->buf = ibuf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) ==
+ NULL)
+ fatalx("ssl_write: cannot create dynamic buffer");
+
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, check_tls_read,
+ &cte->tv_start, &cte->table->conf.timeout, cte);
+ return;
+ } else if (ret == TLS_WANT_POLLIN) {
+ retry_flag = EV_READ;
+ } else if (ret == TLS_WANT_POLLOUT) {
+ retry_flag = EV_WRITE;
+ } else {
+ cte->host->up = HOST_DOWN;
+ check_tls_error(cte, cte->host->conf.name, "cannot write");
+ check_tls_cleanup(cte);
+ hce_notify_done(cte->host, HCE_TLS_WRITE_ERROR);
+ return;
+ }
+
+ event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, check_tls_write,
+ &cte->tv_start, &cte->table->conf.timeout, cte);
+}
+
+void
+check_tls_handshake(int fd, short event, void *arg)
+{
+ struct ctl_tcp_event *cte = arg;
+ int retry_flag = 0;
+ int ret;
+
+ if (event == EV_TIMEOUT) {
+ cte->host->up = HOST_DOWN;
+ hce_notify_done(cte->host, HCE_TLS_CONNECT_TIMEOUT);
+ check_tls_cleanup(cte);
+ return;
+ }
+
+ ret = tls_handshake(cte->tls);
+ if (ret == 0) {
+ if (cte->table->conf.check == CHECK_TCP) {
+ cte->host->up = HOST_UP;
+ hce_notify_done(cte->host, HCE_TLS_CONNECT_OK);
+ check_tls_cleanup(cte);
+ return;
+ }
+ if (cte->table->sendbuf != NULL) {
+ event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE,
+ check_tls_write, &cte->tv_start,
+ &cte->table->conf.timeout, cte);
+ return;
+ }
+ if ((cte->buf = ibuf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) ==
+ NULL)
+ fatalx("ssl_connect: cannot create dynamic buffer");
+ event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_READ,
+ check_tls_read, &cte->tv_start, &cte->table->conf.timeout,
+ cte);
+ return;
+ } else if (ret == TLS_WANT_POLLIN) {
+ retry_flag = EV_READ;
+ } else if (ret == TLS_WANT_POLLOUT) {
+ retry_flag = EV_WRITE;
+ } else {
+ cte->host->up = HOST_DOWN;
+ check_tls_error(cte, cte->host->conf.name,
+ "cannot connect");
+ hce_notify_done(cte->host, HCE_TLS_CONNECT_FAIL);
+ check_tls_cleanup(cte);
+ return;
+ }
+
+ event_again(&cte->ev, cte->s, EV_TIMEOUT|retry_flag,
+ check_tls_handshake,
+ &cte->tv_start, &cte->table->conf.timeout, cte);
+}
+
+void
+check_tls_cleanup(struct ctl_tcp_event *cte)
+{
+ tls_close(cte->tls);
+ tls_reset(cte->tls);
+ close(cte->s);
+ ibuf_free(cte->buf);
+ cte->buf = NULL;
+}
+
+void
+check_tls_error(struct ctl_tcp_event *cte, const char *where, const char *what)
+{
+ if (log_getverbose() < 2)
+ return;
+ log_debug("TLS error: %s: %s: %s", where, what, tls_error(cte->tls));
+}
+
+void
+check_tls(struct ctl_tcp_event *cte)
+{
+ if (cte->tls == NULL) {
+ cte->tls = tls_client();
+ if (cte->tls == NULL)
+ fatal("cannot create TLS connection");
+ }
+ /* need to re-configure because of tls_reset */
+ if (tls_configure(cte->tls, cte->table->tls_cfg) == -1)
+ fatal("cannot configure TLS connection");
+
+ if (tls_connect_socket(cte->tls, cte->s, NULL) == -1) {
+ check_tls_error(cte, cte->host->conf.name,
+ "cannot connect");
+ tls_close(cte->tls);
+ tls_reset(cte->tls);
+ cte->host->up = HOST_UNKNOWN;
+ hce_notify_done(cte->host, HCE_TLS_CONNECT_ERROR);
+ return;
+ }
+
+ event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE, check_tls_handshake,
+ &cte->tv_start, &cte->table->conf.timeout, cte);
+}
diff --git a/usr.sbin/relayd/config.c b/usr.sbin/relayd/config.c
index e9d00420804..2d95412460b 100644
--- a/usr.sbin/relayd/config.c
+++ b/usr.sbin/relayd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.31 2016/11/24 21:01:18 reyk Exp $ */
+/* $OpenBSD: config.c,v 1.32 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -100,8 +100,12 @@ config_init(struct relayd *env)
(void)strlcpy(env->sc_proto_default.tlsciphers,
TLSCIPHERS_DEFAULT,
sizeof(env->sc_proto_default.tlsciphers));
- env->sc_proto_default.tlsecdhcurve = TLSECDHCURVE_DEFAULT;
- env->sc_proto_default.tlsdhparams = TLSDHPARAMS_DEFAULT;
+ (void)strlcpy(env->sc_proto_default.tlsecdhcurve,
+ TLSECDHCURVE_DEFAULT,
+ sizeof(env->sc_proto_default.tlsecdhcurve));
+ (void)strlcpy(env->sc_proto_default.tlsdhparams,
+ TLSDHPARAM_DEFAULT,
+ sizeof(env->sc_proto_default.tlsdhparams));
env->sc_proto_default.type = RELAY_PROTO_TCP;
(void)strlcpy(env->sc_proto_default.name, "default",
sizeof(env->sc_proto_default.name));
@@ -269,6 +273,8 @@ config_getcfg(struct relayd *env, struct imsg *imsg)
ssl_init(env);
if (what & CONFIG_CA_ENGINE)
ca_engine_init(env);
+ if (tls_init() == -1)
+ fatalx("unable to initialize TLS");
}
if (privsep_process != PROC_PARENT)
diff --git a/usr.sbin/relayd/hce.c b/usr.sbin/relayd/hce.c
index 33cc9ee2a45..6162c2008eb 100644
--- a/usr.sbin/relayd/hce.c
+++ b/usr.sbin/relayd/hce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hce.c,v 1.75 2016/09/03 14:09:04 reyk Exp $ */
+/* $OpenBSD: hce.c,v 1.76 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -90,9 +90,11 @@ hce_setup_events(void)
if (env->sc_conf.flags & F_TLS) {
TAILQ_FOREACH(table, env->sc_tables, entry) {
if (!(table->conf.flags & F_TLS) ||
- table->ssl_ctx != NULL)
+ table->tls_cfg != NULL)
continue;
- table->ssl_ctx = ssl_ctx_create(env);
+ table->tls_cfg = tls_config_new();
+ tls_config_insecure_noverifycert(table->tls_cfg);
+ tls_config_insecure_noverifyname(table->tls_cfg);
}
}
}
diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y
index 57ab789db8f..5e318601f26 100644
--- a/usr.sbin/relayd/parse.y
+++ b/usr.sbin/relayd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.214 2017/01/05 13:53:09 krw Exp $ */
+/* $OpenBSD: parse.y,v 1.215 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -181,7 +181,6 @@ typedef struct {
%type <v.number> opttls opttlsclient
%type <v.number> redirect_proto relay_proto match
%type <v.number> action ruleaf key_option
-%type <v.number> tlsdhparams tlsecdhcurve
%type <v.port> port
%type <v.host> host
%type <v.addr> address
@@ -1000,8 +999,10 @@ proto : relay_proto PROTO STRING {
TAILQ_INIT(&p->rules);
(void)strlcpy(p->tlsciphers, TLSCIPHERS_DEFAULT,
sizeof(p->tlsciphers));
- p->tlsdhparams = TLSDHPARAMS_DEFAULT;
- p->tlsecdhcurve = TLSECDHCURVE_DEFAULT;
+ (void)strlcpy(p->tlsecdhcurve, TLSECDHCURVE_DEFAULT,
+ sizeof(p->tlsecdhcurve));
+ (void)strlcpy(p->tlsdhparams, TLSDHPARAM_DEFAULT,
+ sizeof(p->tlsdhparams));
if (last_proto_id == INT_MAX) {
yyerror("too many protocols defined");
free(p);
@@ -1088,8 +1089,8 @@ tlsflags_l : tlsflags comma tlsflags_l
| tlsflags
;
-tlsflags : SESSION TICKETS { proto->tickets = 0; }
- | NO SESSION TICKETS { proto->tickets = -1; }
+tlsflags : SESSION TICKETS { proto->tickets = 1; }
+ | NO SESSION TICKETS { proto->tickets = 0; }
| CIPHERS STRING {
if (strlcpy(proto->tlsciphers, $2,
sizeof(proto->tlsciphers)) >=
@@ -1101,16 +1102,68 @@ tlsflags : SESSION TICKETS { proto->tickets = 0; }
free($2);
}
| NO EDH {
- proto->tlsdhparams = TLSDHPARAMS_NONE;
+ (void)strlcpy(proto->tlsdhparams, "none",
+ sizeof(proto->tlsdhparams));
}
- | EDH tlsdhparams {
- proto->tlsdhparams = $2;
+ | EDH {
+ (void)strlcpy(proto->tlsdhparams, "auto",
+ sizeof(proto->tlsdhparams));
+ }
+ | EDH PARAMS STRING {
+ struct tls_config *tls_cfg;
+ if ((tls_cfg = tls_config_new()) == NULL) {
+ yyerror("tls_config_new failed");
+ free($3);
+ YYERROR;
+ }
+ if (tls_config_set_dheparams(tls_cfg, $3) != 0) {
+ yyerror("tls edh params %s: %s", $3,
+ tls_config_error(tls_cfg));
+ tls_config_free(tls_cfg);
+ free($3);
+ YYERROR;
+ }
+ tls_config_free(tls_cfg);
+ if (strlcpy(proto->tlsdhparams, $3,
+ sizeof(proto->tlsdhparams)) >=
+ sizeof(proto->tlsdhparams)) {
+ yyerror("tls edh truncated");
+ free($3);
+ YYERROR;
+ }
+ free($3);
}
| NO ECDH {
- proto->tlsecdhcurve = 0;
+ (void)strlcpy(proto->tlsecdhcurve, "none",
+ sizeof(proto->tlsecdhcurve));
+ }
+ | ECDH {
+ (void)strlcpy(proto->tlsecdhcurve, "auto",
+ sizeof(proto->tlsecdhcurve));
}
- | ECDH tlsecdhcurve {
- proto->tlsecdhcurve = $2;
+ | ECDH CURVE STRING {
+ struct tls_config *tls_cfg;
+ if ((tls_cfg = tls_config_new()) == NULL) {
+ yyerror("tls_config_new failed");
+ free($3);
+ YYERROR;
+ }
+ if (tls_config_set_ecdhecurve(tls_cfg, $3) != 0) {
+ yyerror("tls ecdh curve %s: %s", $3,
+ tls_config_error(tls_cfg));
+ tls_config_free(tls_cfg);
+ free($3);
+ YYERROR;
+ }
+ tls_config_free(tls_cfg);
+ if (strlcpy(proto->tlsecdhcurve, $3,
+ sizeof(proto->tlsecdhcurve)) >=
+ sizeof(proto->tlsecdhcurve)) {
+ yyerror("tls ecdh truncated");
+ free($3);
+ YYERROR;
+ }
+ free($3);
}
| CA FILENAME STRING {
if (strlcpy(proto->tlsca, $3,
@@ -1549,29 +1602,6 @@ key_option : /* empty */ { $$ = KEY_OPTION_NONE; }
| LOG { $$ = KEY_OPTION_LOG; }
;
-tlsdhparams : /* empty */ { $$ = TLSDHPARAMS_MIN; }
- | PARAMS NUMBER {
- if ($2 < TLSDHPARAMS_MIN) {
- yyerror("EDH params not supported: %d", $2);
- YYERROR;
- }
- $$ = $2;
- }
- ;
-
-tlsecdhcurve : /* empty */ { $$ = TLSECDHCURVE_DEFAULT; }
- | CURVE STRING {
- if (strcmp("none", $2) == 0)
- $$ = 0;
- else if ((proto->tlsecdhcurve = OBJ_sn2nid($2)) == 0) {
- yyerror("ECDH curve not supported");
- free($2);
- YYERROR;
- }
- free($2);
- }
- ;
-
relay : RELAY STRING {
struct relay *r;
diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c
index 3ed127553b9..4b36e4a8a31 100644
--- a/usr.sbin/relayd/relay.c
+++ b/usr.sbin/relayd/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.219 2017/02/02 08:24:16 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.220 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -39,8 +39,7 @@
#include <siphash.h>
#include <imsg.h>
-#include <openssl/dh.h>
-#include <openssl/ssl.h>
+#include <tls.h>
#include "relayd.h"
@@ -73,22 +72,15 @@ void relay_input(struct rsession *);
void relay_hash_addr(SIPHASH_CTX *, struct sockaddr_storage *, int);
-DH * relay_tls_get_dhparams(int);
-DH *relay_tls_callback_dh(SSL *, int, int);
-SSL_CTX *relay_tls_ctx_create(struct relay *);
+int relay_tls_ctx_create(struct relay *);
void relay_tls_transaction(struct rsession *,
struct ctl_relay_event *);
-void relay_tls_accept(int, short, void *);
+void relay_tls_handshake(int, short, void *);
void relay_connect_retry(int, short, void *);
-void relay_tls_connect(int, short, void *);
void relay_tls_connected(struct ctl_relay_event *);
void relay_tls_readcb(int, short, void *);
void relay_tls_writecb(int, short, void *);
-struct tls_ticket *relay_get_ticket_key(unsigned char *);
-int relay_tls_session_ticket(SSL *, unsigned char *,
- unsigned char *, EVP_CIPHER_CTX *, HMAC_CTX *, int);
-
char *relay_load_file(const char *, off_t *);
extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t,
size_t, void *);
@@ -262,7 +254,7 @@ relay_protodebug(struct relay *rlay)
fprintf(stderr, "\ttls flags: %s\n",
printb_flags(proto->tlsflags, TLSFLAG_BITS));
fprintf(stderr, "\ttls session tickets: %s\n",
- (proto->tickets > -1) ? "enabled" : "disabled");
+ (proto->tickets == 1) ? "enabled" : "disabled");
fprintf(stderr, "\ttype: ");
switch (proto->type) {
case RELAY_PROTO_TCP:
@@ -426,8 +418,8 @@ relay_launch(void)
TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) &&
- (rlay->rl_ssl_ctx = relay_tls_ctx_create(rlay)) == NULL)
- fatal("relay_init: failed to create TLS context");
+ relay_tls_ctx_create(rlay) == -1)
+ fatalx("relay_launch: failed to create TLS context");
TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) {
/*
@@ -687,7 +679,7 @@ relay_connected(int fd, short sig, void *arg)
return;
}
- if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->ssl == NULL)) {
+ if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->tls == NULL)) {
relay_tls_transaction(con, out);
return;
}
@@ -727,7 +719,7 @@ relay_connected(int fd, short sig, void *arg)
con->se_out.bev = bev;
/* Initialize the TLS wrapper */
- if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->ssl != NULL))
+ if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->tls != NULL))
relay_tls_connected(out);
bufferevent_settimeout(bev,
@@ -778,7 +770,7 @@ relay_input(struct rsession *con)
}
/* Initialize the TLS wrapper */
- if ((rlay->rl_conf.flags & F_TLS) && con->se_in.ssl != NULL)
+ if ((rlay->rl_conf.flags & F_TLS) && con->se_in.tls != NULL)
relay_tls_connected(&con->se_in);
bufferevent_settimeout(con->se_in.bev,
@@ -826,8 +818,8 @@ relay_dump(struct ctl_relay_event *cre, const void *buf, size_t len)
* of non-blocking events etc. This is useful to print an
* error message before gracefully closing the session.
*/
- if (cre->ssl != NULL)
- (void)SSL_write(cre->ssl, buf, len);
+ if (cre->tls != NULL)
+ (void)tls_write(cre->tls, buf, len);
else
(void)write(cre->s, buf, len);
}
@@ -1086,9 +1078,9 @@ relay_accept(int fd, short event, void *arg)
goto err;
con->se_in.s = s;
- con->se_in.ssl = NULL;
+ con->se_in.tls = NULL;
con->se_out.s = -1;
- con->se_out.ssl = NULL;
+ con->se_out.tls = NULL;
con->se_in.dst = &con->se_out;
con->se_out.dst = &con->se_in;
con->se_in.con = con;
@@ -1401,7 +1393,7 @@ relay_session(struct rsession *con)
return;
}
- if ((rlay->rl_conf.flags & F_TLS) && (in->ssl == NULL)) {
+ if ((rlay->rl_conf.flags & F_TLS) && (in->tls == NULL)) {
relay_tls_transaction(con, in);
return;
}
@@ -1570,7 +1562,7 @@ relay_connect(struct rsession *con)
/* Connection is already established but session not active */
if ((rlay->rl_conf.flags & F_TLSINSPECT) &&
con->se_out.state == STATE_PRECONNECT) {
- if (con->se_out.ssl == NULL) {
+ if (con->se_out.tls == NULL) {
log_debug("%s: tls connect failed", __func__);
return (-1);
}
@@ -1706,14 +1698,11 @@ relay_close(struct rsession *con, const char *msg)
bufferevent_free(con->se_in.bev);
else if (con->se_in.output != NULL)
evbuffer_free(con->se_in.output);
- if (con->se_in.ssl != NULL) {
- /* XXX handle non-blocking shutdown */
- if (SSL_shutdown(con->se_in.ssl) == 0)
- SSL_shutdown(con->se_in.ssl);
- SSL_free(con->se_in.ssl);
- }
- if (con->se_in.tlscert != NULL)
- X509_free(con->se_in.tlscert);
+ if (con->se_in.tls != NULL)
+ tls_close(con->se_in.tls);
+ tls_free(con->se_in.tls);
+ tls_config_free(con->se_in.tls_cfg);
+ free(con->se_in.tlscert);
if (con->se_in.s != -1) {
close(con->se_in.s);
if (con->se_out.s == -1) {
@@ -1726,20 +1715,16 @@ relay_close(struct rsession *con, const char *msg)
__func__, relay_inflight);
}
}
- free(con->se_in.buf);
if (con->se_out.bev != NULL)
bufferevent_free(con->se_out.bev);
else if (con->se_out.output != NULL)
evbuffer_free(con->se_out.output);
- if (con->se_out.ssl != NULL) {
- /* XXX handle non-blocking shutdown */
- if (SSL_shutdown(con->se_out.ssl) == 0)
- SSL_shutdown(con->se_out.ssl);
- SSL_free(con->se_out.ssl);
- }
- if (con->se_out.tlscert != NULL)
- X509_free(con->se_out.tlscert);
+ if (con->se_out.tls != NULL)
+ tls_close(con->se_out.tls);
+ tls_free(con->se_out.tls);
+ tls_config_free(con->se_out.tls_cfg);
+ free(con->se_out.tlscert);
if (con->se_out.s != -1) {
close(con->se_out.s);
@@ -1751,8 +1736,6 @@ relay_close(struct rsession *con, const char *msg)
}
con->se_out.state = STATE_INIT;
- free(con->se_out.buf);
-
if (con->se_log != NULL)
evbuffer_free(con->se_log);
@@ -1896,6 +1879,8 @@ relay_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg)
int
relay_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
+ struct relay_ticket_key ticket;
+ struct relay *rlay;
struct rsession *con;
struct timeval tv;
objid_t id;
@@ -1945,13 +1930,15 @@ relay_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
config_getreset(env, imsg);
break;
case IMSG_TLSTICKET_REKEY:
- IMSG_SIZE_CHECK(imsg, (&env->sc_tls_ticket));
- /* rotate keys */
- memcpy(&env->sc_tls_ticket_bak, &env->sc_tls_ticket,
- sizeof(env->sc_tls_ticket));
- env->sc_tls_ticket_bak.tt_backup = 1;
- memcpy(&env->sc_tls_ticket, imsg->data,
- sizeof(env->sc_tls_ticket));
+ IMSG_SIZE_CHECK(imsg, (&ticket));
+ memcpy(&env->sc_ticket, imsg->data, sizeof(env->sc_ticket));
+ TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
+ if (rlay->rl_conf.flags & F_TLS)
+ tls_config_add_ticket_key(rlay->rl_tls_cfg,
+ env->sc_ticket.tt_keyrev,
+ env->sc_ticket.tt_key,
+ sizeof(env->sc_ticket.tt_key));
+ }
break;
default:
return (-1);
@@ -1960,69 +1947,6 @@ relay_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
return (0);
}
-DH *
-relay_tls_get_dhparams(int keylen)
-{
- DH *dh;
- BIGNUM *(*prime)(BIGNUM *);
- const char *gen;
-
- gen = "2";
- if (keylen >= 8192)
- prime = get_rfc3526_prime_8192;
- else if (keylen >= 4096)
- prime = get_rfc3526_prime_4096;
- else if (keylen >= 3072)
- prime = get_rfc3526_prime_3072;
- else if (keylen >= 2048)
- prime = get_rfc3526_prime_2048;
- else if (keylen >= 1536)
- prime = get_rfc3526_prime_1536;
- else
- prime = get_rfc2409_prime_1024;
-
- if ((dh = DH_new()) == NULL)
- return (NULL);
-
- dh->p = (*prime)(NULL);
- BN_dec2bn(&dh->g, gen);
-
- if (dh->p == NULL || dh->g == NULL) {
- DH_free(dh);
- return (NULL);
- }
-
- return (dh);
-}
-
-DH *
-relay_tls_callback_dh(SSL *ssl, int export, int keylen)
-{
- struct ctl_relay_event *cre;
- EVP_PKEY *pkey;
- int keytype, maxlen;
- DH *dh = NULL;
-
- /* Get maximum key length from config */
- if ((cre = (struct ctl_relay_event *)SSL_get_app_data(ssl)) == NULL)
- return (NULL);
- maxlen = cre->con->se_relay->rl_proto->tlsdhparams;
-
- /* Get the private key length from the cert */
- if ((pkey = SSL_get_privatekey(ssl))) {
- keytype = EVP_PKEY_type(pkey->type);
- if (keytype == EVP_PKEY_RSA || keytype == EVP_PKEY_DSA)
- keylen = EVP_PKEY_bits(pkey);
- else
- return (NULL);
- }
-
- /* get built-in params based on the shorter key length */
- dh = relay_tls_get_dhparams(MINIMUM(keylen, maxlen));
-
- return (dh);
-}
-
int
relay_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
{
@@ -2034,316 +1958,357 @@ relay_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
return (-1);
}
-SSL_CTX *
-relay_tls_ctx_create(struct relay *rlay)
+static int
+relay_tls_ctx_create_proto(struct protocol *proto, struct tls_config *tls_cfg)
{
- struct protocol *proto = rlay->rl_proto;
- SSL_CTX *ctx;
- EC_KEY *ecdhkey;
+ uint32_t protocols = 0;
- ctx = SSL_CTX_new(SSLv23_method());
- if (ctx == NULL)
- goto err;
+ /* Set the allowed SSL protocols */
+ if (proto->tlsflags & TLSFLAG_TLSV1_0)
+ protocols |= TLS_PROTOCOL_TLSv1_0;
+ if (proto->tlsflags & TLSFLAG_TLSV1_1)
+ protocols |= TLS_PROTOCOL_TLSv1_1;
+ if (proto->tlsflags & TLSFLAG_TLSV1_2)
+ protocols |= TLS_PROTOCOL_TLSv1_2;
+ if (tls_config_set_protocols(tls_cfg, protocols) == -1) {
+ log_warnx("could not set the TLS protocol: %s",
+ tls_config_error(tls_cfg));
+ return (-1);
+ }
+
+ if (tls_config_set_ciphers(tls_cfg, proto->tlsciphers)) {
+ log_warnx("could not set the TLS cypers: %s",
+ tls_config_error(tls_cfg));
+ return (-1);
+ }
+
+ if ((proto->tlsflags & TLSFLAG_CIPHER_SERVER_PREF) == 0)
+ tls_config_prefer_ciphers_client(tls_cfg);
/*
- * Disable the session cache by default.
- * Everything modern uses tickets
+ * Set session ID context to a random value. It needs to be the
+ * same accross all relay processes or session caching will fail.
*/
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+ if (tls_config_set_session_id(tls_cfg, env->sc_conf.tls_sid,
+ sizeof(env->sc_conf.tls_sid)) == -1) {
+ log_warnx("could not set the TLS session ID: %s",
+ tls_config_error(tls_cfg));
+ return (-1);
+ }
/* Set callback for TLS session tickets if enabled */
- if (proto->tickets == -1)
- SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
- else {
- if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx,
- relay_tls_session_ticket))
- log_warnx("could not set the TLS ticket callback");
+ if (proto->tickets == 1) {
/* set timeout to the ticket rekey time */
- SSL_CTX_set_timeout(ctx, TLS_TICKET_REKEY_TIME);
+ tls_config_set_session_lifetime(tls_cfg, TLS_SESSION_LIFETIME);
+
+ tls_config_add_ticket_key(tls_cfg,
+ env->sc_ticket.tt_keyrev, env->sc_ticket.tt_key,
+ sizeof(env->sc_ticket.tt_key));
}
- /* Enable all workarounds and set SSL options */
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
- SSL_CTX_set_options(ctx,
- SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
- if (proto->tlsflags & TLSFLAG_CIPHER_SERVER_PREF)
- SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
- if ((proto->tlsflags & TLSFLAG_CLIENT_RENEG) == 0)
- SSL_CTX_set_options(ctx, SSL_OP_NO_CLIENT_RENEGOTIATION);
+ if (tls_config_set_ecdhecurve(tls_cfg, proto->tlsecdhcurve) != 0) {
+ log_warnx("failed to set ecdh curve %s: %s",
+ proto->tlsecdhcurve, tls_config_error(tls_cfg));
+ return (-1);
+ }
- /* Set the allowed SSL protocols */
- SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
- SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv3);
- if ((proto->tlsflags & TLSFLAG_SSLV3) == 0)
- SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
- SSL_CTX_clear_options(ctx, SSL_OP_NO_TLSv1);
- if ((proto->tlsflags & TLSFLAG_TLSV1_0) == 0)
- SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
- SSL_CTX_clear_options(ctx, SSL_OP_NO_TLSv1_1);
- if ((proto->tlsflags & TLSFLAG_TLSV1_1) == 0)
- SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1);
- SSL_CTX_clear_options(ctx, SSL_OP_NO_TLSv1_2);
- if ((proto->tlsflags & TLSFLAG_TLSV1_2) == 0)
- SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2);
-
- if (proto->tlsecdhcurve > 0) {
- /* Enable ECDHE support for TLS perfect forward secrecy */
- if ((ecdhkey =
- EC_KEY_new_by_curve_name(proto->tlsecdhcurve)) == NULL)
- goto err;
- SSL_CTX_set_tmp_ecdh(ctx, ecdhkey);
- SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
- EC_KEY_free(ecdhkey);
+ if (tls_config_set_dheparams(tls_cfg, proto->tlsdhparams) != 0) {
+ log_warnx("failed to set dh params %s: %s",
+ proto->tlsdhparams, tls_config_error(tls_cfg));
+ return (-1);
}
- if (proto->tlsdhparams > 0) {
- /* Enable EDH params (forward secrecy for older clients) */
- SSL_CTX_set_tmp_dh_callback(ctx, relay_tls_callback_dh);
+ return (0);
+}
+
+/*
+ * This function is not publicy exported because it is a hack until libtls
+ * has a proper privsep setup
+ */
+void tls_config_skip_private_key_check(struct tls_config *config);
+
+int
+relay_tls_ctx_create(struct relay *rlay)
+{
+ struct tls_config *tls_cfg, *tls_client_cfg;
+ struct tls *tls = NULL;
+ const char *fake_key;
+ int fake_keylen;
+
+ if ((tls_cfg = tls_config_new()) == NULL) {
+ log_warnx("unable to allocate TLS config");
+ return (-1);
+ }
+ if ((tls_client_cfg = tls_config_new()) == NULL) {
+ log_warnx("unable to allocate TLS config");
+ return (-1);
}
- if (!SSL_CTX_set_cipher_list(ctx, proto->tlsciphers))
+ if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_cfg) == -1)
+ goto err;
+ if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_client_cfg) == -1)
goto err;
/* Verify the server certificate if we have a CA chain */
- if ((rlay->rl_conf.flags & F_TLSCLIENT) &&
- (rlay->rl_tls_ca != NULL)) {
- if (!SSL_CTX_load_verify_mem(ctx,
- rlay->rl_tls_ca, rlay->rl_conf.tls_ca_len))
- goto err;
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+ if (rlay->rl_conf.flags & F_TLSCLIENT) {
+ /*
+ * Currently relayd can't verify the name of certs and changing
+ * this is non trivial. For now just disable name verification.
+ */
+ tls_config_insecure_noverifyname(tls_client_cfg);
+
+ if (rlay->rl_tls_ca != NULL) {
+ if (tls_config_set_ca_mem(tls_client_cfg,
+ rlay->rl_tls_ca, rlay->rl_conf.tls_ca_len) != 0) {
+ log_warnx("failed to set root certificates: %s",
+ tls_config_error(tls_client_cfg));
+ goto err;
+ }
+ } else {
+ /* No root cert available so disable the checking */
+ tls_config_insecure_noverifycert(tls_client_cfg);
+ }
+
+ rlay->rl_tls_client_cfg = tls_client_cfg;
}
- if ((rlay->rl_conf.flags & F_TLS) == 0)
- return (ctx);
+ if (rlay->rl_conf.flags & F_TLS) {
+ log_debug("%s: loading certificate", __func__);
+ /*
+ * Use the public key as the "private" key - the secret key
+ * parameters are hidden in an extra process that will be
+ * contacted by the RSA engine. The SSL/TLS library needs at
+ * least the public key parameters in the current process.
+ * For this we need to skip the private key check done by
+ * libtls.
+ */
+ tls_config_skip_private_key_check(tls_cfg);
- log_debug("%s: loading certificate", __func__);
- if (!SSL_CTX_use_certificate_chain_mem(ctx,
- rlay->rl_tls_cert, rlay->rl_conf.tls_cert_len))
- goto err;
+ if ((fake_keylen = ssl_ctx_fake_private_key(rlay->rl_tls_cert,
+ rlay->rl_conf.tls_cert_len, &fake_key)) == -1) {
+ /* error already printed */
+ goto err;
+ }
- log_debug("%s: loading private key", __func__);
- if (!ssl_ctx_fake_private_key(ctx,
- &rlay->rl_conf.tls_keyid, sizeof(rlay->rl_conf.tls_keyid),
- rlay->rl_tls_cert, rlay->rl_conf.tls_cert_len,
- &rlay->rl_tls_x509, &rlay->rl_tls_pkey))
- goto err;
+ if (tls_config_set_keypair_ocsp_mem(tls_cfg,
+ rlay->rl_tls_cert, rlay->rl_conf.tls_cert_len,
+ fake_key, fake_keylen, NULL, 0) != 0) {
+ log_warnx("failed to set tls certificate: %s",
+ tls_config_error(tls_cfg));
+ goto err;
+ }
- if (!SSL_CTX_check_private_key(ctx))
- goto err;
+ if (rlay->rl_conf.tls_cacert_len) {
+ log_debug("%s: loading CA certificate", __func__);
+ if (!ssl_load_pkey(&rlay->rl_conf.tls_cakeyid,
+ rlay->rl_tls_cacert, rlay->rl_conf.tls_cacert_len,
+ &rlay->rl_tls_cacertx509, &rlay->rl_tls_capkey))
+ goto err;
+ /* loading certificate public key */
+ if (!ssl_load_pkey(NULL,
+ rlay->rl_tls_cert, rlay->rl_conf.tls_cert_len,
+ NULL, &rlay->rl_tls_pkey))
+ goto err;
+ }
- if (rlay->rl_conf.tls_cacert_len) {
- log_debug("%s: loading CA private key", __func__);
- if (!ssl_load_pkey(&rlay->rl_conf.tls_cakeyid,
- sizeof(rlay->rl_conf.tls_cakeyid),
- rlay->rl_tls_cacert, rlay->rl_conf.tls_cacert_len,
- &rlay->rl_tls_cacertx509, &rlay->rl_tls_capkey))
+ tls = tls_server();
+ if (tls == NULL) {
+ log_warnx("unable to allocate TLS context");
+ goto err;
+ }
+ if (tls_configure(tls, tls_cfg) == -1) {
+ log_warnx("could not configure the TLS context: %s",
+ tls_error(tls));
+ tls_free(tls);
goto err;
+ }
+ rlay->rl_tls_cfg = tls_cfg;
+ rlay->rl_tls_ctx = tls;
}
- /*
- * Set session ID context to a random value. It needs to be the
- * same accross all relay processes or session caching will fail.
- */
- if (!SSL_CTX_set_session_id_context(ctx, env->sc_conf.tls_sid,
- sizeof(env->sc_conf.tls_sid)))
- goto err;
-
/* The text versions of the keys/certs are not needed anymore */
purge_key(&rlay->rl_tls_cert, rlay->rl_conf.tls_cert_len);
purge_key(&rlay->rl_tls_cacert, rlay->rl_conf.tls_cacert_len);
- return (ctx);
+ if (rlay->rl_tls_client_cfg == NULL)
+ tls_config_free(tls_client_cfg);
+ if (rlay->rl_tls_cfg == NULL)
+ tls_config_free(tls_cfg);
+ return (0);
err:
- SSL_CTX_free(ctx);
- ssl_error(rlay->rl_conf.name, "relay_tls_ctx_create");
- return (NULL);
+ tls_config_free(tls_client_cfg);
+ tls_config_free(tls_cfg);
+ return (-1);
}
-void
-relay_tls_transaction(struct rsession *con, struct ctl_relay_event *cre)
+static struct tls *
+relay_tls_inspect_create(struct relay *rlay, struct ctl_relay_event *cre)
{
- struct relay *rlay = con->se_relay;
- SSL *ssl;
- const SSL_METHOD *method;
- void (*cb)(int, short, void *);
- u_int flag;
-
- ssl = SSL_new(rlay->rl_ssl_ctx);
- if (ssl == NULL)
+ struct tls_config *tls_cfg;
+ struct tls *tls;
+ const char *fake_key;
+ int fake_keylen;
+
+ /* TLS inspection: use session-specific certificate */
+ if ((tls_cfg = tls_config_new()) == NULL) {
+ log_warnx("unable to allocate TLS config");
+ goto err;
+ }
+ if (relay_tls_ctx_create_proto(rlay->rl_proto,
+ tls_cfg) == -1) {
+ tls_config_free(tls_cfg);
goto err;
-
- if (cre->dir == RELAY_DIR_REQUEST) {
- cb = relay_tls_accept;
- method = SSLv23_server_method();
- flag = EV_READ;
-
- /* Use session-specific certificate for TLS inspection. */
- if (cre->tlscert != NULL)
- SSL_use_certificate(ssl, cre->tlscert);
- } else {
- cb = relay_tls_connect;
- method = SSLv23_client_method();
- flag = EV_WRITE;
}
- if (!SSL_set_ssl_method(ssl, method))
+ log_debug("%s: loading intercepted certificate", __func__);
+ if ((fake_keylen = ssl_ctx_fake_private_key(cre->tlscert,
+ cre->tlscert_len, &fake_key)) == -1) {
+ /* error already printed */
goto err;
- if (!SSL_set_fd(ssl, cre->s))
+ }
+ if (tls_config_set_keypair_ocsp_mem(tls_cfg,
+ cre->tlscert, cre->tlscert_len, fake_key, fake_keylen,
+ NULL, 0) != 0) {
+ log_warnx("failed to set tls certificate: %s",
+ tls_config_error(tls_cfg));
goto err;
+ }
- if (cre->dir == RELAY_DIR_REQUEST)
- SSL_set_accept_state(ssl);
- else
- SSL_set_connect_state(ssl);
-
- SSL_set_app_data(ssl, cre);
- cre->ssl = ssl;
-
- DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id,
- (flag == EV_READ) ? "EV_READ" : "EV_WRITE");
- event_again(&con->se_ev, cre->s, EV_TIMEOUT|flag, cb,
- &con->se_tv_start, &rlay->rl_conf.timeout, con);
- return;
+ tls = tls_server();
+ if (tls == NULL) {
+ log_warnx("unable to allocate TLS context");
+ goto err;
+ }
+ if (tls_configure(tls, tls_cfg) == -1) {
+ log_warnx("could not configure the TLS context: %s",
+ tls_error(tls));
+ tls_free(tls);
+ goto err;
+ }
+ cre->tls_cfg = tls_cfg;
+ return (tls);
err:
- SSL_free(ssl);
- ssl_error(rlay->rl_conf.name, "relay_tls_transaction");
- relay_close(con, "session tls failed");
+ tls_config_free(tls_cfg);
+ return (NULL);
}
void
-relay_tls_accept(int fd, short event, void *arg)
+relay_tls_transaction(struct rsession *con, struct ctl_relay_event *cre)
{
- struct rsession *con = arg;
- struct relay *rlay = con->se_relay;
- int retry_flag = 0;
- int tls_err = 0;
- int ret;
-
- if (event == EV_TIMEOUT) {
- relay_close(con, "TLS accept timeout");
- return;
- }
+ struct relay *rlay = con->se_relay;
+ struct tls *tls_server;
+ const char *errstr;
+ u_int flag;
- ret = SSL_accept(con->se_in.ssl);
- if (ret <= 0) {
- tls_err = SSL_get_error(con->se_in.ssl, ret);
+ if (cre->dir == RELAY_DIR_REQUEST) {
+ if (cre->tlscert != NULL)
+ tls_server = relay_tls_inspect_create(rlay, cre);
+ else
+ tls_server = rlay->rl_tls_ctx;
- switch (tls_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- case SSL_ERROR_ZERO_RETURN:
- case SSL_ERROR_SYSCALL:
- if (ret == 0) {
- relay_close(con, "closed");
- return;
- }
- /* FALLTHROUGH */
- default:
- ssl_error(rlay->rl_conf.name, "relay_tls_accept");
- relay_close(con, "TLS accept error");
- return;
+ if (tls_accept_socket(tls_server, &cre->tls, cre->s) == -1) {
+ errstr = "could not accept the TLS connection";
+ goto err;
+ }
+ if (cre->tlscert != NULL)
+ tls_free(tls_server);
+ flag = EV_READ;
+ } else {
+ cre->tls = tls_client();
+ if (cre->tls == NULL ||
+ tls_configure(cre->tls, rlay->rl_tls_client_cfg) == -1) {
+ errstr = "could not configure the TLS client context";
+ goto err;
+ }
+ if (tls_connect_socket(cre->tls, cre->s, NULL) == -1) {
+ errstr = "could not connect the TLS connection";
+ goto err;
}
+ flag = EV_WRITE;
}
-
-#ifdef DEBUG
- log_info(
-#else
- log_debug(
-#endif
- "relay %s, session %d established (%d active)",
- rlay->rl_conf.name, con->se_id, relay_sessions);
-
- relay_session(con);
+ log_debug("%s: session %d: scheduling on %s", __func__, con->se_id,
+ (flag == EV_READ) ? "EV_READ" : "EV_WRITE");
+ event_again(&con->se_ev, cre->s, EV_TIMEOUT|flag, relay_tls_handshake,
+ &con->se_tv_start, &rlay->rl_conf.timeout, cre);
return;
-retry:
- DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id,
- (retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE");
- event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_tls_accept,
- &con->se_tv_start, &rlay->rl_conf.timeout, con);
+ err:
+ relay_close(con, errstr);
}
void
-relay_tls_connect(int fd, short event, void *arg)
+relay_tls_handshake(int fd, short event, void *arg)
{
- struct rsession *con = arg;
- struct relay *rlay = con->se_relay;
- int retry_flag = 0;
- int tls_err = 0;
- int ret;
- X509 *servercert = NULL;
+ struct ctl_relay_event *cre = arg;
+ struct rsession *con = cre->con;
+ struct relay *rlay = con->se_relay;
+ int retry_flag = 0;
+ int ret;
if (event == EV_TIMEOUT) {
- relay_close(con, "TLS connect timeout");
+ relay_close(con, "TLS handshake timeout");
return;
}
- ret = SSL_connect(con->se_out.ssl);
- if (ret <= 0) {
- tls_err = SSL_get_error(con->se_out.ssl, ret);
-
- switch (tls_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- case SSL_ERROR_ZERO_RETURN:
- case SSL_ERROR_SYSCALL:
- if (ret == 0) {
- relay_close(con, "closed");
- return;
- }
- /* FALLTHROUGH */
- default:
- ssl_error(rlay->rl_conf.name, "relay_tls_connect");
- relay_close(con, "TLS connect error");
- return;
- }
- }
-
+ ret = tls_handshake(cre->tls);
+ if (ret == 0) {
#ifdef DEBUG
- log_info(
+ log_info(
#else
- log_debug(
+ log_debug(
#endif
- "relay %s, tls session %d connected (%d active)",
- rlay->rl_conf.name, con->se_id, relay_sessions);
+ "relay %s, tls session %d %s (%d active)",
+ rlay->rl_conf.name, con->se_id,
+ cre->dir == RELAY_DIR_REQUEST ? "established" : "connected",
+ relay_sessions);
- if (rlay->rl_conf.flags & F_TLSINSPECT) {
- if ((servercert =
- SSL_get_peer_certificate(con->se_out.ssl)) != NULL) {
- con->se_in.tlscert =
- ssl_update_certificate(servercert,
- rlay->rl_tls_pkey, rlay->rl_tls_capkey,
- rlay->rl_tls_cacertx509);
- } else
- con->se_in.tlscert = NULL;
- if (servercert != NULL)
- X509_free(servercert);
- if (con->se_in.tlscert == NULL)
- relay_close(con, "could not create certificate");
- else
+ if (cre->dir == RELAY_DIR_REQUEST) {
relay_session(con);
+ return;
+ }
+
+ if (rlay->rl_conf.flags & F_TLSINSPECT) {
+ const uint8_t *servercert;
+ size_t len;
+
+ servercert = tls_peer_cert_chain_pem(con->se_out.tls,
+ &len);
+ if (servercert != NULL) {
+ con->se_in.tlscert = ssl_update_certificate(
+ servercert, len,
+ rlay->rl_tls_pkey, rlay->rl_tls_capkey,
+ rlay->rl_tls_cacertx509,
+ &con->se_in.tlscert_len);
+ } else
+ con->se_in.tlscert = NULL;
+ if (con->se_in.tlscert == NULL)
+ relay_close(con,
+ "could not create certificate");
+ else
+ relay_session(con);
+ return;
+ }
+ relay_connected(fd, EV_WRITE, con);
+ return;
+ } else if (ret == TLS_WANT_POLLIN) {
+ retry_flag = EV_READ;
+ } else if (ret == TLS_WANT_POLLOUT) {
+ retry_flag = EV_WRITE;
+ } else {
+ log_debug("TLS handshake failed: %s: %s: %s",
+ rlay->rl_conf.name, __func__,
+ tls_error(cre->tls));
+ relay_close(con, "TLS handshake error");
return;
}
- relay_connected(fd, EV_WRITE, con);
- return;
-
-retry:
DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id,
(retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE");
- event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_tls_connect,
- &con->se_tv_start, &rlay->rl_conf.timeout, con);
+ event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_tls_handshake,
+ &con->se_tv_start, &rlay->rl_conf.timeout, cre);
}
void
@@ -2365,11 +2330,9 @@ relay_tls_readcb(int fd, short event, void *arg)
char rbuf[IBUF_READ_SIZE];
struct bufferevent *bufev = arg;
struct ctl_relay_event *cre = bufev->cbarg;
- struct rsession *con = cre->con;
- struct relay *rlay = con->se_relay;
- int ret = 0, tls_err = 0;
short what = EVBUFFER_READ;
int howmuch = IBUF_READ_SIZE;
+ ssize_t ret;
size_t len;
if (event == EV_TIMEOUT) {
@@ -2380,29 +2343,18 @@ relay_tls_readcb(int fd, short event, void *arg)
if (bufev->wm_read.high != 0)
howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high);
- ret = SSL_read(cre->ssl, rbuf, howmuch);
- if (ret <= 0) {
- tls_err = SSL_get_error(cre->ssl, ret);
+ ret = tls_read(cre->tls, rbuf, howmuch);
+ if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) {
+ goto retry;
+ } else if (ret < 0) {
+ what |= EVBUFFER_ERROR;
+ goto err;
+ }
+ len = ret;
- switch (tls_err) {
- case SSL_ERROR_WANT_READ:
- DPRINTF("%s: session %d: want read",
- __func__, con->se_id);
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- DPRINTF("%s: session %d: want write",
- __func__, con->se_id);
- goto retry;
- default:
- if (ret == 0)
- what |= EVBUFFER_EOF;
- else {
- ssl_error(rlay->rl_conf.name,
- "relay_tls_readcb");
- what |= EVBUFFER_ERROR;
- }
- goto err;
- }
+ if (len == 0) {
+ what |= EVBUFFER_EOF;
+ goto err;
}
if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
@@ -2439,9 +2391,8 @@ relay_tls_writecb(int fd, short event, void *arg)
{
struct bufferevent *bufev = arg;
struct ctl_relay_event *cre = bufev->cbarg;
- struct rsession *con = cre->con;
- struct relay *rlay = con->se_relay;
- int ret = 0, tls_err;
+ ssize_t ret;
+ size_t len;
short what = EVBUFFER_WRITE;
if (event == EV_TIMEOUT) {
@@ -2450,46 +2401,16 @@ relay_tls_writecb(int fd, short event, void *arg)
}
if (EVBUFFER_LENGTH(bufev->output)) {
- if (cre->buf == NULL) {
- cre->buflen = EVBUFFER_LENGTH(bufev->output);
- if ((cre->buf = malloc(cre->buflen)) == NULL) {
- what |= EVBUFFER_ERROR;
- goto err;
- }
- bcopy(EVBUFFER_DATA(bufev->output),
- cre->buf, cre->buflen);
- }
-
- ret = SSL_write(cre->ssl, cre->buf, cre->buflen);
- if (ret <= 0) {
- tls_err = SSL_get_error(cre->ssl, ret);
-
- switch (tls_err) {
- case SSL_ERROR_WANT_READ:
- DPRINTF("%s: session %d: want read",
- __func__, con->se_id);
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- DPRINTF("%s: session %d: want write",
- __func__, con->se_id);
- goto retry;
- default:
- if (ret == 0)
- what |= EVBUFFER_EOF;
- else {
- ssl_error(rlay->rl_conf.name,
- "relay_tls_writecb");
- what |= EVBUFFER_ERROR;
- }
- goto err;
- }
+ ret = tls_write(cre->tls, EVBUFFER_DATA(bufev->output),
+ EVBUFFER_LENGTH(bufev->output));
+ if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) {
+ goto retry;
+ } else if (ret < 0) {
+ what |= EVBUFFER_ERROR;
+ goto err;
}
- evbuffer_drain(bufev->output, ret);
- }
- if (cre->buf != NULL) {
- free(cre->buf);
- cre->buf = NULL;
- cre->buflen = 0;
+ len = ret;
+ evbuffer_drain(bufev->output, len);
}
if (EVBUFFER_LENGTH(bufev->output) != 0)
@@ -2501,71 +2422,13 @@ relay_tls_writecb(int fd, short event, void *arg)
return;
retry:
- if (cre->buflen != 0)
- relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
+ relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
return;
err:
- if (cre->buf != NULL) {
- free(cre->buf);
- cre->buf = NULL;
- cre->buflen = 0;
- }
(*bufev->errorcb)(bufev, what, bufev->cbarg);
}
-struct tls_ticket *
-relay_get_ticket_key(unsigned char *keyname)
-{
- if (keyname) {
- if (timingsafe_memcmp(keyname,
- env->sc_tls_ticket_bak.tt_key_name,
- sizeof(env->sc_tls_ticket_bak.tt_key_name)) == 0)
- return &env->sc_tls_ticket_bak;
- if (timingsafe_memcmp(keyname,
- env->sc_tls_ticket.tt_key_name,
- sizeof(env->sc_tls_ticket.tt_key_name)) == 0)
- return &env->sc_tls_ticket;
- return NULL;
- }
- return &env->sc_tls_ticket;
-}
-
-int
-relay_tls_session_ticket(SSL *ssl, unsigned char *keyname, unsigned char *iv,
- EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int mode)
-{
- struct tls_ticket *key;
-
- if (mode == 1) {
- /* create new session */
- key = relay_get_ticket_key(NULL);
- memcpy(keyname, key->tt_key_name, sizeof(key->tt_key_name));
- arc4random_buf(iv, EVP_MAX_IV_LENGTH);
- EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL,
- key->tt_aes_key, iv);
- HMAC_Init_ex(hctx, key->tt_hmac_key, sizeof(key->tt_hmac_key),
- EVP_sha256(), NULL);
- return 0;
- } else {
- /* get key by name */
- key = relay_get_ticket_key(keyname);
- if (!key)
- return 0;
-
- EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL,
- key->tt_aes_key, iv);
- HMAC_Init_ex(hctx, key->tt_hmac_key, sizeof(key->tt_hmac_key),
- EVP_sha256(), NULL);
-
- /* time to renew the ticket? */
- if (key->tt_backup) {
- return 2;
- }
- return 1;
- }
-}
-
int
relay_bufferevent_add(struct event *ev, int timeout)
{
diff --git a/usr.sbin/relayd/relay_http.c b/usr.sbin/relayd/relay_http.c
index 4082ab35af0..7141fcf4bcc 100644
--- a/usr.sbin/relayd/relay_http.c
+++ b/usr.sbin/relayd/relay_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay_http.c,v 1.64 2017/03/10 21:04:35 reyk Exp $ */
+/* $OpenBSD: relay_http.c,v 1.65 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
@@ -715,11 +715,6 @@ relay_reset_http(struct ctl_relay_event *cre)
struct http_descriptor *desc = cre->desc;
relay_httpdesc_free(desc);
- if (cre->buf != NULL) {
- free(cre->buf);
- cre->buf = NULL;
- cre->buflen = 0;
- }
desc->http_method = 0;
desc->http_chunked = 0;
cre->headerlen = 0;
diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c
index 53996b21b30..e3b443eb42d 100644
--- a/usr.sbin/relayd/relayd.c
+++ b/usr.sbin/relayd/relayd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.c,v 1.166 2017/05/06 19:44:53 fcambus Exp $ */
+/* $OpenBSD: relayd.c,v 1.167 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2007 - 2016 Reyk Floeter <reyk@openbsd.org>
@@ -43,7 +43,7 @@
#include <sha1.h>
#include <md5.h>
-#include <openssl/ssl.h>
+#include <tls.h>
#include "relayd.h"
@@ -530,12 +530,11 @@ purge_table(struct relayd *env, struct tablelist *head, struct table *table)
close(host->cte.s);
}
ibuf_free(host->cte.buf);
- SSL_free(host->cte.ssl);
+ tls_free(host->cte.tls);
free(host);
}
free(table->sendbuf);
- if (table->conf.flags & F_TLS)
- SSL_CTX_free(table->ssl_ctx);
+ tls_config_free(table->tls_cfg);
if (head != NULL)
TAILQ_REMOVE(head, table, entry);
@@ -578,10 +577,6 @@ purge_relay(struct relayd *env, struct relay *rlay)
purge_key(&rlay->rl_tls_ca, rlay->rl_conf.tls_ca_len);
purge_key(&rlay->rl_tls_cakey, rlay->rl_conf.tls_cakey_len);
- if (rlay->rl_tls_x509 != NULL) {
- X509_free(rlay->rl_tls_x509);
- rlay->rl_tls_x509 = NULL;
- }
if (rlay->rl_tls_pkey != NULL) {
EVP_PKEY_free(rlay->rl_tls_pkey);
rlay->rl_tls_pkey = NULL;
@@ -595,7 +590,9 @@ purge_relay(struct relayd *env, struct relay *rlay)
rlay->rl_tls_capkey = NULL;
}
- SSL_CTX_free(rlay->rl_ssl_ctx);
+ tls_free(rlay->rl_tls_ctx);
+ tls_config_free(rlay->rl_tls_cfg);
+ tls_config_free(rlay->rl_tls_client_cfg);
while ((rlt = TAILQ_FIRST(&rlay->rl_tables))) {
TAILQ_REMOVE(&rlay->rl_tables, rlt, rlt_entry);
@@ -1166,18 +1163,18 @@ relay_findbyaddr(struct relayd *env, struct relay_config *rc)
}
EVP_PKEY *
-pkey_find(struct relayd *env, objid_t id)
+pkey_find(struct relayd *env, char * hash)
{
struct ca_pkey *pkey;
TAILQ_FOREACH(pkey, env->sc_pkeys, pkey_entry)
- if (pkey->pkey_id == id)
+ if (strcmp(hash, pkey->pkey_hash) == 0)
return (pkey->pkey);
return (NULL);
}
struct ca_pkey *
-pkey_add(struct relayd *env, EVP_PKEY *pkey, objid_t id)
+pkey_add(struct relayd *env, EVP_PKEY *pkey, char *hash)
{
struct ca_pkey *ca_pkey;
@@ -1188,8 +1185,10 @@ pkey_add(struct relayd *env, EVP_PKEY *pkey, objid_t id)
return (NULL);
ca_pkey->pkey = pkey;
- ca_pkey->pkey_id = id;
-
+ if (strlcpy(ca_pkey->pkey_hash, hash, sizeof(ca_pkey->pkey_hash)) >=
+ sizeof(ca_pkey->pkey_hash))
+ return (NULL);
+
TAILQ_INSERT_TAIL(env->sc_pkeys, ca_pkey, pkey_entry);
return (ca_pkey);
@@ -1638,20 +1637,18 @@ parent_tls_ticket_rekey(int fd, short events, void *arg)
static struct event rekeyev;
struct relayd *env = arg;
struct timeval tv;
- struct tls_ticket key;
+ struct relay_ticket_key key;
log_debug("relayd_tls_ticket_rekey: rekeying tickets");
- arc4random_buf(key.tt_key_name, sizeof(key.tt_key_name));
- arc4random_buf(key.tt_hmac_key, sizeof(key.tt_hmac_key));
- arc4random_buf(key.tt_aes_key, sizeof(key.tt_aes_key));
- key.tt_backup = 0;
+ key.tt_keyrev = arc4random();
+ arc4random_buf(key.tt_key, sizeof(key.tt_key));
proc_compose_imsg(env->sc_ps, PROC_RELAY, -1, IMSG_TLSTICKET_REKEY,
-1, -1, &key, sizeof(key));
evtimer_set(&rekeyev, parent_tls_ticket_rekey, env);
timerclear(&tv);
- tv.tv_sec = TLS_TICKET_REKEY_TIME;
+ tv.tv_sec = TLS_SESSION_LIFETIME / 4;
evtimer_add(&rekeyev, &tv);
}
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index fc24c975950..58f5a707963 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.239 2017/02/02 08:24:16 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.240 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
@@ -37,6 +37,7 @@
#include <imsg.h>
#include <openssl/ssl.h>
+#include <tls.h>
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
@@ -61,6 +62,7 @@
#define MAX_NAME_SIZE 64
#define SRV_MAX_VIRTS 16
#define TLS_NAME_SIZE 512
+#define TLS_CERT_HASH_SIZE 128
#define RELAY_MAX_PREFETCH 256
#define RELAY_MIN_PREFETCHED 32
@@ -166,7 +168,7 @@ struct ctl_tcp_event {
int (*validate_read)(struct ctl_tcp_event *);
int (*validate_close)(struct ctl_tcp_event *);
- SSL *ssl; /* libssl object */
+ struct tls *tls;
};
enum direction {
@@ -192,9 +194,11 @@ struct ctl_relay_event {
struct ctl_relay_event *dst;
struct rsession *con;
- SSL *ssl; /* libssl object */
+ struct tls *tls;
+ struct tls_config *tls_cfg;
- X509 *tlscert;
+ uint8_t *tlscert;
+ size_t tlscert_len;
off_t splicelen;
off_t toread;
@@ -205,9 +209,6 @@ struct ctl_relay_event {
enum relay_state state;
enum direction dir;
- u_int8_t *buf;
- int buflen;
-
/* protocol-specific descriptor */
void *desc;
};
@@ -243,7 +244,7 @@ struct ctl_bindany {
};
struct ctl_keyop {
- objid_t cko_id;
+ char cko_hash[TLS_CERT_HASH_SIZE];
int cko_proc;
int cko_flen;
int cko_tlen;
@@ -496,7 +497,7 @@ struct table {
int up;
int skipped;
struct hostlist hosts;
- SSL_CTX *ssl_ctx; /* libssl context */
+ struct tls_config *tls_cfg;
char *sendbuf;
};
TAILQ_HEAD(tablelist, table);
@@ -680,20 +681,14 @@ TAILQ_HEAD(relay_rules, relay_rule);
"\06cipher-server-preference\07client-renegotiation"
#define TLSCIPHERS_DEFAULT "HIGH:!aNULL"
-#define TLSECDHCURVE_DEFAULT NID_X9_62_prime256v1
-
-#define TLSDHPARAMS_NONE 0
-#define TLSDHPARAMS_DEFAULT 0
-#define TLSDHPARAMS_MIN 1024
+#define TLSECDHCURVE_DEFAULT "auto"
+#define TLSDHPARAM_DEFAULT "none"
-struct tls_ticket {
- /* The key, aes key and hmac key must be 16 bytes / 128bits */
- unsigned char tt_key_name[16];
- unsigned char tt_aes_key[16];
- unsigned char tt_hmac_key[16];
- int tt_backup;
+struct relay_ticket_key {
+ uint32_t tt_keyrev;
+ unsigned char tt_key[TLS_TICKET_KEY_SIZE];
};
-#define TLS_TICKET_REKEY_TIME (2 * 3600)
+#define TLS_SESSION_LIFETIME (2 * 3600)
struct protocol {
objid_t id;
@@ -705,8 +700,8 @@ struct protocol {
u_int8_t tcpipminttl;
u_int8_t tlsflags;
char tlsciphers[768];
- int tlsdhparams;
- int tlsecdhcurve;
+ char tlsdhparams[128];
+ char tlsecdhcurve[128];
char tlsca[PATH_MAX];
char tlscacert[PATH_MAX];
char tlscakey[PATH_MAX];
@@ -742,7 +737,7 @@ struct relay_table {
TAILQ_HEAD(relaytables, relay_table);
struct ca_pkey {
- objid_t pkey_id;
+ char pkey_hash[TLS_CERT_HASH_SIZE];
EVP_PKEY *pkey;
TAILQ_ENTRY(ca_pkey) pkey_entry;
};
@@ -788,10 +783,11 @@ struct relay {
struct event rl_ev;
struct event rl_evt;
- SSL_CTX *rl_ssl_ctx; /* libssl context */
+ struct tls_config *rl_tls_cfg;
+ struct tls_config *rl_tls_client_cfg;
+ struct tls *rl_tls_ctx;
char *rl_tls_cert;
- X509 *rl_tls_x509;
char *rl_tls_key;
EVP_PKEY *rl_tls_pkey;
char *rl_tls_ca;
@@ -1092,11 +1088,10 @@ struct relayd {
struct ctl_icmp_event sc_icmp6_send;
struct ctl_icmp_event sc_icmp6_recv;
+ struct relay_ticket_key sc_ticket;
+
struct privsep *sc_ps;
int sc_reload;
-
- struct tls_ticket sc_tls_ticket;
- struct tls_ticket sc_tls_ticket_bak;
};
#define RELAYD_OPT_VERBOSE 0x01
@@ -1237,6 +1232,9 @@ void check_icmp(struct relayd *, struct timeval *);
/* check_tcp.c */
void check_tcp(struct ctl_tcp_event *);
+/* check_tls.c */
+void check_tls(struct ctl_tcp_event *);
+
/* check_script.c */
void check_script(struct relayd *, struct host *);
void script_done(struct relayd *, struct ctl_script *);
@@ -1244,15 +1242,11 @@ int script_exec(struct relayd *, struct ctl_script *);
/* ssl.c */
void ssl_init(struct relayd *);
-void ssl_transaction(struct ctl_tcp_event *);
-SSL_CTX *ssl_ctx_create(struct relayd *);
-void ssl_error(const char *, const char *);
char *ssl_load_key(struct relayd *, const char *, off_t *, char *);
-X509 *ssl_update_certificate(X509 *, EVP_PKEY *, EVP_PKEY *, X509 *);
-int ssl_load_pkey(const void *, size_t, char *, off_t,
- X509 **, EVP_PKEY **);
-int ssl_ctx_fake_private_key(SSL_CTX *, const void *, size_t,
- char *, off_t, X509 **, EVP_PKEY **);
+uint8_t *ssl_update_certificate(const uint8_t *, size_t, EVP_PKEY *,
+ EVP_PKEY *, X509 *, size_t *);
+int ssl_load_pkey(void *, char *, off_t, X509 **, EVP_PKEY **);
+int ssl_ctx_fake_private_key(char *, off_t, const char **);
/* ca.c */
void ca(struct privsep *, struct privsep_proc *);
@@ -1276,8 +1270,8 @@ struct protocol *proto_find(struct relayd *, objid_t);
struct rsession *session_find(struct relayd *, objid_t);
struct relay *relay_findbyname(struct relayd *, const char *);
struct relay *relay_findbyaddr(struct relayd *, struct relay_config *);
-EVP_PKEY *pkey_find(struct relayd *, objid_t);
-struct ca_pkey *pkey_add(struct relayd *, EVP_PKEY *, objid_t);
+EVP_PKEY *pkey_find(struct relayd *, char *hash);
+struct ca_pkey *pkey_add(struct relayd *, EVP_PKEY *, char *hash);
int expand_string(char *, size_t, const char *, const char *);
void translate_string(char *);
void purge_key(char **, off_t);
diff --git a/usr.sbin/relayd/ssl.c b/usr.sbin/relayd/ssl.c
index f5dad7e36f0..1ff423f5866 100644
--- a/usr.sbin/relayd/ssl.c
+++ b/usr.sbin/relayd/ssl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl.c,v 1.31 2017/01/09 14:49:21 reyk Exp $ */
+/* $OpenBSD: ssl.c,v 1.32 2017/05/27 08:33:25 claudio Exp $ */
/*
* Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -18,12 +18,9 @@
*/
#include <sys/types.h>
-#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <event.h>
#include <unistd.h>
#include <string.h>
#include <imsg.h>
@@ -33,208 +30,11 @@
#include <openssl/engine.h>
#include "relayd.h"
+#include "boguskeys.h"
-void ssl_read(int, short, void *);
-void ssl_write(int, short, void *);
-void ssl_connect(int, short, void *);
-void ssl_cleanup(struct ctl_tcp_event *);
int ssl_password_cb(char *, int, int, void *);
void
-ssl_read(int s, short event, void *arg)
-{
- char rbuf[SMALL_READ_BUF_SIZE];
- struct ctl_tcp_event *cte = arg;
- int retry_flag = EV_READ;
- int tls_err = 0;
- int ret;
-
- if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- ssl_cleanup(cte);
- hce_notify_done(cte->host, HCE_TLS_READ_TIMEOUT);
- return;
- }
-
- bzero(rbuf, sizeof(rbuf));
-
- ret = SSL_read(cte->ssl, rbuf, sizeof(rbuf));
- if (ret <= 0) {
- tls_err = SSL_get_error(cte->ssl, ret);
- switch (tls_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- case SSL_ERROR_ZERO_RETURN: /* FALLTHROUGH */
- case SSL_ERROR_SYSCALL:
- if (ret == 0) {
- cte->host->up = HOST_DOWN;
- (void)cte->validate_close(cte);
- ssl_cleanup(cte);
- hce_notify_done(cte->host, cte->host->he);
- return;
- }
- /* FALLTHROUGH */
- default:
- cte->host->up = HOST_DOWN;
- ssl_error(cte->host->conf.name, "cannot read");
- ssl_cleanup(cte);
- hce_notify_done(cte->host, HCE_TLS_READ_ERROR);
- break;
- }
- return;
- }
- if (ibuf_add(cte->buf, rbuf, ret) == -1)
- fatal("ssl_read: buf_add error");
- if (cte->validate_read != NULL) {
- if (cte->validate_read(cte) != 0)
- goto retry;
-
- ssl_cleanup(cte);
- hce_notify_done(cte->host, cte->host->he);
- return;
- }
-
-retry:
- event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, ssl_read,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
-}
-
-void
-ssl_write(int s, short event, void *arg)
-{
- struct ctl_tcp_event *cte = arg;
- int retry_flag = EV_WRITE;
- int tls_err = 0;
- int len;
- int ret;
-
- if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- ssl_cleanup(cte);
- hce_notify_done(cte->host, HCE_TLS_WRITE_TIMEOUT);
- return;
- }
-
- len = strlen(cte->table->sendbuf);
-
- ret = SSL_write(cte->ssl, cte->table->sendbuf, len);
- if (ret <= 0) {
- tls_err = SSL_get_error(cte->ssl, ret);
- switch (tls_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- default:
- cte->host->up = HOST_DOWN;
- ssl_error(cte->host->conf.name, "cannot write");
- ssl_cleanup(cte);
- hce_notify_done(cte->host, HCE_TLS_WRITE_ERROR);
- return;
- }
- }
- if ((cte->buf = ibuf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
- fatalx("ssl_write: cannot create dynamic buffer");
-
- event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, ssl_read,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
-retry:
- event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, ssl_write,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-void
-ssl_connect(int s, short event, void *arg)
-{
- struct ctl_tcp_event *cte = arg;
- int retry_flag = 0;
- int tls_err = 0;
- int ret;
-
- if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- hce_notify_done(cte->host, HCE_TLS_CONNECT_TIMEOUT);
- ssl_cleanup(cte);
- return;
- }
-
- ret = SSL_connect(cte->ssl);
- if (ret <= 0) {
- tls_err = SSL_get_error(cte->ssl, ret);
- switch (tls_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- default:
- cte->host->up = HOST_DOWN;
- ssl_error(cte->host->conf.name, "cannot connect");
- hce_notify_done(cte->host, HCE_TLS_CONNECT_FAIL);
- ssl_cleanup(cte);
- return;
- }
- }
-
- if (cte->table->conf.check == CHECK_TCP) {
- cte->host->up = HOST_UP;
- hce_notify_done(cte->host, HCE_TLS_CONNECT_OK);
- ssl_cleanup(cte);
- return;
- }
- if (cte->table->sendbuf != NULL) {
- event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE, ssl_write,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
- }
-
- if ((cte->buf = ibuf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
- fatalx("ssl_connect: cannot create dynamic buffer");
- event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_READ, ssl_read,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
-
-retry:
- event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, ssl_connect,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-void
-ssl_cleanup(struct ctl_tcp_event *cte)
-{
- close(cte->s);
- if (cte->ssl != NULL) {
- SSL_shutdown(cte->ssl);
- SSL_clear(cte->ssl);
- }
- ibuf_free(cte->buf);
- cte->buf = NULL;
-}
-
-void
-ssl_error(const char *where, const char *what)
-{
- char errbuf[128];
- unsigned long code;
-
- if (log_getverbose() < 2)
- return;
- for (; (code = ERR_get_error()) != 0 ;) {
- ERR_error_string_n(code, errbuf, sizeof(errbuf));
- log_debug("SSL library error: %s: %s: %s", where, what, errbuf);
- }
-}
-
-void
ssl_init(struct relayd *env)
{
static int initialized = 0;
@@ -252,43 +52,6 @@ ssl_init(struct relayd *env)
initialized = 1;
}
-void
-ssl_transaction(struct ctl_tcp_event *cte)
-{
- if (cte->ssl == NULL) {
- cte->ssl = SSL_new(cte->table->ssl_ctx);
- if (cte->ssl == NULL) {
- ssl_error(cte->host->conf.name, "cannot create object");
- fatal("cannot create SSL object");
- }
- }
-
- if (SSL_set_fd(cte->ssl, cte->s) == 0) {
- cte->host->up = HOST_UNKNOWN;
- ssl_error(cte->host->conf.name, "cannot set fd");
- ssl_cleanup(cte);
- hce_notify_done(cte->host, HCE_TLS_CONNECT_ERROR);
- return;
- }
- SSL_set_connect_state(cte->ssl);
-
- event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE, ssl_connect,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-SSL_CTX *
-ssl_ctx_create(struct relayd *env)
-{
- SSL_CTX *ctx;
-
- ctx = SSL_CTX_new(SSLv23_client_method());
- if (ctx == NULL) {
- ssl_error("ssl_ctx_create", "cannot create context");
- fatal("could not create SSL context");
- }
- return (ctx);
-}
-
int
ssl_password_cb(char *buf, int size, int rwflag, void *u)
{
@@ -345,8 +108,6 @@ ssl_load_key(struct relayd *env, const char *name, off_t *len, char *pass)
return (buf);
fail:
- ssl_error(__func__, name);
-
free(buf);
if (bio != NULL)
BIO_free_all(bio);
@@ -355,21 +116,45 @@ ssl_load_key(struct relayd *env, const char *name, off_t *len, char *pass)
return (NULL);
}
-X509 *
-ssl_update_certificate(X509 *oldcert, EVP_PKEY *pkey, EVP_PKEY *capkey,
- X509 *cacert)
+uint8_t *
+ssl_update_certificate(const uint8_t *oldcert, size_t oldlen, EVP_PKEY *pkey,
+ EVP_PKEY *capkey, X509 *cacert, size_t *newlen)
{
char name[2][TLS_NAME_SIZE];
+ BIO *in, *out = NULL;
+ BUF_MEM *bptr = NULL;
X509 *cert = NULL;
+ uint8_t *newcert = NULL, *foo = NULL;
+
+ /* XXX BIO_new_mem_buf is not using const so work around this */
+ if ((foo = malloc(oldlen)) == NULL) {
+ log_warn("%s: malloc", __func__);
+ return (NULL);
+ }
+ memcpy(foo, oldcert, oldlen);
+
+ if ((in = BIO_new_mem_buf(foo, oldlen)) == NULL) {
+ log_warnx("%s: BIO_new_mem_buf failed", __func__);
+ goto done;
+ }
+
+ if ((cert = PEM_read_bio_X509(in, NULL,
+ ssl_password_cb, NULL)) == NULL) {
+ log_warnx("%s: PEM_read_bio_X509 failed", __func__);
+ goto done;
+ }
+
+ BIO_free(in);
+ in = NULL;
name[0][0] = name[1][0] = '\0';
- if (!X509_NAME_oneline(X509_get_subject_name(oldcert),
+ if (!X509_NAME_oneline(X509_get_subject_name(cert),
name[0], sizeof(name[0])) ||
- !X509_NAME_oneline(X509_get_issuer_name(oldcert),
+ !X509_NAME_oneline(X509_get_issuer_name(cert),
name[1], sizeof(name[1])))
goto done;
- if ((cert = X509_dup(oldcert)) == NULL)
+ if ((cert = X509_dup(cert)) == NULL)
goto done;
/* Update certificate key and use our CA as the issuer */
@@ -377,9 +162,9 @@ ssl_update_certificate(X509 *oldcert, EVP_PKEY *pkey, EVP_PKEY *capkey,
X509_set_issuer_name(cert, X509_get_subject_name(cacert));
/* Sign with our CA */
- if (!X509_sign(cert, capkey, EVP_sha1())) {
- X509_free(cert);
- cert = NULL;
+ if (!X509_sign(cert, capkey, EVP_sha256())) {
+ log_warnx("%s: X509_sign failed", __func__);
+ goto done;
}
#if DEBUG_CERT
@@ -390,15 +175,37 @@ ssl_update_certificate(X509 *oldcert, EVP_PKEY *pkey, EVP_PKEY *capkey,
#endif
#endif
- done:
- if (cert == NULL)
- ssl_error(__func__, name[0]);
+ /* write cert as PEM file */
+ out = BIO_new(BIO_s_mem());
+ if (out == NULL) {
+ log_warnx("%s: BIO_new failed", __func__);
+ goto done;
+ }
+ if (!PEM_write_bio_X509(out, cert)) {
+ log_warnx("%s: PEM_write_bio_X509 failed", __func__);
+ goto done;
+ }
+ BIO_get_mem_ptr(out, &bptr);
+ if ((newcert = malloc(bptr->length)) == NULL) {
+ log_warn("%s: malloc", __func__);
+ goto done;
+ }
+ memcpy(newcert, bptr->data, bptr->length);
+ *newlen = bptr->length;
- return (cert);
+done:
+ free(foo);
+ if (in)
+ BIO_free(in);
+ if (out)
+ BIO_free(out);
+ if (cert)
+ X509_free(cert);
+ return (newcert);
}
int
-ssl_load_pkey(const void *data, size_t datalen, char *buf, off_t len,
+ssl_load_pkey(void *data, char *buf, off_t len,
X509 **x509ptr, EVP_PKEY **pkeyptr)
{
BIO *in;
@@ -408,36 +215,38 @@ ssl_load_pkey(const void *data, size_t datalen, char *buf, off_t len,
void *exdata = NULL;
if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_BUF_LIB);
+ log_warnx("%s: BIO_new_mem_buf failed", __func__);
return (0);
}
if ((x509 = PEM_read_bio_X509(in, NULL,
ssl_password_cb, NULL)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_PEM_LIB);
+ log_warnx("%s: PEM_read_bio_X509 failed", __func__);
goto fail;
}
if ((pkey = X509_get_pubkey(x509)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_X509_LIB);
+ log_warnx("%s: X509_get_pubkey failed", __func__);
goto fail;
}
BIO_free(in);
- if (data != NULL && datalen) {
- if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL ||
- (exdata = malloc(datalen)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_EVP_LIB);
+ if (data != NULL) {
+ if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
+ log_warnx("%s: failed to extract RSA", __func__);
goto fail;
}
- memcpy(exdata, data, datalen);
- RSA_set_ex_data(rsa, 0, exdata);
+ RSA_set_ex_data(rsa, 0, data);
RSA_free(rsa); /* dereference, will be cleaned up with pkey */
}
- *x509ptr = x509;
+ if (x509ptr != NULL)
+ *x509ptr = x509;
+ else
+ X509_free(x509);
+
*pkeyptr = pkey;
return (1);
@@ -456,37 +265,63 @@ ssl_load_pkey(const void *data, size_t datalen, char *buf, off_t len,
return (0);
}
+/*
+ * This function is a horrible hack but for RSA privsep to work a private key
+ * with correct size needs to be loaded into the tls config.
+ */
int
-ssl_ctx_fake_private_key(SSL_CTX *ctx, const void *data, size_t datalen,
- char *buf, off_t len, X509 **x509ptr, EVP_PKEY **pkeyptr)
+ssl_ctx_fake_private_key(char *buf, off_t len, const char **fake_key)
{
- int ret = 0;
+ BIO *in;
EVP_PKEY *pkey = NULL;
X509 *x509 = NULL;
+ int ret = -1, keylen;
- if (!ssl_load_pkey(data, datalen, buf, len, &x509, &pkey))
+ if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
+ log_warnx("%s: BIO_new_mem_buf failed", __func__);
return (0);
+ }
- /*
- * Use the public key as the "private" key - the secret key
- * parameters are hidden in an extra process that will be
- * contacted by the RSA engine. The SSL/TLS library needs at
- * least the public key parameters in the current process.
- */
- ret = SSL_CTX_use_PrivateKey(ctx, pkey);
- if (!ret)
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_SSL_LIB);
+ if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) {
+ log_warnx("%s: PEM_read_bio_X509 failed", __func__);
+ goto fail;
+ }
- if (pkeyptr != NULL)
- *pkeyptr = pkey;
- else if (pkey != NULL)
- EVP_PKEY_free(pkey);
+ if ((pkey = X509_get_pubkey(x509)) == NULL) {
+ log_warnx("%s: X509_get_pubkey failed", __func__);
+ goto fail;
+ }
- if (x509ptr != NULL)
- *x509ptr = x509;
- else if (x509 != NULL)
- X509_free(x509);
+ keylen = EVP_PKEY_size(pkey) * 8;
+ switch(keylen) {
+ case 1024:
+ *fake_key = bogus_1024;
+ ret = sizeof(bogus_1024);
+ break;
+ case 2048:
+ *fake_key = bogus_2048;
+ ret = sizeof(bogus_2048);
+ break;
+ case 4096:
+ *fake_key = bogus_4096;
+ ret = sizeof(bogus_4096);
+ break;
+ case 8192:
+ *fake_key = bogus_8192;
+ ret = sizeof(bogus_8192);
+ break;
+ default:
+ log_warnx("%s: key size %d not support", __func__, keylen);
+ ret = -1;
+ break;
+ }
+fail:
+ BIO_free(in);
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ if (x509 != NULL)
+ X509_free(x509);
+
return (ret);
}
-