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 <errno.h>
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <string.h>
25 #include <syslog.h>
27 #include <openssl/pem.h>
29 #include "log.h"
30 #include "proc.h"
32 struct conf *
33 config_new(void)
34 {
35 struct conf *conf;
37 conf = xcalloc(1, sizeof(*conf));
39 TAILQ_INIT(&conf->fcgi);
40 TAILQ_INIT(&conf->hosts);
41 TAILQ_INIT(&conf->pkis);
42 TAILQ_INIT(&conf->addrs);
44 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
46 init_mime(&conf->mime);
48 conf->prefork = 3;
49 conf->log_syslog = 1;
50 conf->log_facility = LOG_DAEMON;
51 conf->log_format = LOG_FORMAT_LEGACY;
53 conf->use_privsep_crypto = 1;
55 return conf;
56 }
58 void
59 config_purge(struct conf *conf)
60 {
61 struct privsep *ps;
62 struct fcgi *f, *tf;
63 struct vhost *h, *th;
64 struct location *l, *tl;
65 struct proxy *p, *tp;
66 struct envlist *e, *te;
67 struct alist *a, *ta;
68 struct pki *pki, *tpki;
69 struct address *addr, *taddr;
70 int use_privsep_crypto, log_format;
72 ps = conf->ps;
73 use_privsep_crypto = conf->use_privsep_crypto;
74 log_format = conf->log_format;
76 free(conf->log_access);
77 free_mime(&conf->mime);
78 TAILQ_FOREACH_SAFE(f, &conf->fcgi, fcgi, tf) {
79 TAILQ_REMOVE(&conf->fcgi, f, fcgi);
80 free(f);
81 }
83 TAILQ_FOREACH_SAFE(h, &conf->hosts, vhosts, th) {
84 free(h->cert_path);
85 free(h->key_path);
86 free(h->ocsp_path);
87 free(h->cert);
88 free(h->key);
89 free(h->ocsp);
91 TAILQ_FOREACH_SAFE(addr, &h->addrs, addrs, taddr) {
92 TAILQ_REMOVE(&h->addrs, addr, addrs);
93 free(addr);
94 }
96 TAILQ_FOREACH_SAFE(l, &h->locations, locations, tl) {
97 TAILQ_REMOVE(&h->locations, l, locations);
99 if (l->dirfd != -1)
100 close(l->dirfd);
102 free(l->reqca_path);
103 X509_STORE_free(l->reqca);
105 TAILQ_FOREACH_SAFE(e, &l->params, envs, te) {
106 TAILQ_REMOVE(&l->params, e, envs);
107 free(e);
110 free(l);
113 TAILQ_FOREACH_SAFE(a, &h->aliases, aliases, ta) {
114 TAILQ_REMOVE(&h->aliases, a, aliases);
115 free(a);
118 TAILQ_FOREACH_SAFE(p, &h->proxies, proxies, tp) {
119 TAILQ_REMOVE(&h->proxies, p, proxies);
120 free(p->cert_path);
121 free(p->cert);
122 free(p->key_path);
123 free(p->key);
124 free(p->reqca_path);
125 X509_STORE_free(p->reqca);
126 free(p);
129 TAILQ_REMOVE(&conf->hosts, h, vhosts);
130 free(h);
133 TAILQ_FOREACH_SAFE(pki, &conf->pkis, pkis, tpki) {
134 TAILQ_REMOVE(&conf->pkis, pki, pkis);
135 free(pki->hash);
136 EVP_PKEY_free(pki->pkey);
137 free(pki);
140 TAILQ_FOREACH_SAFE(addr, &conf->addrs, addrs, taddr) {
141 TAILQ_REMOVE(&conf->addrs, addr, addrs);
142 if (addr->sock != -1) {
143 close(addr->sock);
144 event_del(&addr->evsock);
145 tls_free(addr->ctx);
147 free(addr);
150 memset(conf, 0, sizeof(*conf));
152 conf->ps = ps;
153 conf->use_privsep_crypto = use_privsep_crypto;
154 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
155 conf->log_syslog = 1;
156 conf->log_facility = LOG_DAEMON;
157 conf->log_format = log_format;
158 init_mime(&conf->mime);
159 TAILQ_INIT(&conf->fcgi);
160 TAILQ_INIT(&conf->hosts);
161 TAILQ_INIT(&conf->pkis);
164 static int
165 config_send_file(struct privsep *ps, enum privsep_procid id, int type,
166 int fd, void *data, size_t l)
168 int n, m, d;
170 n = -1;
171 proc_range(ps, id, &n, &m);
172 for (n = 0; n < m; ++n) {
173 d = -1;
174 if (fd != -1 && (d = dup(fd)) == -1)
175 fatal("dup %d", fd);
176 if (proc_compose_imsg(ps, id, n, type, -1, d, data, l)
177 == -1)
178 return -1;
181 if (fd != -1)
182 close(fd);
184 /* avoid fd rampage */
185 if (proc_flush_imsg(ps, id, -1) == -1) {
186 log_warn("%s: proc_fush_imsg", __func__);
187 return -1;
190 return 0;
193 static int
194 config_open_send(struct privsep *ps, enum privsep_procid id, int type,
195 const char *path)
197 int fd;
199 log_debug("sending %s", path);
201 if ((fd = open(path, O_RDONLY)) == -1)
202 fatal("can't open %s", path);
204 return config_send_file(ps, id, type, fd, NULL, 0);
207 static int
208 config_send_kp(struct privsep *ps, int cert_type, int key_type,
209 const char *cert, const char *key)
211 struct conf *conf = ps->ps_env;
212 int fd, d, key_target;
214 log_debug("sending %s", cert);
215 if ((fd = open(cert, O_RDONLY)) == -1)
216 fatal("can't open %s", cert);
217 if ((d = dup(fd)) == -1)
218 fatal("fd");
220 if (config_send_file(ps, PROC_SERVER, cert_type, fd, NULL, 0) == -1) {
221 close(d);
222 return -1;
224 if (conf->use_privsep_crypto &&
225 config_send_file(ps, PROC_CRYPTO, cert_type, d, NULL, 0) == -1)
226 return -1;
228 key_target = PROC_CRYPTO;
229 if (!conf->use_privsep_crypto)
230 key_target = PROC_SERVER;
232 if (config_open_send(ps, key_target, key_type, key) == -1)
233 return -1;
235 return 0;
238 static int
239 config_send_socks(struct conf *conf)
241 struct privsep *ps = conf->ps;
242 struct address *addr, a;
243 int sock, v;
245 TAILQ_FOREACH(addr, &conf->addrs, addrs) {
246 sock = socket(addr->ai_family, addr->ai_socktype,
247 addr->ai_protocol);
248 if (sock == -1) {
249 if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
250 continue;
251 fatal("socket");
254 v = 1;
255 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v))
256 == -1)
257 fatal("setsockopt(SO_REUSEADDR)");
259 v = 1;
260 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &v, sizeof(v))
261 == -1)
262 fatal("setsockopt(SO_REUSEPORT)");
264 mark_nonblock(sock);
266 if (bind(sock, (struct sockaddr *)&addr->ss, addr->slen)
267 == -1)
268 fatal("bind");
270 if (listen(sock, 16) == -1)
271 fatal("listen");
273 memcpy(&a, addr, sizeof(a));
274 a.conf = NULL;
275 a.sock = -1;
276 memset(&a.evsock, 0, sizeof(a.evsock));
277 memset(&a.addrs, 0, sizeof(a.addrs));
279 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_SOCK, sock,
280 &a, sizeof(a)) == -1)
281 return -1;
284 return 0;
287 int
288 config_send(struct conf *conf)
290 struct privsep *ps = conf->ps;
291 struct etm *m;
292 struct fcgi *fcgi;
293 struct vhost *h;
294 struct location *l;
295 struct proxy *p;
296 struct envlist *e;
297 struct alist *a;
298 size_t i;
300 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_LOG_FMT,
301 &conf->log_format, sizeof(conf->log_format)) == -1)
302 return -1;
304 for (i = 0; i < conf->mime.len; ++i) {
305 m = &conf->mime.t[i];
306 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_MIME,
307 m, sizeof(*m)) == -1)
308 return -1;
311 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PROTOS,
312 &conf->protos, sizeof(conf->protos)) == -1)
313 return -1;
315 if (config_send_socks(conf) == -1)
316 return -1;
318 TAILQ_FOREACH(fcgi, &conf->fcgi, fcgi) {
319 log_debug("sending fastcgi %s", fcgi->path);
320 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_FCGI,
321 fcgi, sizeof(*fcgi)) == -1)
322 return -1;
325 TAILQ_FOREACH(h, &conf->hosts, vhosts) {
326 struct vhost vcopy;
327 struct address *addr, acopy;
329 memcpy(&vcopy, h, sizeof(vcopy));
330 vcopy.cert_path = NULL;
331 vcopy.key_path = NULL;
332 vcopy.ocsp_path = NULL;
334 log_debug("sending host %s", h->domain);
336 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_HOST,
337 &vcopy, sizeof(vcopy)) == -1)
338 return -1;
340 if (config_send_kp(ps, IMSG_RECONF_CERT, IMSG_RECONF_KEY,
341 h->cert_path, h->key_path) == -1)
342 return -1;
344 if (h->ocsp_path != NULL) {
345 if (config_open_send(ps, PROC_SERVER, IMSG_RECONF_OCSP,
346 h->ocsp_path) == -1)
347 return -1;
350 TAILQ_FOREACH(addr, &h->addrs, addrs) {
351 memcpy(&acopy, addr, sizeof(acopy));
352 memset(&acopy.addrs, 0, sizeof(acopy.addrs));
354 if (proc_compose(ps, PROC_SERVER,
355 IMSG_RECONF_HOST_ADDR, &acopy, sizeof(acopy))
356 == -1)
357 return -1;
360 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1) {
361 log_warn("%s: proc_fush_imsg", __func__);
362 return -1;
365 TAILQ_FOREACH(l, &h->locations, locations) {
366 struct location lcopy;
367 int fd = -1;
369 memcpy(&lcopy, l, sizeof(lcopy));
370 lcopy.reqca_path = NULL;
371 lcopy.reqca = NULL;
372 lcopy.dirfd = -1;
373 memset(&lcopy.locations, 0, sizeof(lcopy.locations));
375 if (l->reqca_path != NULL &&
376 (fd = open(l->reqca_path, O_RDONLY)) == -1)
377 fatal("can't open %s", l->reqca_path);
379 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_LOC,
380 fd, &lcopy, sizeof(lcopy)) == -1)
381 return -1;
383 TAILQ_FOREACH(e, &l->params, envs) {
384 if (proc_compose(ps, PROC_SERVER,
385 IMSG_RECONF_ENV, e, sizeof(*e)) == -1)
386 return -1;
390 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
391 return -1;
393 TAILQ_FOREACH(a, &h->aliases, aliases) {
394 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ALIAS,
395 a, sizeof(*a)) == -1)
396 return -1;
399 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
400 return -1;
402 TAILQ_FOREACH(p, &h->proxies, proxies) {
403 struct proxy pcopy;
404 int fd = -1;
406 memcpy(&pcopy, p, sizeof(pcopy));
407 pcopy.cert_path = NULL;
408 pcopy.cert = NULL;
409 pcopy.certlen = 0;
410 pcopy.key_path = NULL;
411 pcopy.key = NULL;
412 pcopy.keylen = 0;
413 pcopy.reqca_path = NULL;
414 pcopy.reqca = NULL;
416 if (p->reqca_path != NULL) {
417 fd = open(p->reqca_path, O_RDONLY);
418 if (fd == -1)
419 fatal("can't open %s", p->reqca_path);
422 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_PROXY,
423 fd, &pcopy, sizeof(pcopy)) == -1)
424 return -1;
426 if (p->cert_path == NULL || p->key_path == NULL)
427 continue;
429 if (config_open_send(ps, PROC_SERVER,
430 IMSG_RECONF_PROXY_CERT, p->cert_path) == -1 ||
431 config_open_send(ps, PROC_SERVER,
432 IMSG_RECONF_PROXY_KEY, p->key_path) == -1)
433 return -1;
437 return 0;
440 static int
441 load_file(int fd, uint8_t **data, size_t *len)
443 struct stat sb;
444 ssize_t r;
446 if (fstat(fd, &sb) == -1)
447 fatal("fstat");
449 if (sb.st_size < 0 /* || sb.st_size > SIZE_MAX */) {
450 log_warnx("file too large");
451 close(fd);
452 return -1;
454 *len = sb.st_size;
456 if ((*data = malloc(*len)) == NULL)
457 fatal("malloc");
459 r = pread(fd, *data, *len, 0);
460 if (r == -1 || (size_t)r != *len) {
461 log_warn("read failed");
462 close(fd);
463 free(*data);
464 return -1;
467 close(fd);
468 return 0;
471 static int
472 config_crypto_recv_kp(struct conf *conf, struct imsg *imsg)
474 static struct pki *pki;
475 uint8_t *d;
476 size_t len;
477 int fd;
479 /* XXX: check for duplicates */
481 if ((fd = imsg_get_fd(imsg)) == -1)
482 fatalx("%s: no fd for imsg %d", __func__, imsg_get_type(imsg));
484 switch (imsg_get_type(imsg)) {
485 case IMSG_RECONF_CERT:
486 if (pki != NULL)
487 fatalx("imsg in wrong order; pki is not NULL");
488 if ((pki = calloc(1, sizeof(*pki))) == NULL)
489 fatal("calloc");
490 if (load_file(fd, &d, &len) == -1)
491 fatalx("can't load file");
492 if ((pki->hash = ssl_pubkey_hash(d, len)) == NULL)
493 fatalx("failed to compute cert hash");
494 free(d);
495 TAILQ_INSERT_TAIL(&conf->pkis, pki, pkis);
496 break;
498 case IMSG_RECONF_KEY:
499 if (pki == NULL)
500 fatalx("%s: RECONF_KEY: got key without cert",
501 __func__);
502 if (load_file(fd, &d, &len) == -1)
503 fatalx("failed to load private key");
504 if ((pki->pkey = ssl_load_pkey(d, len)) == NULL)
505 fatalx("failed load private key");
506 free(d);
507 pki = NULL;
508 break;
510 default:
511 return -1;
514 return 0;
517 int
518 config_recv(struct conf *conf, struct imsg *imsg)
520 static struct vhost *h;
521 static struct location *l;
522 static struct proxy *p;
523 struct privsep *ps = conf->ps;
524 struct etm m;
525 struct fcgi *fcgi;
526 struct vhost *vh, vht;
527 struct location *loc;
528 struct envlist *env;
529 struct alist *alias;
530 struct proxy *proxy;
531 struct address *addr;
532 uint8_t *d;
533 size_t len;
534 int fd;
536 switch (imsg_get_type(imsg)) {
537 case IMSG_RECONF_START:
538 config_purge(conf);
539 h = NULL;
540 p = NULL;
541 break;
543 case IMSG_RECONF_LOG_FMT:
544 if (imsg_get_data(imsg, &conf->log_format,
545 sizeof(conf->log_format)) == -1)
546 fatalx("bad length imsg LOG_FMT");
547 break;
549 case IMSG_RECONF_MIME:
550 if (imsg_get_data(imsg, &m, sizeof(m)) == -1)
551 fatalx("bad length imsg RECONF_MIME");
552 if (m.mime[sizeof(m.mime) - 1] != '\0' ||
553 m.ext[sizeof(m.ext) - 1] != '\0')
554 fatal("received corrupted IMSG_RECONF_MIME");
555 if (add_mime(&conf->mime, m.mime, m.ext) == -1)
556 fatal("failed to add mime mapping %s -> %s",
557 m.mime, m.ext);
558 break;
560 case IMSG_RECONF_PROTOS:
561 if (imsg_get_data(imsg, &conf->protos, sizeof(conf->protos))
562 == -1)
563 fatalx("bad length imsg RECONF_PROTOS");
564 break;
566 case IMSG_RECONF_SOCK:
567 addr = xcalloc(1, sizeof(*addr));
568 if (imsg_get_data(imsg, addr, sizeof(*addr)) == -1)
569 fatalx("bad length imsg RECONF_SOCK");
570 if ((fd = imsg_get_fd(imsg)) == -1)
571 fatalx("missing socket for IMSG_RECONF_SOCK");
572 addr->conf = conf;
573 addr->sock = fd;
574 event_set(&addr->evsock, addr->sock, EV_READ|EV_PERSIST,
575 server_accept, addr);
576 if ((addr->ctx = tls_server()) == NULL)
577 fatal("tls_server failure");
578 TAILQ_INSERT_HEAD(&conf->addrs, addr, addrs);
579 break;
581 case IMSG_RECONF_FCGI:
582 fcgi = xcalloc(1, sizeof(*fcgi));
583 if (imsg_get_data(imsg, fcgi, sizeof(*fcgi)) == -1)
584 fatalx("bad length imsg RECONF_FCGI");
585 log_debug("received fcgi %s", fcgi->path);
586 TAILQ_INSERT_TAIL(&conf->fcgi, fcgi, fcgi);
587 break;
589 case IMSG_RECONF_HOST:
590 if (imsg_get_data(imsg, &vht, sizeof(vht)) == -1)
591 fatalx("bad length imsg RECONF_HOST");
592 vh = new_vhost();
593 strlcpy(vh->domain, vht.domain, sizeof(vh->domain));
594 h = vh;
595 TAILQ_INSERT_TAIL(&conf->hosts, h, vhosts);
597 /* reset location and proxy */
598 l = NULL;
599 p = NULL;
600 break;
602 case IMSG_RECONF_CERT:
603 log_debug("receiving cert");
604 if (privsep_process == PROC_CRYPTO)
605 return config_crypto_recv_kp(conf, imsg);
606 if (h == NULL)
607 fatalx("recv'd cert without host");
608 if (h->cert != NULL)
609 fatalx("cert already received");
610 if ((fd = imsg_get_fd(imsg)) == -1)
611 fatalx("no fd for IMSG_RECONF_CERT");
612 if (load_file(fd, &h->cert, &h->certlen) == -1)
613 fatalx("failed to load cert for %s",
614 h->domain);
615 break;
617 case IMSG_RECONF_KEY:
618 log_debug("receiving key");
619 if (privsep_process == PROC_CRYPTO)
620 return config_crypto_recv_kp(conf, imsg);
621 if (h == NULL)
622 fatalx("recv'd key without host");
623 if (h->key != NULL)
624 fatalx("key already received");
625 if ((fd = imsg_get_fd(imsg)) == -1)
626 fatalx("no fd for IMSG_RECONF_KEY");
627 if (load_file(fd, &h->key, &h->keylen) == -1)
628 fatalx("failed to load key for %s",
629 h->domain);
630 break;
632 case IMSG_RECONF_OCSP:
633 log_debug("receiving ocsp");
634 if (h == NULL)
635 fatalx("recv'd ocsp without host");
636 if (h->ocsp != NULL)
637 fatalx("ocsp already received");
638 if ((fd = imsg_get_fd(imsg)) == -1)
639 fatalx("no fd for IMSG_RECONF_OCSP");
640 if (load_file(fd, &h->ocsp, &h->ocsplen) == -1)
641 fatalx("failed to load ocsp for %s",
642 h->domain);
643 break;
645 case IMSG_RECONF_HOST_ADDR:
646 log_debug("receiving host addr");
647 if (h == NULL)
648 fatalx("recv'd host address withouth host");
649 addr = xcalloc(1, sizeof(*addr));
650 if (imsg_get_data(imsg, addr, sizeof(*addr)) == -1)
651 fatalx("bad length imsg RECONF_HOST_ADDR");
652 TAILQ_INSERT_TAIL(&h->addrs, addr, addrs);
653 break;
655 case IMSG_RECONF_LOC:
656 if (h == NULL)
657 fatalx("recv'd location without host");
658 loc = xcalloc(1, sizeof(*loc));
659 if (imsg_get_data(imsg, loc, sizeof(*loc)) == -1)
660 fatalx("bad length imsg RECONF_LOC");
661 TAILQ_INIT(&loc->params);
663 if ((fd = imsg_get_fd(imsg)) != -1) {
664 if (load_file(fd, &d, &len) == -1)
665 fatal("load_file");
666 loc->reqca = load_ca(d, len);
667 if (loc->reqca == NULL)
668 fatalx("failed to load CA");
669 free(d);
672 l = loc;
673 TAILQ_INSERT_TAIL(&h->locations, loc, locations);
674 break;
676 case IMSG_RECONF_ENV:
677 if (l == NULL)
678 fatalx("recv'd env without location");
679 env = xcalloc(1, sizeof(*env));
680 if (imsg_get_data(imsg, env, sizeof(*env)) == -1)
681 fatalx("bad length imsg RECONF_ENV");
682 TAILQ_INSERT_TAIL(&l->params, env, envs);
683 break;
685 case IMSG_RECONF_ALIAS:
686 if (h == NULL)
687 fatalx("recv'd alias without host");
688 alias = xcalloc(1, sizeof(*alias));
689 if (imsg_get_data(imsg, alias, sizeof(*alias)) == -1)
690 fatalx("bad length imsg RECONF_ALIAS");
691 TAILQ_INSERT_TAIL(&h->aliases, alias, aliases);
692 break;
694 case IMSG_RECONF_PROXY:
695 log_debug("receiving proxy");
696 if (h == NULL)
697 fatalx("recv'd proxy without host");
698 proxy = xcalloc(1, sizeof(*proxy));
699 if (imsg_get_data(imsg, proxy, sizeof(*proxy)) == -1)
700 fatalx("bad length imsg RECONF_PROXY");
702 if ((fd = imsg_get_fd(imsg)) != -1) {
703 if (load_file(fd, &d, &len) == -1)
704 fatal("load_file");
705 proxy->reqca = load_ca(d, len);
706 if (proxy->reqca == NULL)
707 fatal("failed to load CA");
708 free(d);
711 TAILQ_INSERT_TAIL(&h->proxies, proxy, proxies);
712 p = proxy;
713 break;
715 case IMSG_RECONF_PROXY_CERT:
716 log_debug("receiving proxy cert");
717 if (p == NULL)
718 fatalx("recv'd proxy cert without proxy");
719 if (p->cert != NULL)
720 fatalx("proxy cert already received");
721 if ((fd = imsg_get_fd(imsg)) == -1)
722 fatalx("no fd for IMSG_RECONF_PROXY_CERT");
723 if (load_file(fd, &p->cert, &p->certlen) == -1)
724 fatalx("failed to load cert for proxy %s of %s",
725 p->host, h->domain);
726 break;
728 case IMSG_RECONF_PROXY_KEY:
729 log_debug("receiving proxy key");
730 if (p == NULL)
731 fatalx("recv'd proxy key without proxy");
732 if (p->key != NULL)
733 fatalx("proxy key already received");
734 if ((fd = imsg_get_fd(imsg)) == -1)
735 fatalx("no fd for IMSG_RECONF_PROXY_KEY");
736 if (load_file(fd, &p->key, &p->keylen) == -1)
737 fatalx("failed to load key for proxy %s of %s",
738 p->host, h->domain);
739 break;
741 case IMSG_RECONF_END:
742 if (proc_compose(ps, PROC_PARENT, IMSG_RECONF_DONE,
743 NULL, 0) == -1)
744 return -1;
745 break;
747 default:
748 return -1;
751 return 0;
754 int
755 config_test(struct conf *conf)
757 struct vhost *h;
758 struct address *addr;
759 int fd;
761 /*
762 * can't use config_crypto_recv_kp() because not on all platforms
763 * we're using the privsep crypto engine (yet).
764 */
765 conf->use_privsep_crypto = 0;
767 TAILQ_FOREACH(h, &conf->hosts, vhosts) {
768 if ((fd = open(h->cert_path, O_RDONLY)) == -1) {
769 log_warn("can't open %s", h->cert_path);
770 return -1;
772 if (load_file(fd, &h->cert, &h->certlen) == -1) {
773 log_warnx("failed to load cert for %s",
774 h->domain);
775 return -1;
778 if ((fd = open(h->key_path, O_RDONLY)) == -1) {
779 log_warn("can't open %s", h->key_path);
780 return -1;
782 if (load_file(fd, &h->key, &h->keylen) == -1) {
783 log_warnx("failed to load key for %s",
784 h->domain);
785 return -1;
789 TAILQ_FOREACH(addr, &conf->addrs, addrs) {
790 if ((addr->ctx = tls_server()) == NULL)
791 fatal("tls_server failed");
792 addr->sock = -1;
795 if (server_configure_done(conf))
796 return -1;
798 return 0;