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>
24 #include <syslog.h>
26 #include <openssl/pem.h>
28 #include "log.h"
29 #include "proc.h"
31 struct conf *
32 config_new(void)
33 {
34 struct conf *conf;
36 conf = xcalloc(1, sizeof(*conf));
38 TAILQ_INIT(&conf->fcgi);
39 TAILQ_INIT(&conf->hosts);
40 TAILQ_INIT(&conf->pkis);
41 TAILQ_INIT(&conf->addrs);
43 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
45 init_mime(&conf->mime);
47 conf->prefork = 3;
48 conf->log_syslog = 1;
49 conf->log_facility = LOG_DAEMON;
50 conf->log_format = LOG_FORMAT_LEGACY;
52 #ifdef __OpenBSD__
53 conf->use_privsep_crypto = 1;
54 #endif
56 return conf;
57 }
59 void
60 config_purge(struct conf *conf)
61 {
62 struct privsep *ps;
63 struct fcgi *f, *tf;
64 struct vhost *h, *th;
65 struct location *l, *tl;
66 struct proxy *p, *tp;
67 struct envlist *e, *te;
68 struct alist *a, *ta;
69 struct pki *pki, *tpki;
70 struct address *addr, *taddr;
71 int use_privsep_crypto, log_format;
73 ps = conf->ps;
74 use_privsep_crypto = conf->use_privsep_crypto;
75 log_format = conf->log_format;
77 free(conf->log_access);
78 free_mime(&conf->mime);
79 TAILQ_FOREACH_SAFE(f, &conf->fcgi, fcgi, tf) {
80 TAILQ_REMOVE(&conf->fcgi, f, fcgi);
81 free(f);
82 }
84 TAILQ_FOREACH_SAFE(h, &conf->hosts, vhosts, th) {
85 free(h->cert_path);
86 free(h->key_path);
87 free(h->ocsp_path);
88 free(h->cert);
89 free(h->key);
90 free(h->ocsp);
92 TAILQ_FOREACH_SAFE(addr, &h->addrs, addrs, taddr) {
93 TAILQ_REMOVE(&h->addrs, addr, addrs);
94 free(addr);
95 }
97 TAILQ_FOREACH_SAFE(l, &h->locations, locations, tl) {
98 TAILQ_REMOVE(&h->locations, l, locations);
100 if (l->dirfd != -1)
101 close(l->dirfd);
103 free(l->reqca_path);
104 X509_STORE_free(l->reqca);
106 TAILQ_FOREACH_SAFE(e, &l->params, envs, te) {
107 TAILQ_REMOVE(&l->params, e, envs);
108 free(e);
111 free(l);
114 TAILQ_FOREACH_SAFE(a, &h->aliases, aliases, ta) {
115 TAILQ_REMOVE(&h->aliases, a, aliases);
116 free(a);
119 TAILQ_FOREACH_SAFE(p, &h->proxies, proxies, tp) {
120 TAILQ_REMOVE(&h->proxies, p, proxies);
121 free(p->cert_path);
122 free(p->cert);
123 free(p->key_path);
124 free(p->key);
125 free(p->reqca_path);
126 X509_STORE_free(p->reqca);
127 free(p);
130 TAILQ_REMOVE(&conf->hosts, h, vhosts);
131 free(h);
134 TAILQ_FOREACH_SAFE(pki, &conf->pkis, pkis, tpki) {
135 TAILQ_REMOVE(&conf->pkis, pki, pkis);
136 free(pki->hash);
137 EVP_PKEY_free(pki->pkey);
138 free(pki);
141 TAILQ_FOREACH_SAFE(addr, &conf->addrs, addrs, taddr) {
142 TAILQ_REMOVE(&conf->addrs, addr, addrs);
143 if (addr->sock != -1) {
144 close(addr->sock);
145 event_del(&addr->evsock);
146 tls_free(addr->ctx);
148 free(addr);
151 memset(conf, 0, sizeof(*conf));
153 conf->ps = ps;
154 conf->use_privsep_crypto = use_privsep_crypto;
155 conf->protos = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3;
156 conf->log_syslog = 1;
157 conf->log_facility = LOG_DAEMON;
158 conf->log_format = log_format;
159 init_mime(&conf->mime);
160 TAILQ_INIT(&conf->fcgi);
161 TAILQ_INIT(&conf->hosts);
162 TAILQ_INIT(&conf->pkis);
165 static int
166 config_send_file(struct privsep *ps, enum privsep_procid id, int type,
167 int fd, void *data, size_t l)
169 int n, m, d;
171 n = -1;
172 proc_range(ps, id, &n, &m);
173 for (n = 0; n < m; ++n) {
174 d = -1;
175 if (fd != -1 && (d = dup(fd)) == -1)
176 fatal("dup %d", fd);
177 if (proc_compose_imsg(ps, id, n, type, -1, d, data, l)
178 == -1)
179 return -1;
182 if (fd != -1)
183 close(fd);
185 /* avoid fd rampage */
186 if (proc_flush_imsg(ps, id, -1) == -1) {
187 log_warn("%s: proc_fush_imsg", __func__);
188 return -1;
191 return 0;
194 static int
195 config_open_send(struct privsep *ps, enum privsep_procid id, int type,
196 const char *path)
198 int fd;
200 log_debug("sending %s", path);
202 if ((fd = open(path, O_RDONLY)) == -1)
203 fatal("can't open %s", path);
205 return config_send_file(ps, id, type, fd, NULL, 0);
208 static int
209 config_send_kp(struct privsep *ps, int cert_type, int key_type,
210 const char *cert, const char *key)
212 struct conf *conf = ps->ps_env;
213 int fd, d, key_target;
215 log_debug("sending %s", cert);
216 if ((fd = open(cert, O_RDONLY)) == -1)
217 fatal("can't open %s", cert);
218 if ((d = dup(fd)) == -1)
219 fatal("fd");
221 if (config_send_file(ps, PROC_SERVER, cert_type, fd, NULL, 0) == -1) {
222 close(d);
223 return -1;
225 if (conf->use_privsep_crypto &&
226 config_send_file(ps, PROC_CRYPTO, cert_type, d, NULL, 0) == -1)
227 return -1;
229 key_target = PROC_CRYPTO;
230 if (!conf->use_privsep_crypto)
231 key_target = PROC_SERVER;
233 if (config_open_send(ps, key_target, key_type, key) == -1)
234 return -1;
236 return 0;
239 static int
240 config_send_socks(struct conf *conf)
242 struct privsep *ps = conf->ps;
243 struct address *addr, a;
244 int sock, v;
246 TAILQ_FOREACH(addr, &conf->addrs, addrs) {
247 sock = socket(addr->ai_family, addr->ai_socktype,
248 addr->ai_protocol);
249 if (sock == -1)
250 fatal("socket");
252 v = 1;
253 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v))
254 == -1)
255 fatal("setsockopt(SO_REUSEADDR)");
257 v = 1;
258 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &v, sizeof(v))
259 == -1)
260 fatal("setsockopt(SO_REUSEPORT)");
262 mark_nonblock(sock);
264 if (bind(sock, (struct sockaddr *)&addr->ss, addr->slen)
265 == -1)
266 fatal("bind");
268 if (listen(sock, 16) == -1)
269 fatal("listen");
271 memcpy(&a, addr, sizeof(a));
272 a.conf = NULL;
273 a.sock = -1;
274 memset(&a.evsock, 0, sizeof(a.evsock));
275 memset(&a.addrs, 0, sizeof(a.addrs));
277 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_SOCK, sock,
278 &a, sizeof(a)) == -1)
279 return -1;
282 return 0;
285 int
286 config_send(struct conf *conf)
288 struct privsep *ps = conf->ps;
289 struct etm *m;
290 struct fcgi *fcgi;
291 struct vhost *h;
292 struct location *l;
293 struct proxy *p;
294 struct envlist *e;
295 struct alist *a;
296 size_t i;
298 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_LOG_FMT,
299 &conf->log_format, sizeof(conf->log_format)) == -1)
300 return -1;
302 for (i = 0; i < conf->mime.len; ++i) {
303 m = &conf->mime.t[i];
304 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_MIME,
305 m, sizeof(*m)) == -1)
306 return -1;
309 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_PROTOS,
310 &conf->protos, sizeof(conf->protos)) == -1)
311 return -1;
313 if (config_send_socks(conf) == -1)
314 return -1;
316 TAILQ_FOREACH(fcgi, &conf->fcgi, fcgi) {
317 log_debug("sending fastcgi %s", fcgi->path);
318 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_FCGI,
319 fcgi, sizeof(*fcgi)) == -1)
320 return -1;
323 TAILQ_FOREACH(h, &conf->hosts, vhosts) {
324 struct vhost vcopy;
325 struct address *addr, acopy;
327 memcpy(&vcopy, h, sizeof(vcopy));
328 vcopy.cert_path = NULL;
329 vcopy.key_path = NULL;
330 vcopy.ocsp_path = NULL;
332 log_debug("sending host %s", h->domain);
334 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_HOST,
335 &vcopy, sizeof(vcopy)) == -1)
336 return -1;
338 if (config_send_kp(ps, IMSG_RECONF_CERT, IMSG_RECONF_KEY,
339 h->cert_path, h->key_path) == -1)
340 return -1;
342 if (h->ocsp_path != NULL) {
343 if (config_open_send(ps, PROC_SERVER, IMSG_RECONF_OCSP,
344 h->ocsp_path) == -1)
345 return -1;
348 TAILQ_FOREACH(addr, &h->addrs, addrs) {
349 memcpy(&acopy, addr, sizeof(acopy));
350 memset(&acopy.addrs, 0, sizeof(acopy.addrs));
352 if (proc_compose(ps, PROC_SERVER,
353 IMSG_RECONF_HOST_ADDR, &acopy, sizeof(acopy))
354 == -1)
355 return -1;
358 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1) {
359 log_warn("%s: proc_fush_imsg", __func__);
360 return -1;
363 TAILQ_FOREACH(l, &h->locations, locations) {
364 struct location lcopy;
365 int fd = -1;
367 memcpy(&lcopy, l, sizeof(lcopy));
368 lcopy.reqca_path = NULL;
369 lcopy.reqca = NULL;
370 lcopy.dirfd = -1;
371 memset(&lcopy.locations, 0, sizeof(lcopy.locations));
373 if (l->reqca_path != NULL &&
374 (fd = open(l->reqca_path, O_RDONLY)) == -1)
375 fatal("can't open %s", l->reqca_path);
377 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_LOC,
378 fd, &lcopy, sizeof(lcopy)) == -1)
379 return -1;
381 TAILQ_FOREACH(e, &l->params, envs) {
382 if (proc_compose(ps, PROC_SERVER,
383 IMSG_RECONF_ENV, e, sizeof(*e)) == -1)
384 return -1;
388 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
389 return -1;
391 TAILQ_FOREACH(a, &h->aliases, aliases) {
392 if (proc_compose(ps, PROC_SERVER, IMSG_RECONF_ALIAS,
393 a, sizeof(*a)) == -1)
394 return -1;
397 if (proc_flush_imsg(ps, PROC_SERVER, -1) == -1)
398 return -1;
400 TAILQ_FOREACH(p, &h->proxies, proxies) {
401 struct proxy pcopy;
402 int fd = -1;
404 memcpy(&pcopy, p, sizeof(pcopy));
405 pcopy.cert_path = NULL;
406 pcopy.cert = NULL;
407 pcopy.certlen = 0;
408 pcopy.key_path = NULL;
409 pcopy.key = NULL;
410 pcopy.keylen = 0;
411 pcopy.reqca_path = NULL;
412 pcopy.reqca = NULL;
414 if (p->reqca_path != NULL) {
415 fd = open(p->reqca_path, O_RDONLY);
416 if (fd == -1)
417 fatal("can't open %s", p->reqca_path);
420 if (config_send_file(ps, PROC_SERVER, IMSG_RECONF_PROXY,
421 fd, &pcopy, sizeof(pcopy)) == -1)
422 return -1;
424 if (p->cert_path == NULL || p->key_path == NULL)
425 continue;
427 if (config_open_send(ps, PROC_SERVER,
428 IMSG_RECONF_PROXY_CERT, p->cert_path) == -1 ||
429 config_open_send(ps, PROC_SERVER,
430 IMSG_RECONF_PROXY_KEY, p->key_path) == -1)
431 return -1;
435 return 0;
438 static int
439 load_file(int fd, uint8_t **data, size_t *len)
441 struct stat sb;
442 ssize_t r;
444 if (fstat(fd, &sb) == -1)
445 fatal("fstat");
447 if (sb.st_size < 0 /* || sb.st_size > SIZE_MAX */) {
448 log_warnx("file too large");
449 close(fd);
450 return -1;
452 *len = sb.st_size;
454 if ((*data = malloc(*len)) == NULL)
455 fatal("malloc");
457 r = pread(fd, *data, *len, 0);
458 if (r == -1 || (size_t)r != *len) {
459 log_warn("read failed");
460 close(fd);
461 free(*data);
462 return -1;
465 close(fd);
466 return 0;
469 static int
470 config_crypto_recv_kp(struct conf *conf, struct imsg *imsg)
472 static struct pki *pki;
473 uint8_t *d;
474 size_t len;
476 /* XXX: check for duplicates */
478 if (imsg->fd == -1)
479 fatalx("no fd for imsg %d", imsg->hdr.type);
481 switch (imsg->hdr.type) {
482 case IMSG_RECONF_CERT:
483 if (pki != NULL)
484 fatalx("imsg in wrong order; pki is not NULL");
485 if ((pki = calloc(1, sizeof(*pki))) == NULL)
486 fatal("calloc");
487 if (load_file(imsg->fd, &d, &len) == -1)
488 fatalx("can't load file");
489 if ((pki->hash = ssl_pubkey_hash(d, len)) == NULL)
490 fatalx("failed to compute cert hash");
491 free(d);
492 TAILQ_INSERT_TAIL(&conf->pkis, pki, pkis);
493 break;
495 case IMSG_RECONF_KEY:
496 if (pki == NULL)
497 fatalx("got key without cert beforehand %d",
498 imsg->hdr.type);
499 if (load_file(imsg->fd, &d, &len) == -1)
500 fatalx("failed to load private key");
501 if ((pki->pkey = ssl_load_pkey(d, len)) == NULL)
502 fatalx("failed load private key");
503 free(d);
504 pki = NULL;
505 break;
507 default:
508 return -1;
511 return 0;
514 int
515 config_recv(struct conf *conf, struct imsg *imsg)
517 static struct vhost *h;
518 static struct location *l;
519 static struct proxy *p;
520 struct privsep *ps = conf->ps;
521 struct etm m;
522 struct fcgi *fcgi;
523 struct vhost *vh, vht;
524 struct location *loc;
525 struct envlist *env;
526 struct alist *alias;
527 struct proxy *proxy;
528 struct address *addr;
529 uint8_t *d;
530 size_t len, datalen;
532 datalen = IMSG_DATA_SIZE(imsg);
534 switch (imsg->hdr.type) {
535 case IMSG_RECONF_START:
536 config_purge(conf);
537 h = NULL;
538 p = NULL;
539 break;
541 case IMSG_RECONF_LOG_FMT:
542 IMSG_SIZE_CHECK(imsg, &conf->log_format);
543 memcpy(&conf->log_format, imsg->data, datalen);
544 break;
546 case IMSG_RECONF_MIME:
547 IMSG_SIZE_CHECK(imsg, &m);
548 memcpy(&m, imsg->data, datalen);
549 if (m.mime[sizeof(m.mime) - 1] != '\0' ||
550 m.ext[sizeof(m.ext) - 1] != '\0')
551 fatal("received corrupted IMSG_RECONF_MIME");
552 if (add_mime(&conf->mime, m.mime, m.ext) == -1)
553 fatal("failed to add mime mapping %s -> %s",
554 m.mime, m.ext);
555 break;
557 case IMSG_RECONF_PROTOS:
558 IMSG_SIZE_CHECK(imsg, &conf->protos);
559 memcpy(&conf->protos, imsg->data, datalen);
560 break;
562 case IMSG_RECONF_SOCK:
563 addr = xcalloc(1, sizeof(*addr));
564 IMSG_SIZE_CHECK(imsg, addr);
565 memcpy(addr, imsg->data, sizeof(*addr));
566 if (imsg->fd == -1)
567 fatalx("missing socket for IMSG_RECONF_SOCK");
568 addr->conf = conf;
569 addr->sock = imsg->fd;
570 event_set(&addr->evsock, addr->sock, EV_READ|EV_PERSIST,
571 server_accept, addr);
572 if ((addr->ctx = tls_server()) == NULL)
573 fatal("tls_server failure");
574 TAILQ_INSERT_HEAD(&conf->addrs, addr, addrs);
575 break;
577 case IMSG_RECONF_FCGI:
578 IMSG_SIZE_CHECK(imsg, fcgi);
579 fcgi = xcalloc(1, sizeof(*fcgi));
580 memcpy(fcgi, imsg->data, datalen);
581 log_debug("received fcgi %s", fcgi->path);
582 TAILQ_INSERT_TAIL(&conf->fcgi, fcgi, fcgi);
583 break;
585 case IMSG_RECONF_HOST:
586 IMSG_SIZE_CHECK(imsg, &vht);
587 memcpy(&vht, imsg->data, datalen);
588 vh = new_vhost();
589 strlcpy(vh->domain, vht.domain, sizeof(vh->domain));
590 h = vh;
591 TAILQ_INSERT_TAIL(&conf->hosts, h, vhosts);
593 /* reset location and proxy */
594 l = NULL;
595 p = NULL;
596 break;
598 case IMSG_RECONF_CERT:
599 log_debug("receiving cert");
600 if (privsep_process == PROC_CRYPTO)
601 return config_crypto_recv_kp(conf, imsg);
602 if (h == NULL)
603 fatalx("recv'd cert without host");
604 if (h->cert != NULL)
605 fatalx("cert already received");
606 if (imsg->fd == -1)
607 fatalx("no fd for IMSG_RECONF_CERT");
608 if (load_file(imsg->fd, &h->cert, &h->certlen) == -1)
609 fatalx("failed to load cert for %s",
610 h->domain);
611 break;
613 case IMSG_RECONF_KEY:
614 log_debug("receiving key");
615 if (privsep_process == PROC_CRYPTO)
616 return config_crypto_recv_kp(conf, imsg);
617 if (h == NULL)
618 fatalx("recv'd key without host");
619 if (h->key != NULL)
620 fatalx("key already received");
621 if (imsg->fd == -1)
622 fatalx("no fd for IMSG_RECONF_KEY");
623 if (load_file(imsg->fd, &h->key, &h->keylen) == -1)
624 fatalx("failed to load key for %s",
625 h->domain);
626 break;
628 case IMSG_RECONF_OCSP:
629 log_debug("receiving ocsp");
630 if (h == NULL)
631 fatalx("recv'd ocsp without host");
632 if (h->ocsp != NULL)
633 fatalx("ocsp already received");
634 if (imsg->fd == -1)
635 fatalx("no fd for IMSG_RECONF_OCSP");
636 if (load_file(imsg->fd, &h->ocsp, &h->ocsplen) == -1)
637 fatalx("failed to load ocsp for %s",
638 h->domain);
639 break;
641 case IMSG_RECONF_HOST_ADDR:
642 log_debug("receiving host addr");
643 if (h == NULL)
644 fatalx("recv'd host address withouth host");
645 IMSG_SIZE_CHECK(imsg, addr);
646 addr = xcalloc(1, sizeof(*addr));
647 memcpy(addr, imsg->data, datalen);
648 TAILQ_INSERT_TAIL(&h->addrs, addr, addrs);
649 break;
651 case IMSG_RECONF_LOC:
652 if (h == NULL)
653 fatalx("recv'd location without host");
654 IMSG_SIZE_CHECK(imsg, loc);
655 loc = xcalloc(1, sizeof(*loc));
656 memcpy(loc, imsg->data, datalen);
657 TAILQ_INIT(&loc->params);
659 if (imsg->fd != -1) {
660 if (load_file(imsg->fd, &d, &len) == -1)
661 fatal("load_file");
662 loc->reqca = load_ca(d, len);
663 if (loc->reqca == NULL)
664 fatalx("failed to load CA");
665 free(d);
668 l = loc;
669 TAILQ_INSERT_TAIL(&h->locations, loc, locations);
670 break;
672 case IMSG_RECONF_ENV:
673 if (l == NULL)
674 fatalx("recv'd env without location");
675 IMSG_SIZE_CHECK(imsg, env);
676 env = xcalloc(1, sizeof(*env));
677 memcpy(env, imsg->data, datalen);
678 TAILQ_INSERT_TAIL(&l->params, env, envs);
679 break;
681 case IMSG_RECONF_ALIAS:
682 if (h == NULL)
683 fatalx("recv'd alias without host");
684 IMSG_SIZE_CHECK(imsg, alias);
685 alias = xcalloc(1, sizeof(*alias));
686 memcpy(alias, imsg->data, datalen);
687 TAILQ_INSERT_TAIL(&h->aliases, alias, aliases);
688 break;
690 case IMSG_RECONF_PROXY:
691 log_debug("receiving proxy");
692 if (h == NULL)
693 fatalx("recv'd proxy without host");
694 IMSG_SIZE_CHECK(imsg, proxy);
695 proxy = xcalloc(1, sizeof(*proxy));
696 memcpy(proxy, imsg->data, datalen);
698 if (imsg->fd != -1) {
699 if (load_file(imsg->fd, &d, &len) == -1)
700 fatal("load_file");
701 proxy->reqca = load_ca(d, len);
702 if (proxy->reqca == NULL)
703 fatal("failed to load CA");
704 free(d);
707 TAILQ_INSERT_TAIL(&h->proxies, proxy, proxies);
708 p = proxy;
709 break;
711 case IMSG_RECONF_PROXY_CERT:
712 log_debug("receiving proxy cert");
713 if (p == NULL)
714 fatalx("recv'd proxy cert without proxy");
715 if (p->cert != NULL)
716 fatalx("proxy cert already received");
717 if (imsg->fd == -1)
718 fatalx("no fd for IMSG_RECONF_PROXY_CERT");
719 if (load_file(imsg->fd, &p->cert, &p->certlen) == -1)
720 fatalx("failed to load cert for proxy %s of %s",
721 p->host, h->domain);
722 break;
724 case IMSG_RECONF_PROXY_KEY:
725 log_debug("receiving proxy key");
726 if (p == NULL)
727 fatalx("recv'd proxy key without proxy");
728 if (p->key != NULL)
729 fatalx("proxy key already received");
730 if (imsg->fd == -1)
731 fatalx("no fd for IMSG_RECONF_PROXY_KEY");
732 if (load_file(imsg->fd, &p->key, &p->keylen) == -1)
733 fatalx("failed to load key for proxy %s of %s",
734 p->host, h->domain);
735 break;
737 case IMSG_RECONF_END:
738 if (proc_compose(ps, PROC_PARENT, IMSG_RECONF_DONE,
739 NULL, 0) == -1)
740 return -1;
741 break;
743 default:
744 return -1;
747 return 0;
750 int
751 config_test(struct conf *conf)
753 struct vhost *h;
754 struct address *addr;
755 int fd;
757 /*
758 * can't use config_crypto_recv_kp() because not on all platforms
759 * we're using the privsep crypto engine (yet).
760 */
761 conf->use_privsep_crypto = 0;
763 TAILQ_FOREACH(h, &conf->hosts, vhosts) {
764 if ((fd = open(h->cert_path, O_RDONLY)) == -1) {
765 log_warn("can't open %s", h->cert_path);
766 return -1;
768 if (load_file(fd, &h->cert, &h->certlen) == -1) {
769 log_warnx("failed to load cert for %s",
770 h->domain);
771 return -1;
774 if ((fd = open(h->key_path, O_RDONLY)) == -1) {
775 log_warn("can't open %s", h->key_path);
776 return -1;
778 if (load_file(fd, &h->key, &h->keylen) == -1) {
779 log_warnx("failed to load key for %s",
780 h->domain);
781 return -1;
785 TAILQ_FOREACH(addr, &conf->addrs, addrs) {
786 if ((addr->ctx = tls_server()) == NULL)
787 fatal("tls_server failed");
788 addr->sock = -1;
791 if (server_configure_done(conf))
792 return -1;
794 return 0;