From: Evan Hunt Date: Wed, 16 Sep 2020 19:21:32 +0000 (-0700) Subject: Add parser support for DoH configuration options X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=37f81ca5fbcf575489dcfab705f8ff6ae91b13b2;p=thirdparty%2Fbind9.git Add parser support for DoH configuration options This commit adds stub parser support and tests for: - an "https-server" global option for HTTP/2 configuration. - an "https-endpoint" view option for DoH configuration. - add specific -p options to set dns, tls, or https port numbers by specifying -p dns-PORT, -p tls=PORT, or -p https=PORT. NOTE: this change only affects syntax; specifying the TLS port on the command line DOES NOT CURRENTLY HAVE ANY EFFECT. - change option names to tls-port and https-port for consistency. - change variable names in system tests to TLSPORT and HTTPSPORT, and report them when running tests. Documentation for these options has also been added to the ARM, but needs further work. --- diff --git a/bin/named/config.c b/bin/named/config.c index 72094f8302e..123e277349b 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -94,6 +94,7 @@ options {\n\ # pid-file \"" NAMED_LOCALSTATEDIR "/run/named/named.pid\"; \n\ port 53;\n\ tls-port 853;\n\ + https-port 443;\n\ prefetch 2 9;\n\ recursing-file \"named.recursing\";\n\ recursive-clients 1000;\n\ diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 501bedaea4c..3671211bb9b 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -73,6 +73,7 @@ EXTERN const char *named_g_configargs INIT(PACKAGE_CONFIGARGS); EXTERN const char *named_g_builder INIT(PACKAGE_BUILDER); EXTERN in_port_t named_g_port INIT(0); EXTERN in_port_t named_g_tlsport INIT(0); +EXTERN in_port_t named_g_http_secure_port INIT(0); EXTERN isc_dscp_t named_g_dscp INIT(-1); EXTERN named_server_t *named_g_server INIT(NULL); diff --git a/bin/named/main.c b/bin/named/main.c index eacb18cc813..c803934859b 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -705,7 +705,7 @@ parse_T_opt(char *option) { static void parse_port(char *arg) { - enum { DNSPORT, TLSPORT } ptype = DNSPORT; + enum { DNSPORT, TLSPORT, HTTP_SECURE_PORT } ptype = DNSPORT; char *value = arg; int port; @@ -714,6 +714,9 @@ parse_port(char *arg) { } else if (strncmp(arg, "tls=", 4) == 0) { value = arg + 4; ptype = TLSPORT; + } else if (strncmp(arg, "https=", 6) == 0) { + value = arg + 6; + ptype = HTTP_SECURE_PORT; } port = parse_int(value, "port"); @@ -728,6 +731,9 @@ parse_port(char *arg) { case TLSPORT: named_g_tlsport = port; break; + case HTTP_SECURE_PORT: + named_g_http_secure_port = port; + break; default: INSIST(0); ISC_UNREACHABLE(); diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst index 722c514dbce..2ba2f2f6bc6 100644 --- a/bin/named/named.conf.rst +++ b/bin/named/named.conf.rst @@ -264,6 +264,12 @@ OPTIONS glue-cache boolean;// deprecated heartbeat-interval integer; hostname ( quoted_string | none ); + https-endpoint quoted_string https-server string; + https-port integer; + https-server string [ port integer ] tls string { ( + quoted_string [ port integer ] [ dscp integer ] | + ipv4_address [ port integer ] [ dscp integer ] | + ipv6_address [ port integer ] [ dscp integer ] ); ... }; inline-signing boolean; interface-interval duration; ipv4only-contact string; @@ -652,6 +658,7 @@ VIEW forwarders [ port integer ] [ dscp integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ dscp integer ]; ... }; glue-cache boolean;// deprecated + https-endpoint quoted_string https-server string; inline-signing boolean; ipv4only-contact string; ipv4only-enable boolean; diff --git a/bin/named/named.rst b/bin/named/named.rst index 9b039cdbf02..c2b19f6dd60 100644 --- a/bin/named/named.rst +++ b/bin/named/named.rst @@ -115,7 +115,9 @@ Options ``portnum``; if not not specified, the default is port 53. If ``value`` is of the form ``tls=``, the server will listen for TLS queries on ``portnum``; the default is 853. - + If ``value`` is of the form ``https=``, the server will + listen for HTTPS queries on ``portnum``; the default is 443. + ``-s`` This option writes memory usage statistics to ``stdout`` on exit. diff --git a/bin/tests/system/checkconf/good-doh-global.conf b/bin/tests/system/checkconf/good-doh-global.conf new file mode 100644 index 00000000000..83711d6329d --- /dev/null +++ b/bin/tests/system/checkconf/good-doh-global.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on { 10.53.0.1; }; + https-server local-server port 443 tls local-tls { 10.53.0.1; }; + https-endpoint "/dns-query" https-server local-server; +}; diff --git a/bin/tests/system/checkconf/good-doh-view.conf b/bin/tests/system/checkconf/good-doh-view.conf new file mode 100644 index 00000000000..cdbce797418 --- /dev/null +++ b/bin/tests/system/checkconf/good-doh-view.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on { 10.53.0.1; }; + https-server local-server port 443 tls local-tls { 10.53.0.1; }; +}; + +view one { + https-endpoint "/dns-query" https-server local-server; +}; diff --git a/bin/tests/system/checkconf/good-dot-global.conf b/bin/tests/system/checkconf/good-dot-global.conf new file mode 100644 index 00000000000..2a1729752d1 --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-global.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/conf.sh.common b/bin/tests/system/conf.sh.common index de998c050e5..df88dd1d106 100644 --- a/bin/tests/system/conf.sh.common +++ b/bin/tests/system/conf.sh.common @@ -668,6 +668,7 @@ copy_setports() { atsign="@" sed -e "s/${atsign}PORT${atsign}/${PORT}/g" \ -e "s/${atsign}TLSPORT${atsign}/${TLSPORT}/g" \ + -e "s/${atsign}HTTPSPORT${atsign}/${HTTPSPORT}/g" \ -e "s/${atsign}EXTRAPORT1${atsign}/${EXTRAPORT1}/g" \ -e "s/${atsign}EXTRAPORT2${atsign}/${EXTRAPORT2}/g" \ -e "s/${atsign}EXTRAPORT3${atsign}/${EXTRAPORT3}/g" \ diff --git a/bin/tests/system/get_ports.sh b/bin/tests/system/get_ports.sh index eac854d65c8..f63ba472535 100755 --- a/bin/tests/system/get_ports.sh +++ b/bin/tests/system/get_ports.sh @@ -82,6 +82,7 @@ done echo "export PORT=$(get_port "$baseport")" echo "export TLSPORT=$(get_port)" +echo "export HTTPSPORT=$(get_port)" echo "export EXTRAPORT1=$(get_port)" echo "export EXTRAPORT2=$(get_port)" echo "export EXTRAPORT3=$(get_port)" diff --git a/bin/tests/system/run.sh.in b/bin/tests/system/run.sh.in index e802332c8cc..38021817622 100644 --- a/bin/tests/system/run.sh.in +++ b/bin/tests/system/run.sh.in @@ -149,7 +149,7 @@ stop_servers() { echostart "S:$systest:$(date_with_args)" echoinfo "T:$systest:1:A" echoinfo "A:$systest:System test $systest" -echoinfo "I:$systest:PORTS:${PORT},${TLSPORT},${EXTRAPORT1},${EXTRAPORT2},${EXTRAPORT3},${EXTRAPORT4},${EXTRAPORT5},${EXTRAPORT6},${EXTRAPORT7},${EXTRAPORT8},${CONTROLPORT}" +echoinfo "I:$systest:PORTS:${PORT},${TLSPORT},${HTTPSPORT},${EXTRAPORT1},${EXTRAPORT2},${EXTRAPORT3},${EXTRAPORT4},${EXTRAPORT5},${EXTRAPORT6},${EXTRAPORT7},${EXTRAPORT8},${CONTROLPORT}" $PERL ${srcdir}/testsock.pl -p "$PORT" || { echowarn "I:$systest:Network interface aliases not set up. Skipping test." diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index f3599be319f..b699da9171b 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -1078,6 +1078,14 @@ default is used. the default is the ``named`` working directory. See :ref:`acl` for details about ``geoip`` ACLs. +.. _https_endpoint: + +``https-endpoint`` + This configures an DNS-over-HTTPS service endpoint. It takes a string + which specifies the endpoint URL path, and an ``https-server`` + parameter specifying the server name of an HTTPS listener. (See + :ref:`Link title `.) + ``key-directory`` This is the directory where the public and private DNSSEC key files should be found when performing a dynamic update of secure zones, if different @@ -2436,6 +2444,8 @@ Interfaces The interfaces and ports that the server answers queries from may be specified using the ``listen-on`` and ``listen-on-v6`` options. +specified using the ``listen-on`` and ``listen-on-v6`` options, as +well as the ``https-server`` option for HTTPS queries. ``listen-on`` takes an optional port, an optional TLS configuration identifier, and an ``address_match_list`` of IPv4 addresses. (IPv6 @@ -2488,6 +2498,15 @@ To instruct the server not to listen on any IPv6 addresses, use: listen-on-v6 { none; }; +.. _https_server: + +``https-server`` takes a server name, an optional port, a TLS +configuration identifier, and an ``address_match_list`` of both IPv4 and +IPv6 addresses. This sets up an HTTPS responder using the key and +certificate specified in the referenced ``tls`` statement. The endpoint +for incoming HTTPS queries must be specified using the ``https-endpoint`` +option (see :ref:`Link title `). + .. _query_address: Query Address diff --git a/doc/man/named.8in b/doc/man/named.8in index db3ddd4176b..f758454cdeb 100644 --- a/doc/man/named.8in +++ b/doc/man/named.8in @@ -115,6 +115,8 @@ for queries. If \fBvalue\fP is of the form \fB\fP or \fBportnum\fP; if not not specified, the default is port 53. If \fBvalue\fP is of the form \fBtls=\fP, the server will listen for TLS queries on \fBportnum\fP; the default is 853. +If \fBvalue\fP is of the form \fBhttps=\fP, the server will +listen for HTTPS queries on \fBportnum\fP; the default is 443. .TP .B \fB\-s\fP This option writes memory usage statistics to \fBstdout\fP on exit. diff --git a/doc/man/named.conf.5in b/doc/man/named.conf.5in index 7884fd5f28c..ac9d03ded39 100644 --- a/doc/man/named.conf.5in +++ b/doc/man/named.conf.5in @@ -327,6 +327,12 @@ options { glue\-cache boolean;// deprecated heartbeat\-interval integer; hostname ( quoted_string | none ); + https\-endpoint quoted_string https\-server string; + https\-port integer; + https\-server string [ port integer ] tls string { ( + quoted_string [ port integer ] [ dscp integer ] | + ipv4_address [ port integer ] [ dscp integer ] | + ipv6_address [ port integer ] [ dscp integer ] ); ... }; inline\-signing boolean; interface\-interval duration; ipv4only\-contact string; @@ -747,6 +753,7 @@ view string [ class ] { forwarders [ port integer ] [ dscp integer ] { ( ipv4_address | ipv6_address ) [ port integer ] [ dscp integer ]; ... }; glue\-cache boolean;// deprecated + https\-endpoint quoted_string https\-server string; inline\-signing boolean; ipv4only\-contact string; ipv4only\-enable boolean; diff --git a/doc/misc/options b/doc/misc/options index 1e5bedec9c3..c1fd8248084 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -193,6 +193,12 @@ options { glue-cache ; // deprecated heartbeat-interval ; hostname ( | none ); + https-endpoint https-server ; + https-port ; + https-server [ port ] tls { ( + [ port ] [ dscp ] | + [ port ] [ dscp ] | + [ port ] [ dscp ] ); ... }; inline-signing ; interface-interval ; ipv4only-contact ; @@ -541,6 +547,7 @@ view [ ] { forwarders [ port ] [ dscp ] { ( | ) [ port ] [ dscp ]; ... }; glue-cache ; // deprecated + https-endpoint https-server ; inline-signing ; ipv4only-contact ; ipv4only-enable ; diff --git a/doc/misc/options.active b/doc/misc/options.active index 0e007d68554..2bafa0664ee 100644 --- a/doc/misc/options.active +++ b/doc/misc/options.active @@ -192,6 +192,12 @@ options { glue-cache ; // deprecated heartbeat-interval ; hostname ( | none ); + https-endpoint https-server ; + https-port ; + https-server [ port ] tls { ( + [ port ] [ dscp ] | + [ port ] [ dscp ] | + [ port ] [ dscp ] ); ... }; inline-signing ; interface-interval ; ipv4only-contact ; @@ -538,6 +544,7 @@ view [ ] { forwarders [ port ] [ dscp ] { ( | ) [ port ] [ dscp ]; ... }; glue-cache ; // deprecated + https-endpoint https-server ; inline-signing ; ipv4only-contact ; ipv4only-enable ; diff --git a/doc/misc/options.grammar.rst b/doc/misc/options.grammar.rst index 30aee7b7c98..5e8d8d04f54 100644 --- a/doc/misc/options.grammar.rst +++ b/doc/misc/options.grammar.rst @@ -119,6 +119,12 @@ glue-cache ; // deprecated heartbeat-interval ; hostname ( | none ); + https-endpoint https-server ; + https-port ; + https-server [ port ] tls { ( + [ port ] [ dscp ] | + [ port ] [ dscp ] | + [ port ] [ dscp ] ); ... }; inline-signing ; interface-interval ; ipv4only-contact ; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index c18196ea5b3..75e81cd297d 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -91,6 +91,8 @@ static cfg_type_t cfg_type_dnstap; static cfg_type_t cfg_type_dnstapoutput; static cfg_type_t cfg_type_dyndb; static cfg_type_t cfg_type_plugin; +static cfg_type_t cfg_type_http_secure_endpoint; +static cfg_type_t cfg_type_http_secure_server; static cfg_type_t cfg_type_ixfrdifftype; static cfg_type_t cfg_type_ixfrratio; static cfg_type_t cfg_type_key; @@ -1205,6 +1207,7 @@ static cfg_clausedef_t options_clauses[] = { { "host-statistics", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "host-statistics-max", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "hostname", &cfg_type_qstringornone, 0 }, + { "https-server", &cfg_type_http_secure_server, 0 }, { "interface-interval", &cfg_type_duration, 0 }, { "keep-response-order", &cfg_type_bracketed_aml, 0 }, { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, @@ -1221,6 +1224,7 @@ static cfg_clausedef_t options_clauses[] = { { "pid-file", &cfg_type_qstringornone, 0 }, { "port", &cfg_type_uint32, 0 }, { "tls-port", &cfg_type_uint32, 0 }, + { "https-port", &cfg_type_uint32, 0 }, { "querylog", &cfg_type_boolean, 0 }, { "random-device", &cfg_type_qstringornone, 0 }, { "recursing-file", &cfg_type_qstring, 0 }, @@ -1988,6 +1992,7 @@ static cfg_clausedef_t view_clauses[] = { { "filter-aaaa-on-v4", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT }, { "filter-aaaa-on-v6", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT }, { "glue-cache", &cfg_type_boolean, CFG_CLAUSEFLAG_DEPRECATED }, + { "https-endpoint", &cfg_type_http_secure_endpoint, 0 }, { "ipv4only-enable", &cfg_type_boolean, 0 }, { "ipv4only-contact", &cfg_type_astring, 0 }, { "ipv4only-server", &cfg_type_astring, 0 }, @@ -3853,3 +3858,35 @@ static cfg_type_t cfg_type_optional_tls = { "tlsoptional", parse_optional_keyvalue, print_keyvalue, doc_optional_keyvalue, &cfg_rep_string, &tls_kw }; +static cfg_type_t cfg_type_tls = { "tls", parse_keyvalue, + print_keyvalue, doc_keyvalue, + &cfg_rep_string, &tls_kw }; + +static keyword_type_t servername_kw = { "https-server", &cfg_type_astring }; +static cfg_type_t cfg_type_servername = { "servername", parse_keyvalue, + print_keyvalue, doc_keyvalue, + &cfg_rep_string, &servername_kw }; + +/* http-endpoint */ +static cfg_tuplefielddef_t endpoint_fields[] = { + { "path", &cfg_type_qstring, 0 }, + { "servername", &cfg_type_servername, 0 }, + { NULL, NULL, 0 } +}; +static cfg_type_t cfg_type_http_secure_endpoint = { + "endpoint", cfg_parse_tuple, cfg_print_tuple, + cfg_doc_tuple, &cfg_rep_tuple, endpoint_fields +}; + +/* http-server */ +static cfg_tuplefielddef_t server_fields[] = { + { "name", &cfg_type_astring, 0 }, + { "port", &cfg_type_optional_port, 0 }, + { "tls", &cfg_type_tls, 0 }, + { "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 }, + { NULL, NULL, 0 } +}; +static cfg_type_t cfg_type_http_secure_server = { + "server", cfg_parse_tuple, cfg_print_tuple, + cfg_doc_tuple, &cfg_rep_tuple, server_fields +};