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_mime(&conf->mime);
73 TAILQ_FOREACH_SAFE(f, &conf->fcgi, fcgi, tf) {
74 TAILQ_REMOVE(&conf->fcgi, f, fcgi);
75 free(f);
76 }
78 TAILQ_FOREACH_SAFE(h, &conf->hosts, vhosts, th) {
79 free(h->cert_path);
80 free(h->key_path);
81 free(h->ocsp_path);
82 free(h->cert);
83 free(h->key);
84 free(h->ocsp);
86 TAILQ_FOREACH_SAFE(addr, &h->addrs, addrs, taddr) {
87 TAILQ_REMOVE(&h->addrs, addr, addrs);
88 free(addr);
89 }
91 TAILQ_FOREACH_SAFE(l, &h->locations, locations, tl) {
92 TAILQ_REMOVE(&h->locations, l, locations);
94 if (l->dirfd != -1)
95 close(l->dirfd);
97 free(l->reqca_path);
98 X509_STORE_free(l->reqca);
99 free(l);
102 TAILQ_FOREACH_SAFE(e, &h->params, envs, te) {
103 TAILQ_REMOVE(&h->params, e, envs);
104 free(e);
107 TAILQ_FOREACH_SAFE(a, &h->aliases, aliases, ta) {
108 TAILQ_REMOVE(&h->aliases, a, aliases);
109 free(a);
112 TAILQ_FOREACH_SAFE(p, &h->proxies, proxies, tp) {
113 TAILQ_REMOVE(&h->proxies, p, proxies);
114 free(p->cert_path);
115 free(p->cert);
116 free(p->key_path);
117 free(p->key);
118 free(p->reqca_path);
119 X509_STORE_free(p->reqca);
120 free(p);
123 TAILQ_REMOVE(&conf->hosts, h, vhosts);
124 free(h);
127 TAILQ_FOREACH_SAFE(pki, &conf->pkis, pkis, tpki) {
128 TAILQ_REMOVE(&conf->pkis, pki, pkis);
129 free(pki->hash);
130 EVP_PKEY_free(pki->pkey);
131 free(pki);
134 TAILQ_FOREACH_SAFE(addr, &conf->addrs, addrs, taddr) {
135 TAILQ_REMOVE(&conf->addrs, addr, addrs);
136 if (addr->sock != -1) {
137 close(addr->sock);
138 event_del(&addr->evsock);
140 free(addr);
143 memset(conf, 0, sizeof(*conf));
145 conf->ps = ps;
146 conf->use_privsep_crypto = use_privsep_crypto;
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);
154 static int
155 config_send_file(struct privsep *ps, enum privsep_procid id, int type,
156 int fd, void *data, size_t l)
158 int n, m, d;
160 n = -1;
161 proc_range(ps, id, &n, &m);
162 for (n = 0; n < m; ++n) {
163 d = -1;
164 if (fd != -1 && (d = dup(fd)) == -1)
165 fatal("dup %d", fd);
166 if (proc_compose_imsg(ps, id, n, type, -1, d, data, l)
167 == -1)
168 return -1;
171 if (fd != -1)
172 close(fd);
173 return 0;
176 static int
177 config_open_send(struct privsep *ps, enum privsep_procid id, int type,
178 const char *path)
180 int fd;
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);
190 static int
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)
201 fatal("fd");
203 if (config_send_file(ps, PROC_SERVER, cert_type, fd, NULL, 0) == -1) {
204 close(d);
205 return -1;
207 if (conf->use_privsep_crypto &&
208 config_send_file(ps, PROC_CRYPTO, cert_type, d, NULL, 0) == -1)
209 return -1;
211 key_target = PROC_CRYPTO;
212 if (!conf->use_privsep_crypto)
213 key_target = PROC_SERVER;
215 if (config_open_send(ps, key_target, key_type, key) == -1)
216 return -1;
218 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
219 return -1;
220 if (proc_flush_imsg(ps, PROC_CRYPTO, -1) == -1)
221 return -1;
222 return 0;
225 static int
226 config_send_socks(struct conf *conf)
228 struct privsep *ps = conf->ps;
229 struct address *addr, a;
230 int sock, v;
232 TAILQ_FOREACH(addr, &conf->addrs, addrs) {
233 sock = socket(addr->ai_family, addr->ai_socktype,
234 addr->ai_protocol);
235 if (sock == -1)
236 fatal("socket");
238 v = 1;
239 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v))
240 == -1)
241 fatal("setsockopt(SO_REUSEADDR)");
243 v = 1;
244 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &v, sizeof(v))
245 == -1)
246 fatal("setsockopt(SO_REUSEPORT)");
248 mark_nonblock(sock);
250 if (bind(sock, (struct sockaddr *)&addr->ss, addr->slen)
251 == -1)
252 fatal("bind");
254 if (listen(sock, 16) == -1)
255 fatal("listen");
257 memcpy(&a, addr, sizeof(a));
258 a.conf = NULL;
259 a.sock = -1;
260 memset(&a.evsock, 0, sizeof(a.evsock));
261 memset(&a.addrs, 0, sizeof(a.addrs));
263 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_SOCK, sock,
264 &a, sizeof(a)) == -1)
265 return -1;
268 return 0;
271 int
272 config_send(struct conf *conf)
274 struct privsep *ps = conf->ps;
275 struct etm *m;
276 struct fcgi *fcgi;
277 struct vhost *h;
278 struct location *l;
279 struct proxy *p;
280 struct envlist *e;
281 struct alist *a;
282 size_t i;
284 for (i = 0; i < conf->mime.len; ++i) {
285 m = &conf->mime.t[i];
286 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_MIME,
287 m, sizeof(*m)) == -1)
288 return -1;
291 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PROTOS,
292 &conf->protos, sizeof(conf->protos)) == -1)
293 return -1;
295 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
296 return -1;
298 if (config_send_socks(conf) == -1)
299 return -1;
301 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -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;
314 memcpy(&vcopy, h, sizeof(vcopy));
315 vcopy.cert_path = NULL;
316 vcopy.key_path = NULL;
317 vcopy.ocsp_path = NULL;
319 log_debug("sending host %s", h->domain);
321 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_HOST,
322 &vcopy, sizeof(vcopy)) == -1)
323 return -1;
325 if (config_send_kp(ps, IMSG_RECONF_CERT, IMSG_RECONF_KEY,
326 h->cert_path, h->key_path) == -1)
327 return -1;
329 if (h->ocsp_path != NULL) {
330 if (config_open_send(ps, PROC_SERVER, IMSG_RECONF_OCSP,
331 h->ocsp_path) == -1)
332 return -1;
333 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
334 return -1;
337 TAILQ_FOREACH(l, &h->locations, locations) {
338 struct location lcopy;
339 int fd = -1;
341 memcpy(&lcopy, l, sizeof(lcopy));
342 lcopy.reqca_path = NULL;
343 lcopy.reqca = NULL;
344 lcopy.dirfd = -1;
345 memset(&lcopy.locations, 0, sizeof(lcopy.locations));
347 if (l->reqca_path != NULL &&
348 (fd = open(l->reqca_path, O_RDONLY)) == -1)
349 fatal("can't open %s", l->reqca_path);
351 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_LOC,
352 fd, &lcopy, sizeof(lcopy)) == -1)
353 return -1;
356 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
357 return -1;
359 TAILQ_FOREACH(e, &h->params, envs) {
360 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ENV,
361 e, sizeof(*e)) == -1)
362 return -1;
365 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
366 return -1;
368 TAILQ_FOREACH(a, &h->aliases, aliases) {
369 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ALIAS,
370 a, sizeof(*a)) == -1)
371 return -1;
374 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
375 return -1;
377 TAILQ_FOREACH(p, &h->proxies, proxies) {
378 struct proxy pcopy;
379 int fd = -1;
381 memcpy(&pcopy, p, sizeof(pcopy));
382 pcopy.cert_path = NULL;
383 pcopy.cert = NULL;
384 pcopy.certlen = 0;
385 pcopy.key_path = NULL;
386 pcopy.key = NULL;
387 pcopy.keylen = 0;
388 pcopy.reqca_path = NULL;
389 pcopy.reqca = NULL;
391 if (p->reqca_path != NULL) {
392 fd = open(p->reqca_path, O_RDONLY);
393 if (fd == -1)
394 fatal("can't open %s", p->reqca_path);
397 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_PROXY,
398 fd, &pcopy, sizeof(pcopy)) == -1)
399 return -1;
401 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
402 return -1;
404 if (p->cert_path == NULL || p->key_path == NULL)
405 continue;
407 if (config_open_send(ps, PROC_SERVER,
408 IMSG_RECONF_PROXY_CERT, p->cert_path) == -1 ||
409 config_open_send(ps, PROC_SERVER,
410 IMSG_RECONF_PROXY_KEY, p->key_path) == -1)
411 return -1;
413 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
414 return -1;
417 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
418 return -1;
421 return 0;
424 static int
425 load_file(int fd, uint8_t **data, size_t *len)
427 struct stat sb;
428 ssize_t r;
430 if (fstat(fd, &sb) == -1)
431 fatal("fstat");
433 if (sb.st_size < 0 /* || sb.st_size > SIZE_MAX */) {
434 log_warnx("file too large");
435 close(fd);
436 return -1;
438 *len = sb.st_size;
440 if ((*data = malloc(*len)) == NULL)
441 fatal("malloc");
443 r = pread(fd, *data, *len, 0);
444 if (r == -1 || (size_t)r != *len) {
445 log_warn("read failed");
446 close(fd);
447 free(*data);
448 return -1;
451 close(fd);
452 return 0;
455 static int
456 config_crypto_recv_kp(struct conf *conf, struct imsg *imsg)
458 static struct pki *pki;
459 uint8_t *d;
460 size_t len;
462 /* XXX: check for duplicates */
464 if (imsg->fd == -1)
465 fatalx("no fd for imsg %d", imsg->hdr.type);
467 switch (imsg->hdr.type) {
468 case IMSG_RECONF_CERT:
469 if (pki != NULL)
470 fatalx("imsg in wrong order; pki is not NULL");
471 if ((pki = calloc(1, sizeof(*pki))) == NULL)
472 fatal("calloc");
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");
477 free(d);
478 TAILQ_INSERT_TAIL(&conf->pkis, pki, pkis);
479 break;
481 case IMSG_RECONF_KEY:
482 if (pki == NULL)
483 fatalx("got key without cert beforehand %d",
484 imsg->hdr.type);
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");
489 free(d);
490 pki = NULL;
491 break;
493 default:
494 return -1;
497 return 0;
500 int
501 config_recv(struct conf *conf, struct imsg *imsg)
503 static struct vhost *h;
504 static struct proxy *p;
505 struct privsep *ps = conf->ps;
506 struct etm m;
507 struct fcgi *fcgi;
508 struct vhost *vh, vht;
509 struct location *loc;
510 struct envlist *env;
511 struct alist *alias;
512 struct proxy *proxy;
513 struct address *addr;
514 uint8_t *d;
515 size_t len, datalen;
517 datalen = IMSG_DATA_SIZE(imsg);
519 switch (imsg->hdr.type) {
520 case IMSG_RECONF_START:
521 config_purge(conf);
522 h = NULL;
523 p = NULL;
524 break;
526 case IMSG_RECONF_MIME:
527 IMSG_SIZE_CHECK(imsg, &m);
528 memcpy(&m, imsg->data, datalen);
529 if (m.mime[sizeof(m.mime) - 1] != '\0' ||
530 m.ext[sizeof(m.ext) - 1] != '\0')
531 fatal("received corrupted IMSG_RECONF_MIME");
532 if (add_mime(&conf->mime, m.mime, m.ext) == -1)
533 fatal("failed to add mime mapping %s -> %s",
534 m.mime, m.ext);
535 break;
537 case IMSG_RECONF_PROTOS:
538 IMSG_SIZE_CHECK(imsg, &conf->protos);
539 memcpy(&conf->protos, imsg->data, datalen);
540 break;
542 case IMSG_RECONF_SOCK:
543 addr = xcalloc(1, sizeof(*addr));
544 IMSG_SIZE_CHECK(imsg, addr);
545 memcpy(addr, imsg->data, sizeof(*addr));
546 if (imsg->fd == -1)
547 fatalx("missing socket for IMSG_RECONF_SOCK4");
548 addr->conf = conf;
549 addr->sock = imsg->fd;
550 event_set(&addr->evsock, addr->sock, EV_READ|EV_PERSIST,
551 do_accept, addr);
552 TAILQ_INSERT_HEAD(&conf->addrs, addr, addrs);
553 break;
555 case IMSG_RECONF_FCGI:
556 IMSG_SIZE_CHECK(imsg, fcgi);
557 fcgi = xcalloc(1, sizeof(*fcgi));
558 memcpy(fcgi, imsg->data, datalen);
559 log_debug("received fcgi %s", fcgi->path);
560 TAILQ_INSERT_TAIL(&conf->fcgi, fcgi, fcgi);
561 break;
563 case IMSG_RECONF_HOST:
564 IMSG_SIZE_CHECK(imsg, &vht);
565 memcpy(&vht, imsg->data, datalen);
566 vh = new_vhost();
567 strlcpy(vh->domain, vht.domain, sizeof(vh->domain));
568 h = vh;
569 TAILQ_INSERT_TAIL(&conf->hosts, h, vhosts);
571 /* reset proxy */
572 p = NULL;
573 break;
575 case IMSG_RECONF_CERT:
576 log_debug("receiving cert");
577 if (privsep_process == PROC_CRYPTO)
578 return config_crypto_recv_kp(conf, imsg);
579 if (h == NULL)
580 fatalx("recv'd cert without host");
581 if (h->cert != NULL)
582 fatalx("cert already received");
583 if (imsg->fd == -1)
584 fatalx("no fd for IMSG_RECONF_CERT");
585 if (load_file(imsg->fd, &h->cert, &h->certlen) == -1)
586 fatalx("failed to load cert for %s",
587 h->domain);
588 break;
590 case IMSG_RECONF_KEY:
591 log_debug("receiving key");
592 if (privsep_process == PROC_CRYPTO)
593 return config_crypto_recv_kp(conf, imsg);
594 if (h == NULL)
595 fatalx("recv'd key without host");
596 if (h->key != NULL)
597 fatalx("key already received");
598 if (imsg->fd == -1)
599 fatalx("no fd for IMSG_RECONF_KEY");
600 if (load_file(imsg->fd, &h->key, &h->keylen) == -1)
601 fatalx("failed to load key for %s",
602 h->domain);
603 break;
605 case IMSG_RECONF_OCSP:
606 log_debug("receiving ocsp");
607 if (h == NULL)
608 fatalx("recv'd ocsp without host");
609 if (h->ocsp != NULL)
610 fatalx("ocsp already received");
611 if (imsg->fd == -1)
612 fatalx("no fd for IMSG_RECONF_OCSP");
613 if (load_file(imsg->fd, &h->ocsp, &h->ocsplen) == -1)
614 fatalx("failed to load ocsp for %s",
615 h->domain);
616 break;
618 case IMSG_RECONF_LOC:
619 if (h == NULL)
620 fatalx("recv'd location without host");
621 IMSG_SIZE_CHECK(imsg, loc);
622 loc = xcalloc(1, sizeof(*loc));
623 memcpy(loc, imsg->data, datalen);
625 if (imsg->fd != -1) {
626 if (load_file(imsg->fd, &d, &len) == -1)
627 fatal("load_file");
628 loc->reqca = load_ca(d, len);
629 if (loc->reqca == NULL)
630 fatalx("failed to load CA");
631 free(d);
634 TAILQ_INSERT_TAIL(&h->locations, loc, locations);
635 break;
637 case IMSG_RECONF_ENV:
638 if (h == NULL)
639 fatalx("recv'd env without host");
640 IMSG_SIZE_CHECK(imsg, env);
641 env = xcalloc(1, sizeof(*env));
642 memcpy(env, imsg->data, datalen);
643 TAILQ_INSERT_TAIL(&h->params, env, envs);
644 break;
646 case IMSG_RECONF_ALIAS:
647 if (h == NULL)
648 fatalx("recv'd alias without host");
649 IMSG_SIZE_CHECK(imsg, alias);
650 alias = xcalloc(1, sizeof(*alias));
651 memcpy(alias, imsg->data, datalen);
652 TAILQ_INSERT_TAIL(&h->aliases, alias, aliases);
653 break;
655 case IMSG_RECONF_PROXY:
656 log_debug("receiving proxy");
657 if (h == NULL)
658 fatalx("recv'd proxy without host");
659 IMSG_SIZE_CHECK(imsg, proxy);
660 proxy = xcalloc(1, sizeof(*proxy));
661 memcpy(proxy, imsg->data, datalen);
663 if (imsg->fd != -1) {
664 if (load_file(imsg->fd, &d, &len) == -1)
665 fatal("load_file");
666 proxy->reqca = load_ca(d, len);
667 if (proxy->reqca == NULL)
668 fatal("failed to load CA");
669 free(d);
672 TAILQ_INSERT_TAIL(&h->proxies, proxy, proxies);
673 p = proxy;
674 break;
676 case IMSG_RECONF_PROXY_CERT:
677 log_debug("receiving proxy cert");
678 if (p == NULL)
679 fatalx("recv'd proxy cert without proxy");
680 if (p->cert != NULL)
681 fatalx("proxy cert already received");
682 if (imsg->fd == -1)
683 fatalx("no fd for IMSG_RECONF_PROXY_CERT");
684 if (load_file(imsg->fd, &p->cert, &p->certlen) == -1)
685 fatalx("failed to load cert for proxy %s of %s",
686 p->host, h->domain);
687 break;
689 case IMSG_RECONF_PROXY_KEY:
690 log_debug("receiving proxy key");
691 if (p == NULL)
692 fatalx("recv'd proxy key without proxy");
693 if (p->key != NULL)
694 fatalx("proxy key already received");
695 if (imsg->fd == -1)
696 fatalx("no fd for IMSG_RECONF_PROXY_KEY");
697 if (load_file(imsg->fd, &p->key, &p->keylen) == -1)
698 fatalx("failed to load key for proxy %s of %s",
699 p->host, h->domain);
700 break;
702 case IMSG_RECONF_END:
703 if (proc_compose(ps, PROC_PARENT, IMSG_RECONF_DONE,
704 NULL, 0) == -1)
705 return -1;
706 break;
708 default:
709 return -1;
712 return 0;