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);
40 TAILQ_INIT(&conf->addrs);
42 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
44 init_mime(&conf->mime);
49 conf->use_privsep_crypto = 1;
56 config_purge(struct conf *conf)
61 struct location *l, *tl;
63 struct envlist *e, *te;
65 struct pki *pki, *tpki;
66 struct address *addr, *taddr;
67 int use_privsep_crypto;
70 use_privsep_crypto = conf->use_privsep_crypto;
72 free_mime(&conf->mime);
73 TAILQ_FOREACH_SAFE(f, &conf->fcgi, fcgi, tf) {
74 TAILQ_REMOVE(&conf->fcgi, f, fcgi);
78 TAILQ_FOREACH_SAFE(h, &conf->hosts, vhosts, th) {
86 TAILQ_FOREACH_SAFE(addr, &h->addrs, addrs, taddr) {
87 TAILQ_REMOVE(&h->addrs, addr, addrs);
91 TAILQ_FOREACH_SAFE(l, &h->locations, locations, tl) {
92 TAILQ_REMOVE(&h->locations, l, locations);
98 X509_STORE_free(l->reqca);
101 TAILQ_FOREACH_SAFE(e, &l->params, envs, te) {
102 TAILQ_REMOVE(&l->params, e, envs);
107 TAILQ_FOREACH_SAFE(a, &h->aliases, aliases, ta) {
108 TAILQ_REMOVE(&h->aliases, a, aliases);
112 TAILQ_FOREACH_SAFE(p, &h->proxies, proxies, tp) {
113 TAILQ_REMOVE(&h->proxies, p, proxies);
119 X509_STORE_free(p->reqca);
123 TAILQ_REMOVE(&conf->hosts, h, vhosts);
127 TAILQ_FOREACH_SAFE(pki, &conf->pkis, pkis, tpki) {
128 TAILQ_REMOVE(&conf->pkis, pki, pkis);
130 EVP_PKEY_free(pki->pkey);
134 TAILQ_FOREACH_SAFE(addr, &conf->addrs, addrs, taddr) {
135 TAILQ_REMOVE(&conf->addrs, addr, addrs);
136 if (addr->sock != -1) {
138 event_del(&addr->evsock);
144 memset(conf, 0, sizeof(*conf));
147 conf->use_privsep_crypto = use_privsep_crypto;
148 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
149 init_mime(&conf->mime);
150 TAILQ_INIT(&conf->fcgi);
151 TAILQ_INIT(&conf->hosts);
152 TAILQ_INIT(&conf->pkis);
156 config_send_file(struct privsep *ps, enum privsep_procid id, int type,
157 int fd, void *data, size_t l)
162 proc_range(ps, id, &n, &m);
163 for (n = 0; n < m; ++n) {
165 if (fd != -1 && (d = dup(fd)) == -1)
167 if (proc_compose_imsg(ps, id, n, type, -1, d, data, l)
175 /* avoid fd rampage */
176 if (proc_flush_imsg(ps, id, -1) == -1) {
177 log_warn("%s: proc_fush_imsg", __func__);
185 config_open_send(struct privsep *ps, enum privsep_procid id, int type,
190 log_debug("sending %s", path);
192 if ((fd = open(path, O_RDONLY)) == -1)
193 fatal("can't open %s", path);
195 return config_send_file(ps, id, type, fd, NULL, 0);
199 config_send_kp(struct privsep *ps, int cert_type, int key_type,
200 const char *cert, const char *key)
202 struct conf *conf = ps->ps_env;
203 int fd, d, key_target;
205 log_debug("sending %s", cert);
206 if ((fd = open(cert, O_RDONLY)) == -1)
207 fatal("can't open %s", cert);
208 if ((d = dup(fd)) == -1)
211 if (config_send_file(ps, PROC_SERVER, cert_type, fd, NULL, 0) == -1) {
215 if (conf->use_privsep_crypto &&
216 config_send_file(ps, PROC_CRYPTO, cert_type, d, NULL, 0) == -1)
219 key_target = PROC_CRYPTO;
220 if (!conf->use_privsep_crypto)
221 key_target = PROC_SERVER;
223 if (config_open_send(ps, key_target, key_type, key) == -1)
230 config_send_socks(struct conf *conf)
232 struct privsep *ps = conf->ps;
233 struct address *addr, a;
236 TAILQ_FOREACH(addr, &conf->addrs, addrs) {
237 sock = socket(addr->ai_family, addr->ai_socktype,
243 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v))
245 fatal("setsockopt(SO_REUSEADDR)");
248 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &v, sizeof(v))
250 fatal("setsockopt(SO_REUSEPORT)");
254 if (bind(sock, (struct sockaddr *)&addr->ss, addr->slen)
258 if (listen(sock, 16) == -1)
261 memcpy(&a, addr, sizeof(a));
264 memset(&a.evsock, 0, sizeof(a.evsock));
265 memset(&a.addrs, 0, sizeof(a.addrs));
267 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_SOCK, sock,
268 &a, sizeof(a)) == -1)
276 config_send(struct conf *conf)
278 struct privsep *ps = conf->ps;
288 for (i = 0; i < conf->mime.len; ++i) {
289 m = &conf->mime.t[i];
290 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_MIME,
291 m, sizeof(*m)) == -1)
295 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PROTOS,
296 &conf->protos, sizeof(conf->protos)) == -1)
299 if (config_send_socks(conf) == -1)
302 TAILQ_FOREACH(fcgi, &conf->fcgi, fcgi) {
303 log_debug("sending fastcgi %s", fcgi->path);
304 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_FCGI,
305 fcgi, sizeof(*fcgi)) == -1)
309 TAILQ_FOREACH(h, &conf->hosts, vhosts) {
311 struct address *addr, acopy;
313 memcpy(&vcopy, h, sizeof(vcopy));
314 vcopy.cert_path = NULL;
315 vcopy.key_path = NULL;
316 vcopy.ocsp_path = NULL;
318 log_debug("sending host %s", h->domain);
320 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_HOST,
321 &vcopy, sizeof(vcopy)) == -1)
324 if (config_send_kp(ps, IMSG_RECONF_CERT, IMSG_RECONF_KEY,
325 h->cert_path, h->key_path) == -1)
328 if (h->ocsp_path != NULL) {
329 if (config_open_send(ps, PROC_SERVER, IMSG_RECONF_OCSP,
334 TAILQ_FOREACH(addr, &h->addrs, addrs) {
335 memcpy(&acopy, addr, sizeof(acopy));
336 memset(&acopy.addrs, 0, sizeof(acopy.addrs));
338 if (proc_compose(ps, PROC_SERVER,
339 IMSG_RECONF_HOST_ADDR, &acopy, sizeof(acopy))
344 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1) {
345 log_warn("%s: proc_fush_imsg", __func__);
349 TAILQ_FOREACH(l, &h->locations, locations) {
350 struct location lcopy;
353 memcpy(&lcopy, l, sizeof(lcopy));
354 lcopy.reqca_path = NULL;
357 memset(&lcopy.locations, 0, sizeof(lcopy.locations));
359 if (l->reqca_path != NULL &&
360 (fd = open(l->reqca_path, O_RDONLY)) == -1)
361 fatal("can't open %s", l->reqca_path);
363 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_LOC,
364 fd, &lcopy, sizeof(lcopy)) == -1)
367 TAILQ_FOREACH(e, &l->params, envs) {
368 if (proc_compose(ps, PROC_SERVER,
369 IMSG_RECONF_ENV, e, sizeof(*e)) == -1)
374 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
377 TAILQ_FOREACH(a, &h->aliases, aliases) {
378 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ALIAS,
379 a, sizeof(*a)) == -1)
383 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
386 TAILQ_FOREACH(p, &h->proxies, proxies) {
390 memcpy(&pcopy, p, sizeof(pcopy));
391 pcopy.cert_path = NULL;
394 pcopy.key_path = NULL;
397 pcopy.reqca_path = NULL;
400 if (p->reqca_path != NULL) {
401 fd = open(p->reqca_path, O_RDONLY);
403 fatal("can't open %s", p->reqca_path);
406 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_PROXY,
407 fd, &pcopy, sizeof(pcopy)) == -1)
410 if (p->cert_path == NULL || p->key_path == NULL)
413 if (config_open_send(ps, PROC_SERVER,
414 IMSG_RECONF_PROXY_CERT, p->cert_path) == -1 ||
415 config_open_send(ps, PROC_SERVER,
416 IMSG_RECONF_PROXY_KEY, p->key_path) == -1)
425 load_file(int fd, uint8_t **data, size_t *len)
430 if (fstat(fd, &sb) == -1)
433 if (sb.st_size < 0 /* || sb.st_size > SIZE_MAX */) {
434 log_warnx("file too large");
440 if ((*data = malloc(*len)) == NULL)
443 r = pread(fd, *data, *len, 0);
444 if (r == -1 || (size_t)r != *len) {
445 log_warn("read failed");
456 config_crypto_recv_kp(struct conf *conf, struct imsg *imsg)
458 static struct pki *pki;
462 /* XXX: check for duplicates */
465 fatalx("no fd for imsg %d", imsg->hdr.type);
467 switch (imsg->hdr.type) {
468 case IMSG_RECONF_CERT:
470 fatalx("imsg in wrong order; pki is not NULL");
471 if ((pki = calloc(1, sizeof(*pki))) == NULL)
473 if (load_file(imsg->fd, &d, &len) == -1)
474 fatalx("can't load file");
475 if ((pki->hash = ssl_pubkey_hash(d, len)) == NULL)
476 fatalx("failed to compute cert hash");
478 TAILQ_INSERT_TAIL(&conf->pkis, pki, pkis);
481 case IMSG_RECONF_KEY:
483 fatalx("got key without cert beforehand %d",
485 if (load_file(imsg->fd, &d, &len) == -1)
486 fatalx("failed to load private key");
487 if ((pki->pkey = ssl_load_pkey(d, len)) == NULL)
488 fatalx("failed load private key");
501 config_recv(struct conf *conf, struct imsg *imsg)
503 static struct vhost *h;
504 static struct location *l;
505 static struct proxy *p;
506 struct privsep *ps = conf->ps;
509 struct vhost *vh, vht;
510 struct location *loc;
514 struct address *addr;
518 datalen = IMSG_DATA_SIZE(imsg);
520 switch (imsg->hdr.type) {
521 case IMSG_RECONF_START:
527 case IMSG_RECONF_MIME:
528 IMSG_SIZE_CHECK(imsg, &m);
529 memcpy(&m, imsg->data, datalen);
530 if (m.mime[sizeof(m.mime) - 1] != '\0' ||
531 m.ext[sizeof(m.ext) - 1] != '\0')
532 fatal("received corrupted IMSG_RECONF_MIME");
533 if (add_mime(&conf->mime, m.mime, m.ext) == -1)
534 fatal("failed to add mime mapping %s -> %s",
538 case IMSG_RECONF_PROTOS:
539 IMSG_SIZE_CHECK(imsg, &conf->protos);
540 memcpy(&conf->protos, imsg->data, datalen);
543 case IMSG_RECONF_SOCK:
544 addr = xcalloc(1, sizeof(*addr));
545 IMSG_SIZE_CHECK(imsg, addr);
546 memcpy(addr, imsg->data, sizeof(*addr));
548 fatalx("missing socket for IMSG_RECONF_SOCK");
550 addr->sock = imsg->fd;
551 event_set(&addr->evsock, addr->sock, EV_READ|EV_PERSIST,
552 server_accept, addr);
553 if ((addr->ctx = tls_server()) == NULL)
554 fatal("tls_server failure");
555 TAILQ_INSERT_HEAD(&conf->addrs, addr, addrs);
558 case IMSG_RECONF_FCGI:
559 IMSG_SIZE_CHECK(imsg, fcgi);
560 fcgi = xcalloc(1, sizeof(*fcgi));
561 memcpy(fcgi, imsg->data, datalen);
562 log_debug("received fcgi %s", fcgi->path);
563 TAILQ_INSERT_TAIL(&conf->fcgi, fcgi, fcgi);
566 case IMSG_RECONF_HOST:
567 IMSG_SIZE_CHECK(imsg, &vht);
568 memcpy(&vht, imsg->data, datalen);
570 strlcpy(vh->domain, vht.domain, sizeof(vh->domain));
572 TAILQ_INSERT_TAIL(&conf->hosts, h, vhosts);
574 /* reset location and proxy */
579 case IMSG_RECONF_CERT:
580 log_debug("receiving cert");
581 if (privsep_process == PROC_CRYPTO)
582 return config_crypto_recv_kp(conf, imsg);
584 fatalx("recv'd cert without host");
586 fatalx("cert already received");
588 fatalx("no fd for IMSG_RECONF_CERT");
589 if (load_file(imsg->fd, &h->cert, &h->certlen) == -1)
590 fatalx("failed to load cert for %s",
594 case IMSG_RECONF_KEY:
595 log_debug("receiving key");
596 if (privsep_process == PROC_CRYPTO)
597 return config_crypto_recv_kp(conf, imsg);
599 fatalx("recv'd key without host");
601 fatalx("key already received");
603 fatalx("no fd for IMSG_RECONF_KEY");
604 if (load_file(imsg->fd, &h->key, &h->keylen) == -1)
605 fatalx("failed to load key for %s",
609 case IMSG_RECONF_OCSP:
610 log_debug("receiving ocsp");
612 fatalx("recv'd ocsp without host");
614 fatalx("ocsp already received");
616 fatalx("no fd for IMSG_RECONF_OCSP");
617 if (load_file(imsg->fd, &h->ocsp, &h->ocsplen) == -1)
618 fatalx("failed to load ocsp for %s",
622 case IMSG_RECONF_HOST_ADDR:
623 log_debug("receiving host addr");
625 fatalx("recv'd host address withouth host");
626 IMSG_SIZE_CHECK(imsg, addr);
627 addr = xcalloc(1, sizeof(*addr));
628 memcpy(addr, imsg->data, datalen);
629 TAILQ_INSERT_TAIL(&h->addrs, addr, addrs);
632 case IMSG_RECONF_LOC:
634 fatalx("recv'd location without host");
635 IMSG_SIZE_CHECK(imsg, loc);
636 loc = xcalloc(1, sizeof(*loc));
637 memcpy(loc, imsg->data, datalen);
638 TAILQ_INIT(&loc->params);
640 if (imsg->fd != -1) {
641 if (load_file(imsg->fd, &d, &len) == -1)
643 loc->reqca = load_ca(d, len);
644 if (loc->reqca == NULL)
645 fatalx("failed to load CA");
650 TAILQ_INSERT_TAIL(&h->locations, loc, locations);
653 case IMSG_RECONF_ENV:
655 fatalx("recv'd env without location");
656 IMSG_SIZE_CHECK(imsg, env);
657 env = xcalloc(1, sizeof(*env));
658 memcpy(env, imsg->data, datalen);
659 TAILQ_INSERT_TAIL(&l->params, env, envs);
662 case IMSG_RECONF_ALIAS:
664 fatalx("recv'd alias without host");
665 IMSG_SIZE_CHECK(imsg, alias);
666 alias = xcalloc(1, sizeof(*alias));
667 memcpy(alias, imsg->data, datalen);
668 TAILQ_INSERT_TAIL(&h->aliases, alias, aliases);
671 case IMSG_RECONF_PROXY:
672 log_debug("receiving proxy");
674 fatalx("recv'd proxy without host");
675 IMSG_SIZE_CHECK(imsg, proxy);
676 proxy = xcalloc(1, sizeof(*proxy));
677 memcpy(proxy, imsg->data, datalen);
679 if (imsg->fd != -1) {
680 if (load_file(imsg->fd, &d, &len) == -1)
682 proxy->reqca = load_ca(d, len);
683 if (proxy->reqca == NULL)
684 fatal("failed to load CA");
688 TAILQ_INSERT_TAIL(&h->proxies, proxy, proxies);
692 case IMSG_RECONF_PROXY_CERT:
693 log_debug("receiving proxy cert");
695 fatalx("recv'd proxy cert without proxy");
697 fatalx("proxy cert already received");
699 fatalx("no fd for IMSG_RECONF_PROXY_CERT");
700 if (load_file(imsg->fd, &p->cert, &p->certlen) == -1)
701 fatalx("failed to load cert for proxy %s of %s",
705 case IMSG_RECONF_PROXY_KEY:
706 log_debug("receiving proxy key");
708 fatalx("recv'd proxy key without proxy");
710 fatalx("proxy key already received");
712 fatalx("no fd for IMSG_RECONF_PROXY_KEY");
713 if (load_file(imsg->fd, &p->key, &p->keylen) == -1)
714 fatalx("failed to load key for proxy %s of %s",
718 case IMSG_RECONF_END:
719 if (proc_compose(ps, PROC_PARENT, IMSG_RECONF_DONE,