diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2019-11-14 08:34:18 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2019-11-14 08:34:18 +0000 |
commit | ae13959e0b5998b509c62aeaffdd8f4cda26519b (patch) | |
tree | c10268378de62937809b954208720024fd6dd5d3 /sbin | |
parent | 41dff51c79fd37dda973dd31745e0ad6cbb65357 (diff) |
With the stub resolver we have since some time we can resolve the
captive portal host internaly via the resolver process.
deraadt and me observed weird captive portal checking hangs inside of
unwind if only 127.0.0.1 was listed as a nameserver in resolv.conf
with the old code.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/unwind/resolver.c | 75 | ||||
-rw-r--r-- | sbin/unwind/unwind.c | 90 | ||||
-rw-r--r-- | sbin/unwind/unwind.h | 4 |
3 files changed, 104 insertions, 65 deletions
diff --git a/sbin/unwind/resolver.c b/sbin/unwind/resolver.c index c525e72e55a..e17e3487186 100644 --- a/sbin/unwind/resolver.c +++ b/sbin/unwind/resolver.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resolver.c,v 1.64 2019/11/14 08:32:30 florian Exp $ */ +/* $OpenBSD: resolver.c,v 1.65 2019/11/14 08:34:17 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -151,6 +151,8 @@ void check_captive_portal(int); void check_captive_portal_timo(int, short, void *); int check_captive_portal_changed(struct uw_conf *, struct uw_conf *); +void captive_portal_resolve_done(struct uw_resolver *, + void *, int, void *, int, int, char *); void trust_anchor_resolve(void); void trust_anchor_timo(int, short, void *); void trust_anchor_resolve_done(struct uw_resolver *, void *, @@ -1704,6 +1706,8 @@ check_captive_portal_timo(int fd, short events, void *arg) void check_captive_portal(int timer_reset) { + struct uw_resolver *res; + log_debug("%s", __func__); if (resolver_conf->captive_portal_host == NULL) { @@ -1713,11 +1717,6 @@ check_captive_portal(int timer_reset) return; } - if (resolvers[UW_RES_DHCP] == NULL) { - log_debug("%s no DHCP nameservers known", __func__); - return; - } - if (timer_reset) captive_portal_check_tv.tv_sec = PORTAL_CHECK_SEC; @@ -1725,7 +1724,69 @@ check_captive_portal(int timer_reset) captive_portal_state = PORTAL_UNKNOWN; - resolver_imsg_compose_main(IMSG_RESOLVE_CAPTIVE_PORTAL, 0, NULL, 0); + if ((res = best_resolver()) == NULL) + return; + + resolve(res, resolver_conf->captive_portal_host, + LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, NULL, + captive_portal_resolve_done); +} + +void +captive_portal_resolve_done(struct uw_resolver *res, void *arg, int rcode, + void *answer_packet, int answer_len, int sec, char *why_bogus) +{ + struct ub_result *result; + sldns_buffer *buf = NULL; + struct regional *region = NULL; + struct in_addr *in; + int i; + char *str, rdata_buf[sizeof("xxx.xxx.xxx.xxx")]; + + if ((result = calloc(1, sizeof(*result))) == NULL) + goto out; + + log_debug("%s: rcode: %d", __func__, rcode); + if ((str = sldns_wire2str_pkt(answer_packet, answer_len)) != NULL) { + log_debug("%s", str); + free(str); + } + + if ((buf = sldns_buffer_new(answer_len)) == NULL) + goto out; + if ((region = regional_create()) == NULL) + goto out; + result->rcode = LDNS_RCODE_SERVFAIL; + + sldns_buffer_clear(buf); + sldns_buffer_write(buf, answer_packet, answer_len); + sldns_buffer_flip(buf); + libworker_enter_result(result, buf, region, sec); + result->answer_packet = NULL; + result->answer_len = 0; + + if (result->rcode != LDNS_RCODE_NOERROR) { + log_debug("%s: result->rcode: %d", __func__, + result->rcode); + goto out; + } + + i = 0; + while(result->data[i] != NULL) { + if (result->len[i] == 4) { + in = (struct in_addr*) result->data[i]; + log_debug("%s: %s", __func__, inet_ntop(AF_INET, + in, rdata_buf, sizeof(rdata_buf))); + resolver_imsg_compose_main( + IMSG_CONNECT_CAPTIVE_PORTAL_HOST, 0, in, + sizeof(*in)); + } + i++; + } + out: + sldns_buffer_free(buf); + regional_destroy(region); + ub_resolve_free(result); } int diff --git a/sbin/unwind/unwind.c b/sbin/unwind/unwind.c index a04a17858d4..317df549975 100644 --- a/sbin/unwind/unwind.c +++ b/sbin/unwind/unwind.c @@ -1,4 +1,4 @@ -/* $OpenBSD: unwind.c,v 1.35 2019/11/11 05:51:06 florian Exp $ */ +/* $OpenBSD: unwind.c,v 1.36 2019/11/14 08:34:17 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -74,8 +74,7 @@ int main_sendall(enum imsg_type, void *, uint16_t); void open_dhcp_lease(int); void open_ports(void); void solicit_dns_proposals(void); -void resolve_captive_portal(void); -void resolve_captive_portal_done(struct asr_result *, void *); +void connect_captive_portal_host(struct in_addr *); void send_blocklist_fd(void); struct uw_conf *main_conf; @@ -319,7 +318,7 @@ main(int argc, char *argv[]) if (main_conf->blocklist_file != NULL) send_blocklist_fd(); - if (pledge("stdio inet dns rpath sendfd", NULL) == -1) + if (pledge("stdio inet rpath sendfd", NULL) == -1) fatal("pledge"); main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0); @@ -494,6 +493,7 @@ main_dispatch_resolver(int fd, short event, void *bula) struct imsgev *iev = bula; struct imsgbuf *ibuf; struct imsg imsg; + struct in_addr *in; ssize_t n; int shut = 0; @@ -519,8 +519,13 @@ main_dispatch_resolver(int fd, short event, void *bula) break; switch (imsg.hdr.type) { - case IMSG_RESOLVE_CAPTIVE_PORTAL: - resolve_captive_portal(); + case IMSG_CONNECT_CAPTIVE_PORTAL_HOST: + if (IMSG_DATA_SIZE(imsg) != sizeof(*in)) + fatalx("%s: IMSG_CONNECT_CAPTIVE_PORTAL_HOST " + "wrong length: %lu", __func__, + IMSG_DATA_SIZE(imsg)); + in = (struct in_addr *)imsg.data; + connect_captive_portal_host(in); break; default: log_debug("%s: error handling imsg %d", __func__, @@ -988,62 +993,35 @@ solicit_dns_proposals(void) } void -resolve_captive_portal(void) +connect_captive_portal_host(struct in_addr *in) { - struct addrinfo hints; - void *as; - - if (main_conf->captive_portal_host == NULL) - return; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_INET; - hints.ai_socktype = SOCK_STREAM; - - log_debug("%s: %s", __func__, main_conf->captive_portal_host); - - if ((as = getaddrinfo_async(main_conf->captive_portal_host, "www", - &hints, NULL)) != NULL) - event_asr_run(as, resolve_captive_portal_done, NULL); - else - log_warn("%s: getaddrinfo_async", __func__); - -} - -void -resolve_captive_portal_done(struct asr_result *ar, void *arg) -{ - struct addrinfo *res; - int httpsock; - - if (ar->ar_gai_errno) { - log_warnx("%s: %s", __func__, gai_strerror(ar->ar_gai_errno)); + struct sockaddr *sa; + struct sockaddr_in sin; + int httpsock; + + sa = (struct sockaddr *)&sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr = *in; + sin.sin_port = htons(80); + log_debug("%s: ip_port: %s", __func__, ip_port(sa)); + + if ((httpsock = socket(AF_INET, SOCK_STREAM | + SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { + log_warn("%s: socket", __func__); return; } - - for (res = ar->ar_addrinfo; res; res = res->ai_next) { - if (res->ai_family != PF_INET) - continue; - log_debug("%s: ip_port: %s", __func__, - ip_port(res->ai_addr)); - - if ((httpsock = socket(AF_INET, SOCK_STREAM | - SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1) { - log_warn("%s: socket", __func__); - break; - } - if (connect(httpsock, res->ai_addr, res->ai_addrlen) == -1) { - if (errno != EINPROGRESS) { - log_warn("%s: connect", __func__); - close(httpsock); - break; - } + if (connect(httpsock, sa, sizeof(sin)) == -1) { + if (errno != EINPROGRESS) { + log_warn("%s: connect", __func__); + close(httpsock); + return; } - main_imsg_compose_captiveportal_fd(IMSG_HTTPSOCK, 0, - httpsock); } - freeaddrinfo(ar->ar_addrinfo); + main_imsg_compose_captiveportal_fd(IMSG_HTTPSOCK, 0, + httpsock); } void diff --git a/sbin/unwind/unwind.h b/sbin/unwind/unwind.h index 7079ec3ed72..2b64c071c30 100644 --- a/sbin/unwind/unwind.h +++ b/sbin/unwind/unwind.h @@ -1,4 +1,4 @@ -/* $OpenBSD: unwind.h,v 1.27 2019/11/14 08:30:10 florian Exp $ */ +/* $OpenBSD: unwind.h,v 1.28 2019/11/14 08:34:17 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -119,7 +119,7 @@ enum imsg_type { IMSG_NEW_TAS_ABORT, IMSG_NEW_TAS_DONE, IMSG_RECHECK_RESOLVERS, - IMSG_RESOLVE_CAPTIVE_PORTAL, + IMSG_CONNECT_CAPTIVE_PORTAL_HOST, IMSG_BLFD, IMSG_ADD_DNS, IMSG_REMOVE_DNS, |