summaryrefslogtreecommitdiff
path: root/sbin/unwind/frontend.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/unwind/frontend.c')
-rw-r--r--sbin/unwind/frontend.c210
1 files changed, 208 insertions, 2 deletions
diff --git a/sbin/unwind/frontend.c b/sbin/unwind/frontend.c
index b7e4381c99e..6fb169e7717 100644
--- a/sbin/unwind/frontend.c
+++ b/sbin/unwind/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.10 2019/02/03 12:02:30 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.11 2019/02/07 17:20:35 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -88,6 +88,9 @@ void get_rtaddrs(int, struct sockaddr *,
void rtmget_default(void);
struct pending_query *find_pending_query(uint64_t);
void parse_dhcp_lease(int);
+void parse_trust_anchor(struct trust_anchor_head *, int);
+void send_trust_anchors(struct trust_anchor_head *);
+void write_trust_anchors(struct trust_anchor_head *, int);
struct unwind_conf *frontend_conf;
struct imsgev *iev_main;
@@ -96,6 +99,9 @@ struct imsgev *iev_captiveportal;
struct event ev_route;
int udp4sock = -1, udp6sock = -1, routesock = -1;
+static struct trust_anchor_head built_in_trust_anchors;
+static struct trust_anchor_head trust_anchors, new_trust_anchors;
+
void
frontend_sig_handler(int sig, short event, void *bula)
{
@@ -194,6 +200,12 @@ frontend(int debug, int verbose)
TAILQ_INIT(&pending_queries);
+ TAILQ_INIT(&built_in_trust_anchors);
+ TAILQ_INIT(&trust_anchors);
+ TAILQ_INIT(&new_trust_anchors);
+
+ add_new_ta(&built_in_trust_anchors, KSK2017);
+
event_dispatch();
frontend_shutdown();
@@ -460,6 +472,21 @@ frontend_dispatch_main(int fd, short event, void *bula)
__func__);
parse_dhcp_lease(fd);
break;
+ case IMSG_TAFD:
+ if ((fd = imsg.fd) != -1)
+ parse_trust_anchor(&trust_anchors, fd);
+ if (!TAILQ_EMPTY(&trust_anchors))
+ send_trust_anchors(&trust_anchors);
+ else
+ send_trust_anchors(&built_in_trust_anchors);
+ break;
+ case IMSG_TAFD_W:
+ if ((fd = imsg.fd) == -1)
+ fatalx("%s: expected to receive imsg trust "
+ "anchor fd but didn't receive any",
+ __func__);
+ write_trust_anchors(&trust_anchors, fd);
+ break;
default:
log_debug("%s: error handling imsg %d", __func__,
imsg.hdr.type);
@@ -484,7 +511,8 @@ frontend_dispatch_resolver(int fd, short event, void *bula)
struct imsgbuf *ibuf = &iev->ibuf;
struct imsg imsg;
struct query_imsg *query_imsg;
- int n, shut = 0;
+ int n, shut = 0, chg;
+ char *ta;
if (event & EV_READ) {
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
@@ -555,6 +583,31 @@ frontend_dispatch_resolver(int fd, short event, void *bula)
case IMSG_CTL_END:
control_imsg_relay(&imsg);
break;
+ case IMSG_NEW_TA:
+ /* make sure this is a string */
+ ((char *)imsg.data)[imsg.hdr.len - IMSG_HEADER_SIZE - 1]
+ = '\0';
+ ta = imsg.data;
+ add_new_ta(&new_trust_anchors, ta);
+ break;
+ case IMSG_NEW_TAS_ABORT:
+ log_debug("%s: IMSG_NEW_TAS_ABORT", __func__);
+ free_tas(&new_trust_anchors);
+ break;
+ case IMSG_NEW_TAS_DONE:
+ chg = merge_tas(&new_trust_anchors, &trust_anchors);
+ log_debug("%s: IMSG_NEW_TAS_DONE: change: %d",
+ __func__, chg);
+ if (chg) {
+ send_trust_anchors(&trust_anchors);
+ }
+ /*
+ * always write trust anchors, the modify date on
+ * the file is an indication when we made progress
+ */
+ frontend_imsg_compose_main(IMSG_OPEN_TA_W, 0, NULL,
+ 0);
+ break;
default:
log_debug("%s: error handling imsg %d", __func__,
imsg.hdr.type);
@@ -624,6 +677,8 @@ frontend_startup(void)
event_add(&ev_route, NULL);
+ frontend_imsg_compose_main(IMSG_OPEN_TA_RO, 0, NULL, 0);
+
frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0);
rtmget_default();
}
@@ -1028,3 +1083,154 @@ parse_dhcp_lease(int fd)
strlen(ns) + 1);
}
}
+
+
+void
+add_new_ta(struct trust_anchor_head *tah, char *val)
+{
+
+ struct trust_anchor *ta, *i;
+ int cmp;
+
+ if ((ta = malloc(sizeof(*ta))) == NULL)
+ fatal("%s", __func__);
+ if ((ta->ta = strdup(val)) == NULL)
+ fatal("%s", __func__);
+
+ /* keep the list sorted to prevent churn if the order changes in DNS */
+ TAILQ_FOREACH(i, tah, entry) {
+ cmp = strcmp(i->ta, ta->ta);
+ if ( cmp == 0) {
+ /* duplicate */
+ free(ta->ta);
+ free(ta);
+ return;
+ } else if (cmp > 0) {
+ TAILQ_INSERT_BEFORE(i, ta, entry);
+ return;
+ }
+ }
+ TAILQ_INSERT_TAIL(tah, ta, entry);
+}
+
+void
+free_tas(struct trust_anchor_head *tah)
+{
+ struct trust_anchor *ta;
+
+ while ((ta = TAILQ_FIRST(tah))) {
+ TAILQ_REMOVE(tah, ta, entry);
+ free(ta->ta);
+ free(ta);
+ }
+}
+
+int
+merge_tas(struct trust_anchor_head *newh, struct trust_anchor_head *oldh)
+{
+ struct trust_anchor *i, *j;
+ int chg = 0;
+
+ j = TAILQ_FIRST(oldh);
+
+ TAILQ_FOREACH(i, newh, entry) {
+ if (j == NULL || strcmp(i->ta, j->ta) != 0) {
+ chg = 1;
+ break;
+ }
+ j = TAILQ_NEXT(j, entry);
+ }
+ if (j!= NULL)
+ chg = 1;
+
+ if (chg) {
+ free_tas(oldh);
+ while((i = TAILQ_FIRST(newh)) != NULL) {
+ TAILQ_REMOVE(newh, i, entry);
+ TAILQ_INSERT_TAIL(oldh, i, entry);
+ }
+ } else {
+ free_tas(newh);
+ }
+ return (chg);
+}
+
+void
+parse_trust_anchor(struct trust_anchor_head *tah, int fd)
+{
+ FILE *f;
+ char *line = NULL, *p;
+ size_t linesize = 0;
+ ssize_t linelen;
+
+ if((f = fdopen(fd, "r")) == NULL) {
+ log_warn("cannot read trust anchor file");
+ close(fd);
+ return;
+ }
+
+ while ((linelen = getline(&line, &linesize, f)) != -1) {
+ if (*line == ';')
+ continue;
+ p = strchr(line, ';');
+ if (p == NULL)
+ p = strchr(line, '\n');
+ if (p != NULL) {
+ do {
+ p--;
+ } while(p != line && *p == ' ');
+ *(p + 1) = '\0';
+ }
+ log_debug("%s: %s", __func__, line);
+ add_new_ta(tah, line);
+ }
+ free(line);
+ if (ferror(f))
+ log_warn("getline");
+ fclose(f);
+}
+
+void
+send_trust_anchors(struct trust_anchor_head *tah)
+{
+ struct trust_anchor *ta;
+
+ TAILQ_FOREACH(ta, tah, entry)
+ frontend_imsg_compose_resolver(IMSG_NEW_TA, 0, ta->ta,
+ strlen(ta->ta) + 1);
+ frontend_imsg_compose_resolver(IMSG_NEW_TAS_DONE, 0, NULL, 0);
+}
+
+void
+write_trust_anchors(struct trust_anchor_head *tah, int fd)
+{
+ FILE *f;
+ struct trust_anchor *ta;
+
+ if((f = fdopen(fd, "w+")) == NULL) {
+ log_warn("cannot open trust anchor file for writing");
+ goto err;
+ }
+
+ TAILQ_FOREACH(ta, tah, entry)
+ if (fprintf(f, "%s\n", ta->ta) < 0)
+ goto err;
+ if (ferror(f)) {
+ log_warn("%s", __func__);
+ goto err;
+ }
+ if (fclose(f) != 0) {
+ f = NULL;
+ log_warn("%s", __func__);
+ goto err;
+ }
+ frontend_imsg_compose_main(IMSG_TA_W_DONE, 0, NULL, 0);
+ return;
+err:
+ if (f == NULL)
+ close(fd);
+ else
+ fclose(f);
+
+ frontend_imsg_compose_main(IMSG_TA_W_FAILED, 0, NULL, 0);
+}