2 * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #include <openssl/pem.h>
35 conf = xcalloc(1, sizeof(*conf));
37 TAILQ_INIT(&conf->fcgi);
38 TAILQ_INIT(&conf->hosts);
39 TAILQ_INIT(&conf->pkis);
43 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
45 init_mime(&conf->mime);
50 conf->use_privsep_crypto = 1;
60 config_purge(struct conf *conf)
65 struct location *l, *tl;
67 struct envlist *e, *te;
69 struct pki *pki, *tpki;
70 int use_privsep_crypto;
73 use_privsep_crypto = conf->use_privsep_crypto;
75 if (conf->sock4 != -1) {
76 event_del(&conf->evsock4);
80 if (conf->sock6 != -1) {
81 event_del(&conf->evsock6);
85 free_mime(&conf->mime);
86 TAILQ_FOREACH_SAFE(f, &conf->fcgi, fcgi, tf) {
87 TAILQ_REMOVE(&conf->fcgi, f, fcgi);
91 TAILQ_FOREACH_SAFE(h, &conf->hosts, vhosts, th) {
99 TAILQ_FOREACH_SAFE(l, &h->locations, locations, tl) {
100 TAILQ_REMOVE(&h->locations, l, locations);
106 X509_STORE_free(l->reqca);
110 TAILQ_FOREACH_SAFE(e, &h->params, envs, te) {
111 TAILQ_REMOVE(&h->params, e, envs);
115 TAILQ_FOREACH_SAFE(a, &h->aliases, aliases, ta) {
116 TAILQ_REMOVE(&h->aliases, a, aliases);
120 TAILQ_FOREACH_SAFE(p, &h->proxies, proxies, tp) {
121 TAILQ_REMOVE(&h->proxies, p, proxies);
127 X509_STORE_free(p->reqca);
131 TAILQ_REMOVE(&conf->hosts, h, vhosts);
135 TAILQ_FOREACH_SAFE(pki, &conf->pkis, pkis, tpki) {
136 TAILQ_REMOVE(&conf->pkis, pki, pkis);
138 EVP_PKEY_free(pki->pkey);
142 memset(conf, 0, sizeof(*conf));
145 conf->use_privsep_crypto = use_privsep_crypto;
146 conf->sock4 = conf->sock6 = -1;
147 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
148 init_mime(&conf->mime);
149 TAILQ_INIT(&conf->fcgi);
150 TAILQ_INIT(&conf->hosts);
151 TAILQ_INIT(&conf->pkis);
155 config_send_file(struct privsep *ps, enum privsep_procid id, int type,
156 int fd, void *data, size_t l)
161 proc_range(ps, id, &n, &m);
162 for (n = 0; n < m; ++n) {
164 if (fd != -1 && (d = dup(fd)) == -1)
166 if (proc_compose_imsg(ps, id, n, type, -1, d, data, l)
177 config_open_send(struct privsep *ps, enum privsep_procid id, int type,
182 log_debug("sending %s", path);
184 if ((fd = open(path, O_RDONLY)) == -1)
185 fatal("can't open %s", path);
187 return config_send_file(ps, id, type, fd, NULL, 0);
191 config_send_kp(struct privsep *ps, int cert_type, int key_type,
192 const char *cert, const char *key)
194 struct conf *conf = ps->ps_env;
195 int fd, d, key_target;
197 log_debug("sending %s", cert);
198 if ((fd = open(cert, O_RDONLY)) == -1)
199 fatal("can't open %s", cert);
200 if ((d = dup(fd)) == -1)
203 if (config_send_file(ps, PROC_SERVER, cert_type, fd, NULL, 0) == -1) {
207 if (conf->use_privsep_crypto &&
208 config_send_file(ps, PROC_CRYPTO, cert_type, d, NULL, 0) == -1)
211 log_debug("sending %s", key);
212 if ((fd = open(key, O_RDONLY)) == -1)
215 key_target = PROC_CRYPTO;
216 if (!conf->use_privsep_crypto)
217 key_target = PROC_SERVER;
219 if (config_send_file(ps, key_target, key_type, fd, NULL, 0) == -1)
222 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
224 if (proc_flush_imsg(ps, PROC_CRYPTO, -1) == -1)
230 make_socket(int port, int family)
233 struct sockaddr_in addr4;
234 struct sockaddr_in6 addr6;
235 struct sockaddr *addr;
240 memset(&addr4, 0, sizeof(addr4));
241 addr4.sin_family = family;
242 addr4.sin_port = htons(port);
243 addr4.sin_addr.s_addr = INADDR_ANY;
244 addr = (struct sockaddr*)&addr4;
249 memset(&addr6, 0, sizeof(addr6));
250 addr6.sin6_family = AF_INET6;
251 addr6.sin6_port = htons(port);
252 addr6.sin6_addr = in6addr_any;
253 addr = (struct sockaddr*)&addr6;
262 if ((sock = socket(family, SOCK_STREAM, 0)) == -1)
266 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)) == -1)
267 fatal("setsockopt(SO_REUSEADDR)");
270 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &v, sizeof(v)) == -1)
271 fatal("setsockopt(SO_REUSEPORT)");
275 if (bind(sock, addr, len) == -1)
278 if (listen(sock, 16) == -1)
285 config_send_socks(struct conf *conf)
287 struct privsep *ps = conf->ps;
290 if ((sock = make_socket(conf->port, AF_INET)) == -1)
293 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_SOCK4, sock,
300 if ((sock = make_socket(conf->port, AF_INET6)) == -1)
303 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_SOCK6, sock,
311 config_send(struct conf *conf)
313 struct privsep *ps = conf->ps;
323 for (i = 0; i < conf->mime.len; ++i) {
324 m = &conf->mime.t[i];
325 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_MIME,
326 m, sizeof(*m)) == -1)
330 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PROTOS,
331 &conf->protos, sizeof(conf->protos)) == -1)
334 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PORT,
335 &conf->port, sizeof(conf->port)) == -1)
338 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
341 if (config_send_socks(conf) == -1)
344 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
347 TAILQ_FOREACH(fcgi, &conf->fcgi, fcgi) {
348 log_debug("sending fastcgi %s", fcgi->path);
349 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_FCGI,
350 fcgi, sizeof(*fcgi)) == -1)
354 TAILQ_FOREACH(h, &conf->hosts, vhosts) {
357 memcpy(&vcopy, h, sizeof(vcopy));
358 vcopy.cert_path = NULL;
359 vcopy.key_path = NULL;
360 vcopy.ocsp_path = NULL;
362 log_debug("sending host %s", h->domain);
364 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_HOST,
365 &vcopy, sizeof(vcopy)) == -1)
368 if (config_send_kp(ps, IMSG_RECONF_CERT, IMSG_RECONF_KEY,
369 h->cert_path, h->key_path) == -1)
372 if (h->ocsp_path != NULL) {
373 if (config_open_send(ps, PROC_SERVER, IMSG_RECONF_OCSP,
376 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
380 TAILQ_FOREACH(l, &h->locations, locations) {
381 struct location lcopy;
384 memcpy(&lcopy, l, sizeof(lcopy));
385 lcopy.reqca_path = NULL;
388 memset(&lcopy.locations, 0, sizeof(lcopy.locations));
390 if (l->reqca_path != NULL &&
391 (fd = open(l->reqca_path, O_RDONLY)) == -1)
392 fatal("can't open %s", l->reqca_path);
394 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_LOC,
395 fd, &lcopy, sizeof(lcopy)) == -1)
399 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
402 TAILQ_FOREACH(e, &h->params, envs) {
403 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ENV,
404 e, sizeof(*e)) == -1)
408 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
411 TAILQ_FOREACH(a, &h->aliases, aliases) {
412 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ALIAS,
413 a, sizeof(*a)) == -1)
417 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
420 TAILQ_FOREACH(p, &h->proxies, proxies) {
424 memcpy(&pcopy, p, sizeof(pcopy));
425 pcopy.cert_path = NULL;
428 pcopy.key_path = NULL;
431 pcopy.reqca_path = NULL;
434 if (p->reqca_path != NULL) {
435 fd = open(p->reqca_path, O_RDONLY);
437 fatal("can't open %s", p->reqca_path);
440 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_PROXY,
441 fd, &pcopy, sizeof(pcopy)) == -1)
444 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
447 if (p->cert_path == NULL || p->key_path == NULL)
450 if (config_open_send(ps, PROC_SERVER,
451 IMSG_RECONF_PROXY_CERT, p->cert_path) == -1 ||
452 config_open_send(ps, PROC_SERVER,
453 IMSG_RECONF_PROXY_KEY, p->key_path) == -1)
456 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
460 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
468 load_file(int fd, uint8_t **data, size_t *len)
473 if (fstat(fd, &sb) == -1)
476 if (sb.st_size < 0 /* || sb.st_size > SIZE_MAX */) {
477 log_warnx("file too large");
483 if ((*data = malloc(*len)) == NULL)
486 r = pread(fd, *data, *len, 0);
487 if (r == -1 || (size_t)r != *len) {
488 log_warn("read failed");
499 config_crypto_recv_kp(struct conf *conf, struct imsg *imsg)
501 static struct pki *pki;
505 /* XXX: check for duplicates */
508 fatalx("no fd for imsg %d", imsg->hdr.type);
510 switch (imsg->hdr.type) {
511 case IMSG_RECONF_CERT:
513 fatalx("imsg in wrong order; pki is not NULL");
514 if ((pki = calloc(1, sizeof(*pki))) == NULL)
516 if (load_file(imsg->fd, &d, &len) == -1)
517 fatalx("can't load file");
518 if ((pki->hash = ssl_pubkey_hash(d, len)) == NULL)
519 fatalx("failed to compute cert hash");
521 TAILQ_INSERT_TAIL(&conf->pkis, pki, pkis);
524 case IMSG_RECONF_KEY:
526 fatalx("got key without cert beforehand %d",
528 if (load_file(imsg->fd, &d, &len) == -1)
529 fatalx("failed to load private key");
530 if ((pki->pkey = ssl_load_pkey(d, len)) == NULL)
531 fatalx("failed load private key");
544 config_recv(struct conf *conf, struct imsg *imsg)
546 static struct vhost *h;
547 static struct proxy *p;
548 struct privsep *ps = conf->ps;
551 struct vhost *vh, vht;
552 struct location *loc;
558 datalen = IMSG_DATA_SIZE(imsg);
560 switch (imsg->hdr.type) {
561 case IMSG_RECONF_START:
567 case IMSG_RECONF_MIME:
568 IMSG_SIZE_CHECK(imsg, &m);
569 memcpy(&m, imsg->data, datalen);
570 if (m.mime[sizeof(m.mime) - 1] != '\0' ||
571 m.ext[sizeof(m.ext) - 1] != '\0')
572 fatal("received corrupted IMSG_RECONF_MIME");
573 if (add_mime(&conf->mime, m.mime, m.ext) == -1)
574 fatal("failed to add mime mapping %s -> %s",
578 case IMSG_RECONF_PROTOS:
579 IMSG_SIZE_CHECK(imsg, &conf->protos);
580 memcpy(&conf->protos, imsg->data, datalen);
583 case IMSG_RECONF_PORT:
584 IMSG_SIZE_CHECK(imsg, &conf->port);
585 memcpy(&conf->port, imsg->data, datalen);
588 case IMSG_RECONF_SOCK4:
589 if (conf->sock4 != -1)
590 fatalx("socket ipv4 already recv'd");
592 fatalx("missing socket for IMSG_RECONF_SOCK4");
593 conf->sock4 = imsg->fd;
594 event_set(&conf->evsock4, conf->sock4, EV_READ|EV_PERSIST,
598 case IMSG_RECONF_SOCK6:
599 if (conf->sock6 != -1)
600 fatalx("socket ipv6 already recv'd");
602 fatalx("missing socket for IMSG_RECONF_SOCK6");
603 conf->sock6 = imsg->fd;
604 event_set(&conf->evsock6, conf->sock6, EV_READ|EV_PERSIST,
608 case IMSG_RECONF_FCGI:
609 IMSG_SIZE_CHECK(imsg, fcgi);
610 fcgi = xcalloc(1, sizeof(*fcgi));
611 memcpy(fcgi, imsg->data, datalen);
612 log_debug("received fcgi %s", fcgi->path);
613 TAILQ_INSERT_TAIL(&conf->fcgi, fcgi, fcgi);
616 case IMSG_RECONF_HOST:
617 IMSG_SIZE_CHECK(imsg, &vht);
618 memcpy(&vht, imsg->data, datalen);
620 strlcpy(vh->domain, vht.domain, sizeof(vh->domain));
622 TAILQ_INSERT_TAIL(&conf->hosts, h, vhosts);
628 case IMSG_RECONF_CERT:
629 log_debug("receiving cert");
630 if (privsep_process == PROC_CRYPTO)
631 return config_crypto_recv_kp(conf, imsg);
633 fatalx("recv'd cert without host");
635 fatalx("cert already received");
637 fatalx("no fd for IMSG_RECONF_CERT");
638 if (load_file(imsg->fd, &h->cert, &h->certlen) == -1)
639 fatalx("failed to load cert for %s",
643 case IMSG_RECONF_KEY:
644 log_debug("receiving key");
645 if (privsep_process == PROC_CRYPTO)
646 return config_crypto_recv_kp(conf, imsg);
648 fatalx("recv'd key without host");
650 fatalx("key already received");
652 fatalx("no fd for IMSG_RECONF_KEY");
653 if (load_file(imsg->fd, &h->key, &h->keylen) == -1)
654 fatalx("failed to load key for %s",
658 case IMSG_RECONF_OCSP:
659 log_debug("receiving ocsp");
661 fatalx("recv'd ocsp without host");
663 fatalx("ocsp already received");
665 fatalx("no fd for IMSG_RECONF_OCSP");
666 if (load_file(imsg->fd, &h->ocsp, &h->ocsplen) == -1)
667 fatalx("failed to load ocsp for %s",
671 case IMSG_RECONF_LOC:
673 fatalx("recv'd location without host");
674 IMSG_SIZE_CHECK(imsg, loc);
675 loc = xcalloc(1, sizeof(*loc));
676 memcpy(loc, imsg->data, datalen);
678 if (imsg->fd != -1) {
679 loc->reqca = load_ca(imsg->fd);
680 if (loc->reqca == NULL)
681 fatalx("failed to load CA");
684 TAILQ_INSERT_TAIL(&h->locations, loc, locations);
687 case IMSG_RECONF_ENV:
689 fatalx("recv'd env without host");
690 IMSG_SIZE_CHECK(imsg, env);
691 env = xcalloc(1, sizeof(*env));
692 memcpy(env, imsg->data, datalen);
693 TAILQ_INSERT_TAIL(&h->params, env, envs);
696 case IMSG_RECONF_ALIAS:
698 fatalx("recv'd alias without host");
699 IMSG_SIZE_CHECK(imsg, alias);
700 alias = xcalloc(1, sizeof(*alias));
701 memcpy(alias, imsg->data, datalen);
702 TAILQ_INSERT_TAIL(&h->aliases, alias, aliases);
705 case IMSG_RECONF_PROXY:
706 log_debug("receiving proxy");
708 fatalx("recv'd proxy without host");
709 IMSG_SIZE_CHECK(imsg, proxy);
710 proxy = xcalloc(1, sizeof(*proxy));
711 memcpy(proxy, imsg->data, datalen);
713 if (imsg->fd != -1) {
714 proxy->reqca = load_ca(imsg->fd);
715 if (proxy->reqca == NULL)
716 fatal("failed to load CA");
719 TAILQ_INSERT_TAIL(&h->proxies, proxy, proxies);
723 case IMSG_RECONF_PROXY_CERT:
724 log_debug("receiving proxy cert");
726 fatalx("recv'd proxy cert without proxy");
728 fatalx("proxy cert already received");
730 fatalx("no fd for IMSG_RECONF_PROXY_CERT");
731 if (load_file(imsg->fd, &p->cert, &p->certlen) == -1)
732 fatalx("failed to load cert for proxy %s of %s",
736 case IMSG_RECONF_PROXY_KEY:
737 log_debug("receiving proxy key");
739 fatalx("recv'd proxy key without proxy");
741 fatalx("proxy key already received");
743 fatalx("no fd for IMSG_RECONF_PROXY_KEY");
744 if (load_file(imsg->fd, &p->key, &p->keylen) == -1)
745 fatalx("failed to load key for proxy %s of %s",
749 case IMSG_RECONF_END:
750 if (proc_compose(ps, PROC_PARENT, IMSG_RECONF_DONE,