diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2017-05-27 08:33:26 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2017-05-27 08:33:26 +0000 |
commit | 460b984bd245edf6c33f3e2a4f4c1f75cde903d3 (patch) | |
tree | 344c5c23e40425bf4eff1021ea92cf67231e6a51 /usr.sbin/relayd | |
parent | 1b5fd98198f2adb6d2d152c115dca82f396d1c11 (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/Makefile | 8 | ||||
-rw-r--r-- | usr.sbin/relayd/boguskeys.h | 200 | ||||
-rw-r--r-- | usr.sbin/relayd/ca.c | 88 | ||||
-rw-r--r-- | usr.sbin/relayd/check_tcp.c | 4 | ||||
-rw-r--r-- | usr.sbin/relayd/check_tls.c | 226 | ||||
-rw-r--r-- | usr.sbin/relayd/config.c | 12 | ||||
-rw-r--r-- | usr.sbin/relayd/hce.c | 8 | ||||
-rw-r--r-- | usr.sbin/relayd/parse.y | 100 | ||||
-rw-r--r-- | usr.sbin/relayd/relay.c | 813 | ||||
-rw-r--r-- | usr.sbin/relayd/relay_http.c | 7 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.c | 39 | ||||
-rw-r--r-- | usr.sbin/relayd/relayd.h | 72 | ||||
-rw-r--r-- | usr.sbin/relayd/ssl.c | 413 |
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); } - |