aboutsummaryrefslogtreecommitdiff
path: root/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'config.c')
-rw-r--r--config.c405
1 files changed, 405 insertions, 0 deletions
diff --git a/config.c b/config.c
index 7a438a5..feb0ca9 100644
--- a/config.c
+++ b/config.c
@@ -16,8 +16,15 @@
#include "gmid.h"
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <limits.h>
#include <string.h>
+#include "log.h"
+#include "proc.h"
+
void
config_init(void)
{
@@ -30,11 +37,15 @@ config_init(void)
init_mime(&conf.mime);
conf.prefork = 3;
+
+ conf.sock4 = -1;
+ conf.sock6 = -1;
}
void
config_free(void)
{
+ struct privsep *ps;
struct vhost *h, *th;
struct location *l, *tl;
struct proxy *p, *tp;
@@ -42,14 +53,33 @@ config_free(void)
struct alist *a, *ta;
int v;
+ ps = conf.ps;
v = conf.verbose;
+ if (conf.sock4 != -1) {
+ event_del(&conf.evsock4);
+ close(conf.sock4);
+ }
+
+ if (conf.sock6 != -1) {
+ event_del(&conf.evsock6);
+ close(conf.sock6);
+ }
+
free_mime(&conf.mime);
memset(&conf, 0, sizeof(conf));
+ conf.ps = ps;
conf.verbose = v;
+ conf.sock4 = conf.sock6 = -1;
+ conf.protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
+ init_mime(&conf.mime);
TAILQ_FOREACH_SAFE(h, &hosts, vhosts, th) {
+ free(h->cert);
+ free(h->key);
+ free(h->ocsp);
+
TAILQ_FOREACH_SAFE(l, &h->locations, locations, tl) {
TAILQ_REMOVE(&h->locations, l, locations);
@@ -82,3 +112,378 @@ config_free(void)
memset(fcgi, 0, sizeof(fcgi));
}
+
+static int
+config_send_file(struct privsep *ps, int fd, int type)
+{
+ int n, m, id, d;
+
+ id = PROC_SERVER;
+ n = -1;
+ proc_range(ps, id, &n, &m);
+ for (n = 0; n < m; ++n) {
+ if ((d = dup(fd)) == -1)
+ fatal("dup");
+ if (proc_compose_imsg(ps, id, n, type, -1, d, NULL, 0)
+ == -1)
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+static int
+config_send_socks(struct conf *conf)
+{
+ struct privsep *ps = conf->ps;
+ int sock;
+
+ if ((sock = make_socket(conf->port, AF_INET)) == -1)
+ return -1;
+
+ if (config_send_file(ps, sock, IMSG_RECONF_SOCK4) == -1)
+ return -1;
+
+ if (!conf->ipv6)
+ return 0;
+
+ if ((sock = make_socket(conf->port, AF_INET6)) == -1)
+ return -1;
+
+ if (config_send_file(ps, sock, IMSG_RECONF_SOCK6) == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+config_send(struct conf *conf, struct fcgi *fcgi, struct vhosthead *hosts)
+{
+ struct privsep *ps = conf->ps;
+ struct etm *m;
+ struct vhost *h;
+ struct location *l;
+ struct proxy *p;
+ struct envlist *e;
+ struct alist *a;
+ size_t i;
+ int fd;
+
+ for (i = 0; i < conf->mime.len; ++i) {
+ m = &conf->mime.t[i];
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_MIME,
+ m, sizeof(*m)) == -1)
+ return -1;
+ }
+
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PROTOS,
+ &conf->protos, sizeof(conf->protos)) == -1)
+ return -1;
+
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PORT,
+ &conf->port, sizeof(conf->port)) == -1)
+ return -1;
+
+ if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
+ return -1;
+
+ if (config_send_socks(conf) == -1)
+ return -1;
+
+ if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
+ return -1;
+
+ for (i = 0; i < FCGI_MAX; ++i) {
+ if (*fcgi[i].path == '\0')
+ break;
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_FCGI,
+ &fcgi[i], sizeof(fcgi[i])) == -1)
+ return -1;
+ }
+
+ TAILQ_FOREACH(h, hosts, vhosts) {
+ log_debug("sending host %s", h->domain);
+
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_HOST,
+ h, sizeof(*h)) == -1)
+ return -1;
+
+ log_debug("sending certificate %s", h->cert_path);
+ if ((fd = open(h->cert_path, O_RDONLY)) == -1)
+ fatal("can't open %s", h->cert_path);
+ if (config_send_file(ps, fd, IMSG_RECONF_CERT) == -1)
+ return -1;
+
+ log_debug("sending key %s", h->key_path);
+ if ((fd = open(h->key_path, O_RDONLY)) == -1)
+ fatal("can't open %s", h->key_path);
+ if (config_send_file(ps, fd, IMSG_RECONF_KEY) == -1)
+ return -1;
+
+ if (*h->ocsp_path != '\0') {
+ log_debug("sending ocsp %s", h->ocsp_path);
+ if ((fd = open(h->ocsp_path, O_RDONLY)) == -1)
+ fatal("can't open %s", h->ocsp_path);
+ if (config_send_file(ps, fd, IMSG_RECONF_OCSP) == -1)
+ return -1;
+ }
+
+ TAILQ_FOREACH(l, &h->locations, locations) {
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_LOC,
+ l, sizeof(*l)) == -1)
+ return -1;
+ }
+
+ if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
+ return -1;
+
+ TAILQ_FOREACH(e, &h->params, envs) {
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ENV,
+ e, sizeof(*e)) == -1)
+ return -1;
+ }
+
+ if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
+ return -1;
+
+ TAILQ_FOREACH(a, &h->aliases, aliases) {
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ALIAS,
+ a, sizeof(*a)) == -1)
+ return -1;
+ }
+
+ if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
+ return -1;
+
+ TAILQ_FOREACH(p, &h->proxies, proxies) {
+ if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PROXY,
+ p, sizeof(*p)) == -1)
+ return -1;
+ }
+
+ if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+load_file(int fd, uint8_t **data, size_t *len)
+{
+ struct stat sb;
+ FILE *fp;
+ size_t r;
+
+ if (fstat(fd, &sb) == -1)
+ fatal("fstat");
+
+ if ((fp = fdopen(fd, "r")) == NULL)
+ fatal("fdopen");
+
+ if (sb.st_size < 0 /* || sb.st_size > SIZE_MAX */) {
+ log_warnx("file too large");
+ fclose(fp);
+ return -1;
+ }
+ *len = sb.st_size;
+
+ if ((*data = malloc(*len)) == NULL)
+ fatal("malloc");
+
+ r = fread(*data, 1, *len, fp);
+ if (r != *len) {
+ log_warn("read");
+ fclose(fp);
+ free(*data);
+ return -1;
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+int
+config_recv(struct conf *conf, struct imsg *imsg)
+{
+ static struct vhost *h;
+ struct privsep *ps = conf->ps;
+ struct etm m;
+ struct fcgi *f;
+ struct vhost *vh, vht;
+ struct location *loc;
+ struct envlist *env;
+ struct alist *alias;
+ struct proxy *proxy;
+ size_t i, datalen;
+
+ datalen = IMSG_DATA_SIZE(imsg);
+
+ switch (imsg->hdr.type) {
+ case IMSG_RECONF_START:
+ config_free();
+ h = NULL;
+ break;
+
+ case IMSG_RECONF_MIME:
+ IMSG_SIZE_CHECK(imsg, &m);
+ memcpy(&m, imsg->data, datalen);
+ if (m.mime[sizeof(m.mime) - 1] != '\0' ||
+ m.ext[sizeof(m.ext) - 1] != '\0')
+ fatal("received corrupted IMSG_RECONF_MIME");
+ if (add_mime(&conf->mime, m.mime, m.ext) == -1)
+ fatal("failed to add mime mapping %s -> %s",
+ m.mime, m.ext);
+ break;
+
+ case IMSG_RECONF_PROTOS:
+ IMSG_SIZE_CHECK(imsg, &conf->protos);
+ memcpy(&conf->protos, imsg->data, datalen);
+ break;
+
+ case IMSG_RECONF_PORT:
+ IMSG_SIZE_CHECK(imsg, &conf->port);
+ memcpy(&conf->port, imsg->data, datalen);
+ break;
+
+ case IMSG_RECONF_SOCK4:
+ if (conf->sock4 != -1)
+ fatalx("socket ipv4 already recv'd");
+ if (imsg->fd == -1)
+ fatalx("missing socket for IMSG_RECONF_SOCK4");
+ conf->sock4 = imsg->fd;
+ event_set(&conf->evsock4, conf->sock4, EV_READ|EV_PERSIST,
+ do_accept, NULL);
+ break;
+
+ case IMSG_RECONF_SOCK6:
+ if (conf->sock6 != -1)
+ fatalx("socket ipv6 already recv'd");
+ if (imsg->fd == -1)
+ fatalx("missing socket for IMSG_RECONF_SOCK6");
+ conf->sock6 = imsg->fd;
+ event_set(&conf->evsock6, conf->sock6, EV_READ|EV_PERSIST,
+ do_accept, NULL);
+ break;
+
+ case IMSG_RECONF_FCGI:
+ for (i = 0; i < FCGI_MAX; ++i) {
+ f = &fcgi[i];
+ if (*f->path != '\0')
+ continue;
+ IMSG_SIZE_CHECK(imsg, f);
+ memcpy(f, imsg->data, datalen);
+ break;
+ }
+ if (i == FCGI_MAX)
+ fatalx("recv too many fcgi");
+ break;
+
+ case IMSG_RECONF_HOST:
+ IMSG_SIZE_CHECK(imsg, &vht);
+ memcpy(&vht, imsg->data, datalen);
+ vh = new_vhost();
+ strlcpy(vh->domain, vht.domain, sizeof(vh->domain));
+ h = vh;
+ TAILQ_INSERT_TAIL(&hosts, h, vhosts);
+ break;
+
+ case IMSG_RECONF_CERT:
+ log_debug("receiving cert");
+ if (h == NULL)
+ fatalx("recv'd cert without host");
+ if (h->cert != NULL)
+ fatalx("cert already received");
+ if (imsg->fd == -1)
+ fatalx("no fd for IMSG_RECONF_CERT");
+ if (load_file(imsg->fd, &h->cert, &h->certlen) == -1)
+ fatalx("failed to load cert for %s",
+ h->domain);
+ break;
+
+ case IMSG_RECONF_KEY:
+ log_debug("receiving key");
+ if (h == NULL)
+ fatalx("recv'd key without host");
+ if (h->key != NULL)
+ fatalx("key already received");
+ if (imsg->fd == -1)
+ fatalx("no fd for IMSG_RECONF_KEY");
+ if (load_file(imsg->fd, &h->key, &h->keylen) == -1)
+ fatalx("failed to load key for %s",
+ h->domain);
+ break;
+
+ case IMSG_RECONF_OCSP:
+ log_debug("receiving ocsp");
+ if (h == NULL)
+ fatalx("recv'd ocsp without host");
+ if (h->ocsp != NULL)
+ fatalx("ocsp already received");
+ if (imsg->fd == -1)
+ fatalx("no fd for IMSG_RECONF_OCSP");
+ if (load_file(imsg->fd, &h->ocsp, &h->ocsplen) == -1)
+ fatalx("failed to load ocsp for %s",
+ h->domain);
+ break;
+
+ case IMSG_RECONF_LOC:
+ if (h == NULL)
+ fatalx("recv'd location without host");
+ IMSG_SIZE_CHECK(imsg, loc);
+
+ //loc = new_location();
+ loc = xcalloc(1, sizeof(*loc));
+ loc->dirfd = -1;
+ loc->fcgi = -1;
+
+ memcpy(loc, imsg->data, datalen);
+ loc->dirfd = -1; /* XXX */
+ loc->reqca = NULL; /* XXX */
+ TAILQ_INSERT_TAIL(&h->locations, loc, locations);
+ break;
+
+ case IMSG_RECONF_ENV:
+ if (h == NULL)
+ fatalx("recv'd env without host");
+ IMSG_SIZE_CHECK(imsg, env);
+ env = xcalloc(1, sizeof(*env));
+ memcpy(env, imsg->data, datalen);
+ TAILQ_INSERT_TAIL(&h->params, env, envs);
+ break;
+
+ case IMSG_RECONF_ALIAS:
+ if (h == NULL)
+ fatalx("recv'd alias without host");
+ IMSG_SIZE_CHECK(imsg, alias);
+ alias = xcalloc(1, sizeof(*alias));
+ memcpy(alias, imsg->data, datalen);
+ TAILQ_INSERT_TAIL(&h->aliases, alias, aliases);
+ break;
+
+ case IMSG_RECONF_PROXY:
+ log_debug("receiving proxy");
+ if (h == NULL)
+ fatalx("recv'd proxy without host");
+ IMSG_SIZE_CHECK(imsg, proxy);
+ proxy = xcalloc(1, sizeof(*proxy));
+ memcpy(proxy, imsg->data, datalen);
+ proxy->reqca = NULL; /* XXX */
+ proxy->cert = proxy->key = NULL; /* XXX */
+ proxy->certlen = proxy->keylen = 0; /* XXX */
+ TAILQ_INSERT_TAIL(&h->proxies, proxy, proxies);
+ break;
+
+ case IMSG_RECONF_END:
+ if (proc_compose(ps, PROC_PARENT, IMSG_RECONF_DONE,
+ NULL, 0) == -1)
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}