diff options
author | 2015-07-15 16:00:39 +0000 | |
---|---|---|
committer | 2015-07-15 16:00:39 +0000 | |
commit | 6f8bdc862b4eba8f72d51aae2c7b53ff1f510f55 (patch) | |
tree | 71221807b09baaa31ea27a5fdbf4d02fd0a46308 | |
parent | typo in manual page. (diff) | |
download | wireguard-openbsd-6f8bdc862b4eba8f72d51aae2c7b53ff1f510f55.tar.xz wireguard-openbsd-6f8bdc862b4eba8f72d51aae2c7b53ff1f510f55.zip |
Send the TLS certificate and key via separate imsgs, rather than
including them in the IMSG_CFG_SERVER imsg. This allows the certificate
and key to each be almost 16KB (the maximum size for an imsg), rather than
having a combined total of less than 16KB (which can be reached with large
keys, certificate bundles or by including text versions of certificates).
ok reyk@
-rw-r--r-- | usr.sbin/httpd/config.c | 148 | ||||
-rw-r--r-- | usr.sbin/httpd/httpd.h | 15 | ||||
-rw-r--r-- | usr.sbin/httpd/server.c | 5 |
3 files changed, 142 insertions, 26 deletions
diff --git a/usr.sbin/httpd/config.c b/usr.sbin/httpd/config.c index bd4dab2d5e0..3c889906410 100644 --- a/usr.sbin/httpd/config.c +++ b/usr.sbin/httpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.38 2015/07/15 14:39:13 jsing Exp $ */ +/* $OpenBSD: config.c,v 1.39 2015/07/15 16:00:39 jsing Exp $ */ /* * Copyright (c) 2011 - 2015 Reyk Floeter <reyk@openbsd.org> @@ -193,14 +193,6 @@ config_setserver(struct httpd *env, struct server *srv) iov[c].iov_base = srv->srv_conf.return_uri; iov[c++].iov_len = srv->srv_conf.return_uri_len; } - if (srv->srv_conf.tls_cert_len != 0) { - iov[c].iov_base = srv->srv_conf.tls_cert; - iov[c++].iov_len = srv->srv_conf.tls_cert_len; - } - if (srv->srv_conf.tls_key_len != 0) { - iov[c].iov_base = srv->srv_conf.tls_key; - iov[c++].iov_len = srv->srv_conf.tls_key_len; - } if (id == PROC_SERVER && (srv->srv_conf.flags & SRVFLAG_LOCATION) == 0) { @@ -220,6 +212,9 @@ config_setserver(struct httpd *env, struct server *srv) return (-1); } } + + /* Configure TLS if necessary. */ + config_settls(env, srv); } else { if (proc_composev_imsg(ps, id, -1, IMSG_CFG_SERVER, -1, iov, c) != 0) { @@ -235,6 +230,72 @@ config_setserver(struct httpd *env, struct server *srv) } int +config_settls(struct httpd *env, struct server *srv) +{ + struct privsep *ps = env->sc_ps; + struct tls_config tls; + struct iovec iov[2]; + size_t c; + + if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0) + return (0); + + log_debug("%s: configuring TLS for %s", __func__, srv->srv_conf.name); + + if (srv->srv_conf.tls_cert_len != 0) { + DPRINTF("%s: sending TLS cert \"%s[%u]\" to %s fd %d", __func__, + srv->srv_conf.name, srv->srv_conf.id, + ps->ps_title[PROC_SERVER], srv->srv_s); + + memset(&tls, 0, sizeof(tls)); + tls.id = srv->srv_conf.id; + tls.port = srv->srv_conf.port; + memcpy(&tls.ss, &srv->srv_conf.ss, sizeof(tls.ss)); + tls.tls_cert_len = srv->srv_conf.tls_cert_len; + + c = 0; + iov[c].iov_base = &tls; + iov[c++].iov_len = sizeof(tls); + iov[c].iov_base = srv->srv_conf.tls_cert; + iov[c++].iov_len = srv->srv_conf.tls_cert_len; + + if (proc_composev_imsg(ps, PROC_SERVER, -1, IMSG_CFG_TLS, -1, + iov, c) != 0) { + log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " + "`%s'", __func__, srv->srv_conf.name); + return (-1); + } + } + + if (srv->srv_conf.tls_key_len != 0) { + DPRINTF("%s: sending TLS key \"%s[%u]\" to %s fd %d", __func__, + srv->srv_conf.name, srv->srv_conf.id, + ps->ps_title[PROC_SERVER], srv->srv_s); + + memset(&tls, 0, sizeof(tls)); + tls.id = srv->srv_conf.id; + tls.port = srv->srv_conf.port; + memcpy(&tls.ss, &srv->srv_conf.ss, sizeof(tls.ss)); + tls.tls_key_len = srv->srv_conf.tls_key_len; + + c = 0; + iov[c].iov_base = &tls; + iov[c++].iov_len = sizeof(tls); + iov[c].iov_base = srv->srv_conf.tls_key; + iov[c++].iov_len = srv->srv_conf.tls_key_len; + + if (proc_composev_imsg(ps, PROC_SERVER, -1, IMSG_CFG_TLS, -1, + iov, c) != 0) { + log_warn("%s: failed to compose IMSG_CFG_TLS imsg for " + "`%s'", __func__, srv->srv_conf.name); + return (-1); + } + } + + return (0); +} + +int config_getserver_auth(struct httpd *env, struct server_config *srv_conf) { struct privsep *ps = env->sc_ps; @@ -422,9 +483,7 @@ config_getserver(struct httpd *env, struct imsg *imsg) /* Reset these variables to avoid free'ing invalid pointers */ serverconfig_reset(&srv_conf); - if ((IMSG_DATA_SIZE(imsg) - s) < - (srv_conf.tls_cert_len + srv_conf.tls_key_len + - srv_conf.return_uri_len)) { + if ((IMSG_DATA_SIZE(imsg) - s) < (size_t)srv_conf.return_uri_len) { log_debug("%s: invalid message length", __func__); goto fail; } @@ -475,18 +534,6 @@ config_getserver(struct httpd *env, struct imsg *imsg) goto fail; s += srv->srv_conf.return_uri_len; } - if (srv->srv_conf.tls_cert_len != 0) { - if ((srv->srv_conf.tls_cert = get_data(p + s, - srv->srv_conf.tls_cert_len)) == NULL) - goto fail; - s += srv->srv_conf.tls_cert_len; - } - if (srv->srv_conf.tls_key_len != 0) { - if ((srv->srv_conf.tls_key = get_data(p + s, - srv->srv_conf.tls_key_len)) == NULL) - goto fail; - s += srv->srv_conf.tls_key_len; - } return (0); @@ -501,6 +548,59 @@ config_getserver(struct httpd *env, struct imsg *imsg) } int +config_gettls(struct httpd *env, struct imsg *imsg) +{ +#ifdef DEBUG + struct privsep *ps = env->sc_ps; +#endif + struct server *srv = NULL; + struct tls_config tls_conf; + u_int8_t *p = imsg->data; + size_t s; + + IMSG_SIZE_CHECK(imsg, &tls_conf); + memcpy(&tls_conf, p, sizeof(tls_conf)); + s = sizeof(tls_conf); + + if ((IMSG_DATA_SIZE(imsg) - s) < + (tls_conf.tls_cert_len + tls_conf.tls_key_len)) { + log_debug("%s: invalid message length", __func__); + goto fail; + } + + /* Find server with matching listening socket. */ + if ((srv = server_byaddr((struct sockaddr *) + &tls_conf.ss, tls_conf.port)) == NULL) { + log_debug("%s: server not found", __func__); + goto fail; + } + + DPRINTF("%s: %s %d TLS configuration \"%s[%u]\"", __func__, + ps->ps_title[privsep_process], ps->ps_instance, + srv->srv_conf.name, srv->srv_conf.id); + + if (tls_conf.tls_cert_len != 0) { + srv->srv_conf.tls_cert_len = tls_conf.tls_cert_len; + if ((srv->srv_conf.tls_cert = get_data(p + s, + tls_conf.tls_cert_len)) == NULL) + goto fail; + s += tls_conf.tls_cert_len; + } + if (tls_conf.tls_key_len != 0) { + srv->srv_conf.tls_key_len = tls_conf.tls_key_len; + if ((srv->srv_conf.tls_key = get_data(p + s, + tls_conf.tls_key_len)) == NULL) + goto fail; + s += tls_conf.tls_key_len; + } + + return (0); + + fail: + return (-1); +} + +int config_setmedia(struct httpd *env, struct media_type *media) { struct privsep *ps = env->sc_ps; diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h index 20d75a78334..664f17c6764 100644 --- a/usr.sbin/httpd/httpd.h +++ b/usr.sbin/httpd/httpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.h,v 1.84 2015/06/23 15:23:14 reyk Exp $ */ +/* $OpenBSD: httpd.h,v 1.85 2015/07/15 16:00:39 jsing Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org> @@ -201,6 +201,7 @@ enum imsg_type { IMSG_CTL_START, IMSG_CTL_REOPEN, IMSG_CFG_SERVER, + IMSG_CFG_TLS, IMSG_CFG_MEDIA, IMSG_CFG_AUTH, IMSG_CFG_DONE, @@ -442,6 +443,16 @@ struct server_config { }; TAILQ_HEAD(serverhosts, server_config); +struct tls_config { + u_int32_t id; + + in_port_t port; + struct sockaddr_storage ss; + + size_t tls_cert_len; + size_t tls_key_len; +}; + struct server { TAILQ_ENTRY(server) srv_entry; struct server_config srv_conf; @@ -680,7 +691,9 @@ int config_setreset(struct httpd *, u_int); int config_getreset(struct httpd *, struct imsg *); int config_getcfg(struct httpd *, struct imsg *); int config_setserver(struct httpd *, struct server *); +int config_settls(struct httpd *, struct server *); int config_getserver(struct httpd *, struct imsg *); +int config_gettls(struct httpd *, struct imsg *); int config_setmedia(struct httpd *, struct media_type *); int config_getmedia(struct httpd *, struct imsg *); int config_setauth(struct httpd *, struct auth *); diff --git a/usr.sbin/httpd/server.c b/usr.sbin/httpd/server.c index 15d19450a36..d28b67b90c6 100644 --- a/usr.sbin/httpd/server.c +++ b/usr.sbin/httpd/server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server.c,v 1.65 2015/07/15 14:49:42 jsing Exp $ */ +/* $OpenBSD: server.c,v 1.66 2015/07/15 16:00:39 jsing Exp $ */ /* * Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org> @@ -1134,6 +1134,9 @@ server_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) case IMSG_CFG_SERVER: config_getserver(env, imsg); break; + case IMSG_CFG_TLS: + config_gettls(env, imsg); + break; case IMSG_CFG_DONE: config_getcfg(env, imsg); break; |