summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2019-01-27 12:40:55 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2019-01-27 12:40:55 +0000
commit9f897e4c10474010ceaa248eee1de3023025d521 (patch)
tree191aebb47394ee632046a333c492e7e92bcd5b23
parent1f503548dc5c612a2465358b408a748d14bd22db (diff)
Implement DNS over TLS (DoT).
-rw-r--r--sbin/unwind/frontend.c12
-rw-r--r--sbin/unwind/printconf.c36
-rw-r--r--sbin/unwind/resolver.c61
-rw-r--r--sbin/unwind/resolver.h6
-rw-r--r--sbin/unwind/unwind.c25
-rw-r--r--sbin/unwind/unwind.conf.511
-rw-r--r--sbin/unwind/unwind.h4
-rw-r--r--sbin/unwind/uw_parse.y77
8 files changed, 214 insertions, 18 deletions
diff --git a/sbin/unwind/frontend.c b/sbin/unwind/frontend.c
index 4e2c3eb0277..7bf8f3733a4 100644
--- a/sbin/unwind/frontend.c
+++ b/sbin/unwind/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.4 2019/01/27 07:46:49 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.5 2019/01/27 12:40:54 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -298,6 +298,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
fatal(NULL);
memcpy(nconf, imsg.data, sizeof(struct unwind_conf));
SIMPLEQ_INIT(&nconf->unwind_forwarder_list);
+ SIMPLEQ_INIT(&nconf->unwind_dot_forwarder_list);
break;
case IMSG_RECONF_FORWARDER:
if ((unwind_forwarder = malloc(sizeof(struct
@@ -308,6 +309,15 @@ frontend_dispatch_main(int fd, short event, void *bula)
SIMPLEQ_INSERT_TAIL(&nconf->unwind_forwarder_list,
unwind_forwarder, entry);
break;
+ case IMSG_RECONF_DOT_FORWARDER:
+ if ((unwind_forwarder = malloc(sizeof(struct
+ unwind_forwarder))) == NULL)
+ fatal(NULL);
+ memcpy(unwind_forwarder, imsg.data, sizeof(struct
+ unwind_forwarder));
+ SIMPLEQ_INSERT_TAIL(&nconf->unwind_dot_forwarder_list,
+ unwind_forwarder, entry);
+ break;
case IMSG_RECONF_END:
merge_config(frontend_conf, nconf);
nconf = NULL;
diff --git a/sbin/unwind/printconf.c b/sbin/unwind/printconf.c
index 81e170f3b01..e6c70fa45ba 100644
--- a/sbin/unwind/printconf.c
+++ b/sbin/unwind/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.2 2019/01/27 07:46:49 florian Exp $ */
+/* $OpenBSD: printconf.c,v 1.3 2019/01/27 12:40:54 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -22,10 +22,12 @@
#include <event.h>
#include <imsg.h>
#include <stdio.h>
+#include <string.h>
#include "unwind.h"
const char* yesno(int);
+void print_forwarder(char *);
const char*
yesno(int flag)
@@ -34,17 +36,43 @@ yesno(int flag)
}
void
+print_forwarder(char *name)
+{
+ char *pos;
+
+ pos = strchr(name, '@');
+
+ if (pos != NULL) {
+ *pos = '\0';
+ printf("%s port %s", name, pos + 1);
+ *pos = '@';
+ } else
+ printf("%s", name);
+
+}
+
+void
print_config(struct unwind_conf *conf)
{
struct unwind_forwarder *unwind_forwarder;
printf("strict %s\n", yesno(conf->unwind_options));
- if (!SIMPLEQ_EMPTY(&conf->unwind_forwarder_list)) {
+ if (!SIMPLEQ_EMPTY(&conf->unwind_forwarder_list) ||
+ !SIMPLEQ_EMPTY(&conf->unwind_dot_forwarder_list)) {
printf("forwarder {\n");
SIMPLEQ_FOREACH(unwind_forwarder, &conf->unwind_forwarder_list,
- entry)
- printf("\t%s\n", unwind_forwarder->name);
+ entry) {
+ printf("\t");
+ print_forwarder(unwind_forwarder->name);
+ printf("\n");
+ }
+ SIMPLEQ_FOREACH(unwind_forwarder,
+ &conf->unwind_dot_forwarder_list, entry) {
+ printf("\t");
+ print_forwarder(unwind_forwarder->name);
+ printf(" DoT\n");
+ }
printf("}\n");
}
}
diff --git a/sbin/unwind/resolver.c b/sbin/unwind/resolver.c
index b030ca40022..9cd7f24d442 100644
--- a/sbin/unwind/resolver.c
+++ b/sbin/unwind/resolver.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolver.c,v 1.10 2019/01/27 07:46:49 florian Exp $ */
+/* $OpenBSD: resolver.c,v 1.11 2019/01/27 12:40:54 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -85,6 +85,7 @@ void parse_dhcp_forwarders(char *);
void new_recursor(void);
void new_forwarders(void);
void new_static_forwarders(void);
+void new_static_dot_forwarders(void);
struct unwind_resolver *create_resolver(enum unwind_resolver_type);
void free_resolver(struct unwind_resolver *);
void set_forwarders(struct unwind_resolver *,
@@ -123,6 +124,7 @@ struct imsgev *iev_frontend;
struct imsgev *iev_main;
struct unwind_forwarder_head dhcp_forwarder_list;
struct unwind_resolver *recursor, *forwarder, *static_forwarder;
+struct unwind_resolver *static_dot_forwarder;
struct timeval resolver_check_pause = { 30, 0};
struct event_base *ev_base;
@@ -376,6 +378,7 @@ resolver_dispatch_main(int fd, short event, void *bula)
struct imsgbuf *ibuf;
ssize_t n;
int shut = 0, forwarders_changed;
+ int dot_forwarders_changed;
ibuf = &iev->ibuf;
@@ -433,6 +436,7 @@ resolver_dispatch_main(int fd, short event, void *bula)
fatal(NULL);
memcpy(nconf, imsg.data, sizeof(struct unwind_conf));
SIMPLEQ_INIT(&nconf->unwind_forwarder_list);
+ SIMPLEQ_INIT(&nconf->unwind_dot_forwarder_list);
break;
case IMSG_RECONF_FORWARDER:
if ((unwind_forwarder = malloc(sizeof(struct
@@ -443,16 +447,32 @@ resolver_dispatch_main(int fd, short event, void *bula)
SIMPLEQ_INSERT_TAIL(&nconf->unwind_forwarder_list,
unwind_forwarder, entry);
break;
+ case IMSG_RECONF_DOT_FORWARDER:
+ if ((unwind_forwarder = malloc(sizeof(struct
+ unwind_forwarder))) == NULL)
+ fatal(NULL);
+ memcpy(unwind_forwarder, imsg.data, sizeof(struct
+ unwind_forwarder));
+ SIMPLEQ_INSERT_TAIL(&nconf->unwind_dot_forwarder_list,
+ unwind_forwarder, entry);
+ break;
case IMSG_RECONF_END:
forwarders_changed = check_forwarders_changed(
&resolver_conf->unwind_forwarder_list,
&nconf->unwind_forwarder_list);
+ dot_forwarders_changed = check_forwarders_changed(
+ &resolver_conf->unwind_dot_forwarder_list,
+ &nconf->unwind_dot_forwarder_list);
merge_config(resolver_conf, nconf);
nconf = NULL;
if (forwarders_changed) {
log_debug("static forwarders changed");
new_static_forwarders();
}
+ if (dot_forwarders_changed) {
+ log_debug("static DoT forwarders changed");
+ new_static_dot_forwarders();
+ }
break;
default:
log_debug("%s: unexpected imsg %d", __func__,
@@ -620,6 +640,25 @@ new_static_forwarders(void)
check_resolver(static_forwarder);
}
+void
+new_static_dot_forwarders(void)
+{
+ free_resolver(static_dot_forwarder);
+
+ if (SIMPLEQ_EMPTY(&resolver_conf->unwind_dot_forwarder_list)) {
+ static_dot_forwarder = NULL;
+ return;
+ }
+
+ log_debug("%s: create_resolver", __func__);
+ static_dot_forwarder = create_resolver(STATIC_DOT_FORWARDER);
+ set_forwarders(static_dot_forwarder,
+ &resolver_conf->unwind_dot_forwarder_list);
+ ub_ctx_set_tls(static_dot_forwarder->ctx, 1);
+
+ check_resolver(static_dot_forwarder);
+}
+
struct unwind_resolver *
create_resolver(enum unwind_resolver_type type)
{
@@ -742,6 +781,11 @@ check_resolver(struct unwind_resolver *res)
set_forwarders(check_res,
&resolver_conf->unwind_forwarder_list);
break;
+ case STATIC_DOT_FORWARDER:
+ set_forwarders(check_res,
+ &resolver_conf->unwind_dot_forwarder_list);
+ ub_ctx_set_tls(check_res->ctx, 1);
+ break;
case RESOLVER_NONE:
fatalx("type NONE");
break;
@@ -945,6 +989,11 @@ best_resolver(void)
unwind_resolver_type_str[static_forwarder->type],
unwind_resolver_state_str[static_forwarder->state]);
+ if (static_dot_forwarder != NULL)
+ log_debug("%s: %s state: %s", __func__,
+ unwind_resolver_type_str[static_dot_forwarder->type],
+ unwind_resolver_state_str[static_dot_forwarder->state]);
+
if (forwarder != NULL)
log_debug("%s: %s state: %s", __func__,
unwind_resolver_type_str[forwarder->type],
@@ -952,6 +1001,9 @@ best_resolver(void)
res = recursor;
+ if (resolver_cmp(res, static_dot_forwarder) < 0)
+ res = static_dot_forwarder;
+
if (resolver_cmp(res, static_forwarder) < 0)
res = static_forwarder;
@@ -1004,6 +1056,8 @@ show_status(enum unwind_resolver_type type, pid_t pid)
send_resolver_info(forwarder, forwarder == best, pid);
send_resolver_info(static_forwarder, static_forwarder == best,
pid);
+ send_resolver_info(static_dot_forwarder, static_dot_forwarder
+ == best, pid);
break;
case RECURSOR:
send_resolver_info(recursor, recursor == best, pid);
@@ -1018,6 +1072,11 @@ show_status(enum unwind_resolver_type type, pid_t pid)
pid);
send_detailed_resolver_info(static_forwarder, pid);
break;
+ case STATIC_DOT_FORWARDER:
+ send_resolver_info(static_dot_forwarder, static_dot_forwarder
+ == best, pid);
+ send_detailed_resolver_info(static_dot_forwarder, pid);
+ break;
}
resolver_imsg_compose_frontend(IMSG_CTL_END, pid, NULL, 0);
}
diff --git a/sbin/unwind/resolver.h b/sbin/unwind/resolver.h
index 9d5cc61c16d..da9525ba3a0 100644
--- a/sbin/unwind/resolver.h
+++ b/sbin/unwind/resolver.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolver.h,v 1.1 2019/01/23 13:11:00 florian Exp $ */
+/* $OpenBSD: resolver.h,v 1.2 2019/01/27 12:40:54 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -35,13 +35,15 @@ enum unwind_resolver_type {
RECURSOR,
FORWARDER,
STATIC_FORWARDER,
+ STATIC_DOT_FORWARDER,
RESOLVER_NONE = -1
};
static const char * const unwind_resolver_type_str[] = {
"recursor",
"dhcp forwarder",
- "static forwarder"
+ "static forwarder",
+ "DoT forwarder"
};
static const int64_t histogram_limits[] = {
diff --git a/sbin/unwind/unwind.c b/sbin/unwind/unwind.c
index 84e0c6c9b9c..11a6d776b41 100644
--- a/sbin/unwind/unwind.c
+++ b/sbin/unwind/unwind.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: unwind.c,v 1.4 2019/01/27 07:46:49 florian Exp $ */
+/* $OpenBSD: unwind.c,v 1.5 2019/01/27 12:40:54 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -577,7 +577,7 @@ main_imsg_send_config(struct unwind_conf *xconf)
if (main_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1)
return (-1);
- /* send static forarders to children */
+ /* send static forwarders to children */
SIMPLEQ_FOREACH(unwind_forwarder, &xconf->unwind_forwarder_list, entry) {
if (main_sendboth(IMSG_RECONF_FORWARDER, unwind_forwarder,
sizeof(*unwind_forwarder)) == -1)
@@ -585,6 +585,15 @@ main_imsg_send_config(struct unwind_conf *xconf)
}
+ /* send static DoT forwarders to children */
+ SIMPLEQ_FOREACH(unwind_forwarder, &xconf->unwind_dot_forwarder_list,
+ entry) {
+ if (main_sendboth(IMSG_RECONF_DOT_FORWARDER, unwind_forwarder,
+ sizeof(*unwind_forwarder)) == -1)
+ return (-1);
+
+ }
+
/* Tell children the revised config is now complete. */
if (main_sendboth(IMSG_RECONF_END, NULL, 0) == -1)
return (-1);
@@ -613,6 +622,11 @@ merge_config(struct unwind_conf *conf, struct unwind_conf *xconf)
SIMPLEQ_REMOVE_HEAD(&conf->unwind_forwarder_list, entry);
free(unwind_forwarder);
}
+ while ((unwind_forwarder =
+ SIMPLEQ_FIRST(&conf->unwind_dot_forwarder_list)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&conf->unwind_dot_forwarder_list, entry);
+ free(unwind_forwarder);
+ }
conf->unwind_options = xconf->unwind_options;
@@ -623,6 +637,12 @@ merge_config(struct unwind_conf *conf, struct unwind_conf *xconf)
SIMPLEQ_INSERT_TAIL(&conf->unwind_forwarder_list,
unwind_forwarder, entry);
}
+ while ((unwind_forwarder =
+ SIMPLEQ_FIRST(&xconf->unwind_dot_forwarder_list)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&xconf->unwind_dot_forwarder_list, entry);
+ SIMPLEQ_INSERT_TAIL(&conf->unwind_dot_forwarder_list,
+ unwind_forwarder, entry);
+ }
free(xconf);
}
@@ -637,6 +657,7 @@ config_new_empty(void)
fatal(NULL);
SIMPLEQ_INIT(&xconf->unwind_forwarder_list);
+ SIMPLEQ_INIT(&xconf->unwind_dot_forwarder_list);
return (xconf);
}
diff --git a/sbin/unwind/unwind.conf.5 b/sbin/unwind/unwind.conf.5
index 5efb0e1086c..e00c9929fdc 100644
--- a/sbin/unwind/unwind.conf.5
+++ b/sbin/unwind/unwind.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: unwind.conf.5,v 1.1 2019/01/23 13:11:00 florian Exp $
+.\" $OpenBSD: unwind.conf.5,v 1.2 2019/01/27 12:40:54 florian Exp $
.\"
.\" Copyright (c) 2018 Florian Obser <florian@openbsd.org>
.\" Copyright (c) 2005 Esben Norby <norby@openbsd.org>
@@ -18,7 +18,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: January 23 2019 $
+.Dd $Mdocdate: January 27 2019 $
.Dt UNWIND.CONF 5
.Os
.Sh NAME
@@ -52,8 +52,13 @@ Macro names may not be reserved words.
Macros are not expanded inside quotes.
.Sh GLOBAL CONFIGURATION
.Bl -tag -width Ds
-.It Ic forwarder Brq forwarder list
+.It Ic forwarder Brq Ar address Oo Ic port Ar number Oc Oo Ic DoT Oc ...
list of addresses of DNS name servers to forward queries to.
+If
+.Ic DoT
+is specified use DNS over TLS when sending queries to the server at
+.Ar address .
+
.El
.Sh FILES
.Bl -tag -width "/etc/unwind.conf" -compact
diff --git a/sbin/unwind/unwind.h b/sbin/unwind/unwind.h
index 916b26f6659..6f8701aef60 100644
--- a/sbin/unwind/unwind.h
+++ b/sbin/unwind/unwind.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: unwind.h,v 1.2 2019/01/24 17:39:43 florian Exp $ */
+/* $OpenBSD: unwind.h,v 1.3 2019/01/27 12:40:54 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -56,6 +56,7 @@ enum imsg_type {
IMSG_CTL_STATUS,
IMSG_RECONF_CONF,
IMSG_RECONF_FORWARDER,
+ IMSG_RECONF_DOT_FORWARDER,
IMSG_RECONF_END,
IMSG_UDP4SOCK,
IMSG_UDP6SOCK,
@@ -87,6 +88,7 @@ struct unwind_forwarder {
struct unwind_conf {
SIMPLEQ_HEAD(unwind_forwarder_head, unwind_forwarder) unwind_forwarder_list;
+ struct unwind_forwarder_head unwind_dot_forwarder_list;
int unwind_options;
};
diff --git a/sbin/unwind/uw_parse.y b/sbin/unwind/uw_parse.y
index 000c6888481..24d7863af8e 100644
--- a/sbin/unwind/uw_parse.y
+++ b/sbin/unwind/uw_parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: uw_parse.y,v 1.2 2019/01/24 15:59:32 florian Exp $ */
+/* $OpenBSD: uw_parse.y,v 1.3 2019/01/27 12:40:54 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -107,7 +107,7 @@ typedef struct {
%}
%token STRICT YES NO INCLUDE ERROR
-%token FORWARDER
+%token FORWARDER DOT PORT
%token <v.string> STRING
%token <v.number> NUMBER
@@ -211,6 +211,66 @@ forwarderoptsl : STRING {
&conf->unwind_forwarder_list,
unwind_forwarder, entry);
}
+ | STRING PORT NUMBER {
+ int ret;
+
+ if ($3 <= 0 || $3 > (int)USHRT_MAX) {
+ yyerror("invalid port: %lld", $3);
+ YYERROR;
+ }
+
+ if ((unwind_forwarder = calloc(1,
+ sizeof(*unwind_forwarder))) == NULL)
+ err(1, NULL);
+
+ ret = snprintf(unwind_forwarder->name,
+ sizeof(unwind_forwarder->name), "%s@%d", $1,
+ (int)$3);
+ if (ret == -1 || (size_t)ret >=
+ sizeof(unwind_forwarder->name))
+ err(1, "%s too long", $1);
+
+ SIMPLEQ_INSERT_TAIL(
+ &conf->unwind_forwarder_list,
+ unwind_forwarder, entry);
+ }
+ | STRING DOT {
+ if ((unwind_forwarder = calloc(1,
+ sizeof(*unwind_forwarder))) == NULL)
+ err(1, NULL);
+
+ if(strlcpy(unwind_forwarder->name, $1,
+ sizeof(unwind_forwarder->name)) >=
+ sizeof(unwind_forwarder->name))
+ err(1, "%s too long", $1);
+
+ SIMPLEQ_INSERT_TAIL(
+ &conf->unwind_dot_forwarder_list,
+ unwind_forwarder, entry);
+ }
+ | STRING PORT NUMBER DOT {
+ int ret;
+
+ if ($3 <= 0 || $3 > (int)USHRT_MAX) {
+ yyerror("invalid port: %lld", $3);
+ YYERROR;
+ }
+
+ if ((unwind_forwarder = calloc(1,
+ sizeof(*unwind_forwarder))) == NULL)
+ err(1, NULL);
+
+ ret = snprintf(unwind_forwarder->name,
+ sizeof(unwind_forwarder->name), "%s@%d", $1,
+ (int)$3);
+ if (ret == -1 || (size_t)ret >=
+ sizeof(unwind_forwarder->name))
+ err(1, "%s too long", $1);
+
+ SIMPLEQ_INSERT_TAIL(
+ &conf->unwind_dot_forwarder_list,
+ unwind_forwarder, entry);
+ }
;
%%
@@ -246,10 +306,14 @@ lookup(char *s)
{
/* This has to be sorted always. */
static const struct keywords keywords[] = {
+ {"dot", DOT},
+ {"DoT", DOT},
{"forwarder", FORWARDER},
{"include", INCLUDE},
{"no", NO},
+ {"port", PORT},
{"strict", STRICT},
+ {"tls", DOT},
{"yes", YES},
};
const struct keywords *p;
@@ -713,11 +777,16 @@ symget(const char *nam)
void
clear_config(struct unwind_conf *xconf)
{
- while((unwind_forwarder = SIMPLEQ_FIRST(&xconf->unwind_forwarder_list)) !=
- NULL) {
+ while((unwind_forwarder =
+ SIMPLEQ_FIRST(&xconf->unwind_forwarder_list)) != NULL) {
SIMPLEQ_REMOVE_HEAD(&xconf->unwind_forwarder_list, entry);
free(unwind_forwarder);
}
+ while((unwind_forwarder =
+ SIMPLEQ_FIRST(&xconf->unwind_dot_forwarder_list)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&xconf->unwind_dot_forwarder_list, entry);
+ free(unwind_forwarder);
+ }
free(xconf);
}