diff options
Diffstat (limited to 'httpd/config.c')
-rw-r--r-- | httpd/config.c | 150 |
1 files changed, 124 insertions, 26 deletions
diff --git a/httpd/config.c b/httpd/config.c index 7635c33..3c88990 100644 --- a/httpd/config.c +++ b/httpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.37 2015/04/11 14:52:49 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,30 +534,69 @@ 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) { + + return (0); + + fail: + if (imsg->fd != -1) + close(imsg->fd); + if (srv != NULL) + serverconfig_free(&srv->srv_conf); + free(srv); + + return (-1); +} + +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, - srv->srv_conf.tls_cert_len)) == NULL) + tls_conf.tls_cert_len)) == NULL) goto fail; - s += srv->srv_conf.tls_cert_len; + s += tls_conf.tls_cert_len; } - if (srv->srv_conf.tls_key_len != 0) { + 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, - srv->srv_conf.tls_key_len)) == NULL) + tls_conf.tls_key_len)) == NULL) goto fail; - s += srv->srv_conf.tls_key_len; + s += tls_conf.tls_key_len; } return (0); fail: - if (imsg->fd != -1) - close(imsg->fd); - if (srv != NULL) { - free(srv->srv_conf.tls_cert); - free(srv->srv_conf.tls_key); - } - free(srv); - return (-1); } |