Blob


1 /*
2 * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
3 *
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.
7 *
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.
15 */
17 #include "gmid.h"
19 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <limits.h>
23 #include <string.h>
25 #include <openssl/pem.h>
27 #include "log.h"
28 #include "proc.h"
30 struct conf *
31 config_new(void)
32 {
33 struct conf *conf;
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);
46 conf->prefork = 3;
48 #ifdef __OpenBSD__
49 conf->use_privsep_crypto = 1;
50 #endif
52 return conf;
53 }
55 void
56 config_purge(struct conf *conf)
57 {
58 struct privsep *ps;
59 struct fcgi *f, *tf;
60 struct vhost *h, *th;
61 struct location *l, *tl;
62 struct proxy *p, *tp;
63 struct envlist *e, *te;
64 struct alist *a, *ta;
65 struct pki *pki, *tpki;
66 struct address *addr, *taddr;
67 int use_privsep_crypto;
69 ps = conf->ps;
70 use_privsep_crypto = conf->use_privsep_crypto;
72 free(conf->log_access);
73 free_mime(&conf->mime);
74 TAILQ_FOREACH_SAFE(f, &conf->fcgi, fcgi, tf) {
75 TAILQ_REMOVE(&conf->fcgi, f, fcgi);
76 free(f);
77 }
79 TAILQ_FOREACH_SAFE(h, &conf->hosts, vhosts, th) {
80 free(h->cert_path);
81 free(h->key_path);
82 free(h->ocsp_path);
83 free(h->cert);
84 free(h->key);
85 free(h->ocsp);
87 TAILQ_FOREACH_SAFE(addr, &h->addrs, addrs, taddr) {
88 TAILQ_REMOVE(&h->addrs, addr, addrs);
89 free(addr);
90 }
92 TAILQ_FOREACH_SAFE(l, &h->locations, locations, tl) {
93 TAILQ_REMOVE(&h->locations, l, locations);
95 if (l->dirfd != -1)
96 close(l->dirfd);
98 free(l->reqca_path);
99 X509_STORE_free(l->reqca);
101 TAILQ_FOREACH_SAFE(e, &l->params, envs, te) {
102 TAILQ_REMOVE(&l->params, e, envs);
103 free(e);
106 free(l);
109 TAILQ_FOREACH_SAFE(a, &h->aliases, aliases, ta) {
110 TAILQ_REMOVE(&h->aliases, a, aliases);
111 free(a);
114 TAILQ_FOREACH_SAFE(p, &h->proxies, proxies, tp) {
115 TAILQ_REMOVE(&h->proxies, p, proxies);
116 free(p->cert_path);
117 free(p->cert);
118 free(p->key_path);
119 free(p->key);
120 free(p->reqca_path);
121 X509_STORE_free(p->reqca);
122 free(p);
125 TAILQ_REMOVE(&conf->hosts, h, vhosts);
126 free(h);
129 TAILQ_FOREACH_SAFE(pki, &conf->pkis, pkis, tpki) {
130 TAILQ_REMOVE(&conf->pkis, pki, pkis);
131 free(pki->hash);
132 EVP_PKEY_free(pki->pkey);
133 free(pki);
136 TAILQ_FOREACH_SAFE(addr, &conf->addrs, addrs, taddr) {
137 TAILQ_REMOVE(&conf->addrs, addr, addrs);
138 if (addr->sock != -1) {
139 close(addr->sock);
140 event_del(&addr->evsock);
141 tls_free(addr->ctx);
143 free(addr);
146 memset(conf, 0, sizeof(*conf));
148 conf->ps = ps;
149 conf->use_privsep_crypto = use_privsep_crypto;
150 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
151 init_mime(&conf->mime);
152 TAILQ_INIT(&conf->fcgi);
153 TAILQ_INIT(&conf->hosts);
154 TAILQ_INIT(&conf->pkis);
157 static int
158 config_send_file(struct privsep *ps, enum privsep_procid id, int type,
159 int fd, void *data, size_t l)
161 int n, m, d;
163 n = -1;
164 proc_range(ps, id, &n, &m);
165 for (n = 0; n < m; ++n) {
166 d = -1;
167 if (fd != -1 && (d = dup(fd)) == -1)
168 fatal("dup %d", fd);
169 if (proc_compose_imsg(ps, id, n, type, -1, d, data, l)
170 == -1)
171 return -1;
174 if (fd != -1)
175 close(fd);
177 /* avoid fd rampage */
178 if (proc_flush_imsg(ps, id, -1) == -1) {
179 log_warn("%s: proc_fush_imsg", __func__);
180 return -1;
183 return 0;
186 static int
187 config_open_send(struct privsep *ps, enum privsep_procid id, int type,
188 const char *path)
190 int fd;
192 log_debug("sending %s", path);
194 if ((fd = open(path, O_RDONLY)) == -1)
195 fatal("can't open %s", path);
197 return config_send_file(ps, id, type, fd, NULL, 0);
200 static int
201 config_send_kp(struct privsep *ps, int cert_type, int key_type,
202 const char *cert, const char *key)
204 struct conf *conf = ps->ps_env;
205 int fd, d, key_target;
207 log_debug("sending %s", cert);
208 if ((fd = open(cert, O_RDONLY)) == -1)
209 fatal("can't open %s", cert);
210 if ((d = dup(fd)) == -1)
211 fatal("fd");
213 if (config_send_file(ps, PROC_SERVER, cert_type, fd, NULL, 0) == -1) {
214 close(d);
215 return -1;
217 if (conf->use_privsep_crypto &&
218 config_send_file(ps, PROC_CRYPTO, cert_type, d, NULL, 0) == -1)
219 return -1;
221 key_target = PROC_CRYPTO;
222 if (!conf->use_privsep_crypto)
223 key_target = PROC_SERVER;
225 if (config_open_send(ps, key_target, key_type, key) == -1)
226 return -1;
228 return 0;
231 static int
232 config_send_socks(struct conf *conf)
234 struct privsep *ps = conf->ps;
235 struct address *addr, a;
236 int sock, v;
238 TAILQ_FOREACH(addr, &conf->addrs, addrs) {
239 sock = socket(addr->ai_family, addr->ai_socktype,
240 addr->ai_protocol);
241 if (sock == -1)
242 fatal("socket");
244 v = 1;
245 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v))
246 == -1)
247 fatal("setsockopt(SO_REUSEADDR)");
249 v = 1;
250 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &v, sizeof(v))
251 == -1)
252 fatal("setsockopt(SO_REUSEPORT)");
254 mark_nonblock(sock);
256 if (bind(sock, (struct sockaddr *)&addr->ss, addr->slen)
257 == -1)
258 fatal("bind");
260 if (listen(sock, 16) == -1)
261 fatal("listen");
263 memcpy(&a, addr, sizeof(a));
264 a.conf = NULL;
265 a.sock = -1;
266 memset(&a.evsock, 0, sizeof(a.evsock));
267 memset(&a.addrs, 0, sizeof(a.addrs));
269 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_SOCK, sock,
270 &a, sizeof(a)) == -1)
271 return -1;
274 return 0;
277 int
278 config_send(struct conf *conf)
280 struct privsep *ps = conf->ps;
281 struct etm *m;
282 struct fcgi *fcgi;
283 struct vhost *h;
284 struct location *l;
285 struct proxy *p;
286 struct envlist *e;
287 struct alist *a;
288 size_t i;
290 for (i = 0; i < conf->mime.len; ++i) {
291 m = &conf->mime.t[i];
292 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_MIME,
293 m, sizeof(*m)) == -1)
294 return -1;
297 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PROTOS,
298 &conf->protos, sizeof(conf->protos)) == -1)
299 return -1;
301 if (config_send_socks(conf) == -1)
302 return -1;
304 TAILQ_FOREACH(fcgi, &conf->fcgi, fcgi) {
305 log_debug("sending fastcgi %s", fcgi->path);
306 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_FCGI,
307 fcgi, sizeof(*fcgi)) == -1)
308 return -1;
311 TAILQ_FOREACH(h, &conf->hosts, vhosts) {
312 struct vhost vcopy;
313 struct address *addr, acopy;
315 memcpy(&vcopy, h, sizeof(vcopy));
316 vcopy.cert_path = NULL;
317 vcopy.key_path = NULL;
318 vcopy.ocsp_path = NULL;
320 log_debug("sending host %s", h->domain);
322 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_HOST,
323 &vcopy, sizeof(vcopy)) == -1)
324 return -1;
326 if (config_send_kp(ps, IMSG_RECONF_CERT, IMSG_RECONF_KEY,
327 h->cert_path, h->key_path) == -1)
328 return -1;
330 if (h->ocsp_path != NULL) {
331 if (config_open_send(ps, PROC_SERVER, IMSG_RECONF_OCSP,
332 h->ocsp_path) == -1)
333 return -1;
336 TAILQ_FOREACH(addr, &h->addrs, addrs) {
337 memcpy(&acopy, addr, sizeof(acopy));
338 memset(&acopy.addrs, 0, sizeof(acopy.addrs));
340 if (proc_compose(ps, PROC_SERVER,
341 IMSG_RECONF_HOST_ADDR, &acopy, sizeof(acopy))
342 == -1)
343 return -1;
346 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1) {
347 log_warn("%s: proc_fush_imsg", __func__);
348 return -1;
351 TAILQ_FOREACH(l, &h->locations, locations) {
352 struct location lcopy;
353 int fd = -1;
355 memcpy(&lcopy, l, sizeof(lcopy));
356 lcopy.reqca_path = NULL;
357 lcopy.reqca = NULL;
358 lcopy.dirfd = -1;
359 memset(&lcopy.locations, 0, sizeof(lcopy.locations));
361 if (l->reqca_path != NULL &&
362 (fd = open(l->reqca_path, O_RDONLY)) == -1)
363 fatal("can't open %s", l->reqca_path);
365 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_LOC,
366 fd, &lcopy, sizeof(lcopy)) == -1)
367 return -1;
369 TAILQ_FOREACH(e, &l->params, envs) {
370 if (proc_compose(ps, PROC_SERVER,
371 IMSG_RECONF_ENV, e, sizeof(*e)) == -1)
372 return -1;
376 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
377 return -1;
379 TAILQ_FOREACH(a, &h->aliases, aliases) {
380 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ALIAS,
381 a, sizeof(*a)) == -1)
382 return -1;
385 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
386 return -1;
388 TAILQ_FOREACH(p, &h->proxies, proxies) {
389 struct proxy pcopy;
390 int fd = -1;
392 memcpy(&pcopy, p, sizeof(pcopy));
393 pcopy.cert_path = NULL;
394 pcopy.cert = NULL;
395 pcopy.certlen = 0;
396 pcopy.key_path = NULL;
397 pcopy.key = NULL;
398 pcopy.keylen = 0;
399 pcopy.reqca_path = NULL;
400 pcopy.reqca = NULL;
402 if (p->reqca_path != NULL) {
403 fd = open(p->reqca_path, O_RDONLY);
404 if (fd == -1)
405 fatal("can't open %s", p->reqca_path);
408 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_PROXY,
409 fd, &pcopy, sizeof(pcopy)) == -1)
410 return -1;
412 if (p->cert_path == NULL || p->key_path == NULL)
413 continue;
415 if (config_open_send(ps, PROC_SERVER,
416 IMSG_RECONF_PROXY_CERT, p->cert_path) == -1 ||
417 config_open_send(ps, PROC_SERVER,
418 IMSG_RECONF_PROXY_KEY, p->key_path) == -1)
419 return -1;
423 return 0;
426 static int
427 load_file(int fd, uint8_t **data, size_t *len)
429 struct stat sb;
430 ssize_t r;
432 if (fstat(fd, &sb) == -1)
433 fatal("fstat");
435 if (sb.st_size < 0 /* || sb.st_size > SIZE_MAX */) {
436 log_warnx("file too large");
437 close(fd);
438 return -1;
440 *len = sb.st_size;
442 if ((*data = malloc(*len)) == NULL)
443 fatal("malloc");
445 r = pread(fd, *data, *len, 0);
446 if (r == -1 || (size_t)r != *len) {
447 log_warn("read failed");
448 close(fd);
449 free(*data);
450 return -1;
453 close(fd);
454 return 0;
457 static int
458 config_crypto_recv_kp(struct conf *conf, struct imsg *imsg)
460 static struct pki *pki;
461 uint8_t *d;
462 size_t len;
464 /* XXX: check for duplicates */
466 if (imsg->fd == -1)
467 fatalx("no fd for imsg %d", imsg->hdr.type);
469 switch (imsg->hdr.type) {
470 case IMSG_RECONF_CERT:
471 if (pki != NULL)
472 fatalx("imsg in wrong order; pki is not NULL");
473 if ((pki = calloc(1, sizeof(*pki))) == NULL)
474 fatal("calloc");
475 if (load_file(imsg->fd, &d, &len) == -1)
476 fatalx("can't load file");
477 if ((pki->hash = ssl_pubkey_hash(d, len)) == NULL)
478 fatalx("failed to compute cert hash");
479 free(d);
480 TAILQ_INSERT_TAIL(&conf->pkis, pki, pkis);
481 break;
483 case IMSG_RECONF_KEY:
484 if (pki == NULL)
485 fatalx("got key without cert beforehand %d",
486 imsg->hdr.type);
487 if (load_file(imsg->fd, &d, &len) == -1)
488 fatalx("failed to load private key");
489 if ((pki->pkey = ssl_load_pkey(d, len)) == NULL)
490 fatalx("failed load private key");
491 free(d);
492 pki = NULL;
493 break;
495 default:
496 return -1;
499 return 0;
502 int
503 config_recv(struct conf *conf, struct imsg *imsg)
505 static struct vhost *h;
506 static struct location *l;
507 static struct proxy *p;
508 struct privsep *ps = conf->ps;
509 struct etm m;
510 struct fcgi *fcgi;
511 struct vhost *vh, vht;
512 struct location *loc;
513 struct envlist *env;
514 struct alist *alias;
515 struct proxy *proxy;
516 struct address *addr;
517 uint8_t *d;
518 size_t len, datalen;
520 datalen = IMSG_DATA_SIZE(imsg);
522 switch (imsg->hdr.type) {
523 case IMSG_RECONF_START:
524 config_purge(conf);
525 h = NULL;
526 p = NULL;
527 break;
529 case IMSG_RECONF_MIME:
530 IMSG_SIZE_CHECK(imsg, &m);
531 memcpy(&m, imsg->data, datalen);
532 if (m.mime[sizeof(m.mime) - 1] != '\0' ||
533 m.ext[sizeof(m.ext) - 1] != '\0')
534 fatal("received corrupted IMSG_RECONF_MIME");
535 if (add_mime(&conf->mime, m.mime, m.ext) == -1)
536 fatal("failed to add mime mapping %s -> %s",
537 m.mime, m.ext);
538 break;
540 case IMSG_RECONF_PROTOS:
541 IMSG_SIZE_CHECK(imsg, &conf->protos);
542 memcpy(&conf->protos, imsg->data, datalen);
543 break;
545 case IMSG_RECONF_SOCK:
546 addr = xcalloc(1, sizeof(*addr));
547 IMSG_SIZE_CHECK(imsg, addr);
548 memcpy(addr, imsg->data, sizeof(*addr));
549 if (imsg->fd == -1)
550 fatalx("missing socket for IMSG_RECONF_SOCK");
551 addr->conf = conf;
552 addr->sock = imsg->fd;
553 event_set(&addr->evsock, addr->sock, EV_READ|EV_PERSIST,
554 server_accept, addr);
555 if ((addr->ctx = tls_server()) == NULL)
556 fatal("tls_server failure");
557 TAILQ_INSERT_HEAD(&conf->addrs, addr, addrs);
558 break;
560 case IMSG_RECONF_FCGI:
561 IMSG_SIZE_CHECK(imsg, fcgi);
562 fcgi = xcalloc(1, sizeof(*fcgi));
563 memcpy(fcgi, imsg->data, datalen);
564 log_debug("received fcgi %s", fcgi->path);
565 TAILQ_INSERT_TAIL(&conf->fcgi, fcgi, fcgi);
566 break;
568 case IMSG_RECONF_HOST:
569 IMSG_SIZE_CHECK(imsg, &vht);
570 memcpy(&vht, imsg->data, datalen);
571 vh = new_vhost();
572 strlcpy(vh->domain, vht.domain, sizeof(vh->domain));
573 h = vh;
574 TAILQ_INSERT_TAIL(&conf->hosts, h, vhosts);
576 /* reset location and proxy */
577 l = NULL;
578 p = NULL;
579 break;
581 case IMSG_RECONF_CERT:
582 log_debug("receiving cert");
583 if (privsep_process == PROC_CRYPTO)
584 return config_crypto_recv_kp(conf, imsg);
585 if (h == NULL)
586 fatalx("recv'd cert without host");
587 if (h->cert != NULL)
588 fatalx("cert already received");
589 if (imsg->fd == -1)
590 fatalx("no fd for IMSG_RECONF_CERT");
591 if (load_file(imsg->fd, &h->cert, &h->certlen) == -1)
592 fatalx("failed to load cert for %s",
593 h->domain);
594 break;
596 case IMSG_RECONF_KEY:
597 log_debug("receiving key");
598 if (privsep_process == PROC_CRYPTO)
599 return config_crypto_recv_kp(conf, imsg);
600 if (h == NULL)
601 fatalx("recv'd key without host");
602 if (h->key != NULL)
603 fatalx("key already received");
604 if (imsg->fd == -1)
605 fatalx("no fd for IMSG_RECONF_KEY");
606 if (load_file(imsg->fd, &h->key, &h->keylen) == -1)
607 fatalx("failed to load key for %s",
608 h->domain);
609 break;
611 case IMSG_RECONF_OCSP:
612 log_debug("receiving ocsp");
613 if (h == NULL)
614 fatalx("recv'd ocsp without host");
615 if (h->ocsp != NULL)
616 fatalx("ocsp already received");
617 if (imsg->fd == -1)
618 fatalx("no fd for IMSG_RECONF_OCSP");
619 if (load_file(imsg->fd, &h->ocsp, &h->ocsplen) == -1)
620 fatalx("failed to load ocsp for %s",
621 h->domain);
622 break;
624 case IMSG_RECONF_HOST_ADDR:
625 log_debug("receiving host addr");
626 if (h == NULL)
627 fatalx("recv'd host address withouth host");
628 IMSG_SIZE_CHECK(imsg, addr);
629 addr = xcalloc(1, sizeof(*addr));
630 memcpy(addr, imsg->data, datalen);
631 TAILQ_INSERT_TAIL(&h->addrs, addr, addrs);
632 break;
634 case IMSG_RECONF_LOC:
635 if (h == NULL)
636 fatalx("recv'd location without host");
637 IMSG_SIZE_CHECK(imsg, loc);
638 loc = xcalloc(1, sizeof(*loc));
639 memcpy(loc, imsg->data, datalen);
640 TAILQ_INIT(&loc->params);
642 if (imsg->fd != -1) {
643 if (load_file(imsg->fd, &d, &len) == -1)
644 fatal("load_file");
645 loc->reqca = load_ca(d, len);
646 if (loc->reqca == NULL)
647 fatalx("failed to load CA");
648 free(d);
651 l = loc;
652 TAILQ_INSERT_TAIL(&h->locations, loc, locations);
653 break;
655 case IMSG_RECONF_ENV:
656 if (l == NULL)
657 fatalx("recv'd env without location");
658 IMSG_SIZE_CHECK(imsg, env);
659 env = xcalloc(1, sizeof(*env));
660 memcpy(env, imsg->data, datalen);
661 TAILQ_INSERT_TAIL(&l->params, env, envs);
662 break;
664 case IMSG_RECONF_ALIAS:
665 if (h == NULL)
666 fatalx("recv'd alias without host");
667 IMSG_SIZE_CHECK(imsg, alias);
668 alias = xcalloc(1, sizeof(*alias));
669 memcpy(alias, imsg->data, datalen);
670 TAILQ_INSERT_TAIL(&h->aliases, alias, aliases);
671 break;
673 case IMSG_RECONF_PROXY:
674 log_debug("receiving proxy");
675 if (h == NULL)
676 fatalx("recv'd proxy without host");
677 IMSG_SIZE_CHECK(imsg, proxy);
678 proxy = xcalloc(1, sizeof(*proxy));
679 memcpy(proxy, imsg->data, datalen);
681 if (imsg->fd != -1) {
682 if (load_file(imsg->fd, &d, &len) == -1)
683 fatal("load_file");
684 proxy->reqca = load_ca(d, len);
685 if (proxy->reqca == NULL)
686 fatal("failed to load CA");
687 free(d);
690 TAILQ_INSERT_TAIL(&h->proxies, proxy, proxies);
691 p = proxy;
692 break;
694 case IMSG_RECONF_PROXY_CERT:
695 log_debug("receiving proxy cert");
696 if (p == NULL)
697 fatalx("recv'd proxy cert without proxy");
698 if (p->cert != NULL)
699 fatalx("proxy cert already received");
700 if (imsg->fd == -1)
701 fatalx("no fd for IMSG_RECONF_PROXY_CERT");
702 if (load_file(imsg->fd, &p->cert, &p->certlen) == -1)
703 fatalx("failed to load cert for proxy %s of %s",
704 p->host, h->domain);
705 break;
707 case IMSG_RECONF_PROXY_KEY:
708 log_debug("receiving proxy key");
709 if (p == NULL)
710 fatalx("recv'd proxy key without proxy");
711 if (p->key != NULL)
712 fatalx("proxy key already received");
713 if (imsg->fd == -1)
714 fatalx("no fd for IMSG_RECONF_PROXY_KEY");
715 if (load_file(imsg->fd, &p->key, &p->keylen) == -1)
716 fatalx("failed to load key for proxy %s of %s",
717 p->host, h->domain);
718 break;
720 case IMSG_RECONF_END:
721 if (proc_compose(ps, PROC_PARENT, IMSG_RECONF_DONE,
722 NULL, 0) == -1)
723 return -1;
724 break;
726 default:
727 return -1;
730 return 0;