mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
Add parser support for DoH configuration options
This commit adds stub parser support and tests for: - an "http" global option for HTTP/2 endpoint configuration. - command line options to set http or https port numbers by specifying -p http=PORT or -p https=PORT. (NOTE: this change only affects syntax; specifying HTTP and HTTPS ports on the command line currently has no effect.) - named.conf options "http-port" and "https-port" - HTTPSPORT environment variable for use when running tests.
This commit is contained in:
parent
6b9a31989c
commit
06951472dd
@ -94,6 +94,8 @@ options {\n\
|
||||
# pid-file \"" NAMED_LOCALSTATEDIR "/run/named/named.pid\"; \n\
|
||||
port 53;\n\
|
||||
tls-port 853;\n\
|
||||
http-port 80;\n\
|
||||
https-port 443;\n\
|
||||
prefetch 2 9;\n\
|
||||
recursing-file \"named.recursing\";\n\
|
||||
recursive-clients 1000;\n\
|
||||
|
@ -73,6 +73,8 @@ 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_httpport INIT(0);
|
||||
EXTERN in_port_t named_g_httpsport INIT(0);
|
||||
EXTERN isc_dscp_t named_g_dscp INIT(-1);
|
||||
|
||||
EXTERN named_server_t *named_g_server INIT(NULL);
|
||||
|
@ -705,7 +705,7 @@ parse_T_opt(char *option) {
|
||||
|
||||
static void
|
||||
parse_port(char *arg) {
|
||||
enum { DNSPORT, TLSPORT } ptype = DNSPORT;
|
||||
enum { DNSPORT, TLSPORT, HTTPSPORT, HTTPPORT } ptype = DNSPORT;
|
||||
char *value = arg;
|
||||
int port;
|
||||
|
||||
@ -714,6 +714,12 @@ 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 = HTTPSPORT;
|
||||
} else if (strncmp(arg, "http=", 5) == 0) {
|
||||
value = arg + 6;
|
||||
ptype = HTTPPORT;
|
||||
}
|
||||
|
||||
port = parse_int(value, "port");
|
||||
@ -728,6 +734,12 @@ parse_port(char *arg) {
|
||||
case TLSPORT:
|
||||
named_g_tlsport = port;
|
||||
break;
|
||||
case HTTPSPORT:
|
||||
named_g_httpsport = port;
|
||||
break;
|
||||
case HTTPPORT:
|
||||
named_g_httpport = port;
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
@ -86,6 +86,15 @@ DYNDB
|
||||
dyndb string quoted_string {
|
||||
unspecified-text };
|
||||
|
||||
HTTP
|
||||
^^^^
|
||||
|
||||
::
|
||||
|
||||
http string {
|
||||
endpoints { quoted_string; ... };
|
||||
};
|
||||
|
||||
KEY
|
||||
^^^
|
||||
|
||||
@ -264,6 +273,8 @@ OPTIONS
|
||||
glue-cache boolean;// deprecated
|
||||
heartbeat-interval integer;
|
||||
hostname ( quoted_string | none );
|
||||
http-port integer;
|
||||
https-port integer;
|
||||
inline-signing boolean;
|
||||
interface-interval duration;
|
||||
ipv4only-contact string;
|
||||
@ -275,10 +286,12 @@ OPTIONS
|
||||
key-directory quoted_string;
|
||||
lame-ttl duration;
|
||||
listen-on [ port integer ] [ dscp
|
||||
integer ] [ tls string ] {
|
||||
integer ] [ tls string ] [ http
|
||||
string ] {
|
||||
address_match_element; ... };
|
||||
listen-on-v6 [ port integer ] [ dscp
|
||||
integer ] [ tls string ] {
|
||||
integer ] [ tls string ] [ http
|
||||
string ] {
|
||||
address_match_element; ... };
|
||||
lmdb-mapsize sizeval;
|
||||
lock-file ( quoted_string | none );
|
||||
|
@ -115,7 +115,9 @@ Options
|
||||
``portnum``; if not not specified, the default is port 53. If
|
||||
``value`` is of the form ``tls=<portnum>``, the server will
|
||||
listen for TLS queries on ``portnum``; the default is 853.
|
||||
|
||||
If ``value`` is of the form ``https=<portnum>``, the server will
|
||||
listen for HTTPS queries on ``portnum``; the default is 443.
|
||||
|
||||
``-s``
|
||||
This option writes memory usage statistics to ``stdout`` on exit.
|
||||
|
||||
|
27
bin/tests/system/checkconf/good-doh-global.conf
Normal file
27
bin/tests/system/checkconf/good-doh-global.conf
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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";
|
||||
};
|
||||
|
||||
http local-http-server {
|
||||
endpoints { "/dns-query"; };
|
||||
};
|
||||
|
||||
options {
|
||||
listen-on { 10.53.0.1; };
|
||||
http-port 80;
|
||||
https-port 443;
|
||||
listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; };
|
||||
listen-on port 8080 http local-http-server { 10.53.0.1; };
|
||||
};
|
19
bin/tests/system/checkconf/good-dot-global.conf
Normal file
19
bin/tests/system/checkconf/good-dot-global.conf
Normal file
@ -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; };
|
||||
};
|
@ -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" \
|
||||
|
@ -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)"
|
||||
|
@ -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."
|
||||
|
@ -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 a DNS-over-HTTPS (DoH) 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 <https_server>`.)
|
||||
|
||||
``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 <https_endpoint>`).
|
||||
|
||||
.. _query_address:
|
||||
|
||||
Query Address
|
||||
|
@ -115,6 +115,8 @@ for queries. If \fBvalue\fP is of the form \fB<portnum>\fP or
|
||||
\fBportnum\fP; if not not specified, the default is port 53. If
|
||||
\fBvalue\fP is of the form \fBtls=<portnum>\fP, the server will
|
||||
listen for TLS queries on \fBportnum\fP; the default is 853.
|
||||
If \fBvalue\fP is of the form \fBhttps=<portnum>\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.
|
||||
|
@ -132,6 +132,19 @@ dyndb string quoted_string {
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SS HTTP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
http string {
|
||||
endpoints { quoted_string; ... };
|
||||
};
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SS KEY
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
@ -327,6 +340,8 @@ options {
|
||||
glue\-cache boolean;// deprecated
|
||||
heartbeat\-interval integer;
|
||||
hostname ( quoted_string | none );
|
||||
http\-port integer;
|
||||
https\-port integer;
|
||||
inline\-signing boolean;
|
||||
interface\-interval duration;
|
||||
ipv4only\-contact string;
|
||||
@ -338,10 +353,12 @@ options {
|
||||
key\-directory quoted_string;
|
||||
lame\-ttl duration;
|
||||
listen\-on [ port integer ] [ dscp
|
||||
integer ] [ tls string ] {
|
||||
integer ] [ tls string ] [ http
|
||||
string ] {
|
||||
address_match_element; ... };
|
||||
listen\-on\-v6 [ port integer ] [ dscp
|
||||
integer ] [ tls string ] {
|
||||
integer ] [ tls string ] [ http
|
||||
string ] {
|
||||
address_match_element; ... };
|
||||
lmdb\-mapsize sizeval;
|
||||
lock\-file ( quoted_string | none );
|
||||
|
@ -37,7 +37,8 @@ OPTIONS_FILES = \
|
||||
tls.grammar.rst \
|
||||
trust-anchors.grammar.rst \
|
||||
managed-keys.grammar.rst \
|
||||
trusted-keys.grammar.rst
|
||||
trusted-keys.grammar.rst \
|
||||
http.grammar.rst
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(OPTIONS_FILES) \
|
||||
@ -175,4 +176,7 @@ managed-keys.grammar.rst: options.active
|
||||
trusted-keys.grammar.rst: options.active
|
||||
$(AM_V_RST_GRAMMARS)$(PERL) $(srcdir)/rst-grammars.pl options.active trusted-keys > $@
|
||||
|
||||
http.grammar.rst: options.active
|
||||
$(AM_V_RST_GRAMMARS)$(PERL) $(srcdir)/rst-grammars.pl options.active http > $@
|
||||
|
||||
endif
|
||||
|
5
doc/misc/http.grammar.rst
Normal file
5
doc/misc/http.grammar.rst
Normal file
@ -0,0 +1,5 @@
|
||||
::
|
||||
|
||||
http <string> {
|
||||
endpoints { <quoted_string>; ... };
|
||||
};
|
@ -42,6 +42,10 @@ dnssec-policy <string> {
|
||||
dyndb <string> <quoted_string> {
|
||||
<unspecified-text> }; // may occur multiple times
|
||||
|
||||
http <string> {
|
||||
endpoints { <quoted_string>; ... };
|
||||
}; // may occur multiple times
|
||||
|
||||
key <string> {
|
||||
algorithm <string>;
|
||||
secret <string>;
|
||||
@ -193,6 +197,8 @@ options {
|
||||
glue-cache <boolean>; // deprecated
|
||||
heartbeat-interval <integer>;
|
||||
hostname ( <quoted_string> | none );
|
||||
http-port <integer>;
|
||||
https-port <integer>;
|
||||
inline-signing <boolean>;
|
||||
interface-interval <duration>;
|
||||
ipv4only-contact <string>;
|
||||
@ -204,10 +210,12 @@ options {
|
||||
key-directory <quoted_string>;
|
||||
lame-ttl <duration>;
|
||||
listen-on [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... }; // may occur multiple times
|
||||
listen-on-v6 [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... }; // may occur multiple times
|
||||
lmdb-mapsize <sizeval>;
|
||||
lock-file ( <quoted_string> | none );
|
||||
|
@ -41,6 +41,10 @@ dnssec-policy <string> {
|
||||
dyndb <string> <quoted_string> {
|
||||
<unspecified-text> }; // may occur multiple times
|
||||
|
||||
http <string> {
|
||||
endpoints { <quoted_string>; ... };
|
||||
}; // may occur multiple times
|
||||
|
||||
key <string> {
|
||||
algorithm <string>;
|
||||
secret <string>;
|
||||
@ -192,6 +196,8 @@ options {
|
||||
glue-cache <boolean>; // deprecated
|
||||
heartbeat-interval <integer>;
|
||||
hostname ( <quoted_string> | none );
|
||||
http-port <integer>;
|
||||
https-port <integer>;
|
||||
inline-signing <boolean>;
|
||||
interface-interval <duration>;
|
||||
ipv4only-contact <string>;
|
||||
@ -203,10 +209,12 @@ options {
|
||||
key-directory <quoted_string>;
|
||||
lame-ttl <duration>;
|
||||
listen-on [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... }; // may occur multiple times
|
||||
listen-on-v6 [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... }; // may occur multiple times
|
||||
lmdb-mapsize <sizeval>;
|
||||
lock-file ( <quoted_string> | none );
|
||||
|
@ -119,6 +119,8 @@
|
||||
glue-cache <boolean>; // deprecated
|
||||
heartbeat-interval <integer>;
|
||||
hostname ( <quoted_string> | none );
|
||||
http-port <integer>;
|
||||
https-port <integer>;
|
||||
inline-signing <boolean>;
|
||||
interface-interval <duration>;
|
||||
ipv4only-contact <string>;
|
||||
@ -130,10 +132,12 @@
|
||||
key-directory <quoted_string>;
|
||||
lame-ttl <duration>;
|
||||
listen-on [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... };
|
||||
listen-on-v6 [ port <integer> ] [ dscp
|
||||
<integer> ] [ tls <string> ] {
|
||||
<integer> ] [ tls <string> ] [ http
|
||||
<string> ] {
|
||||
<address_match_element>; ... };
|
||||
lmdb-mapsize <sizeval>;
|
||||
lock-file ( <quoted_string> | none );
|
||||
|
@ -52,6 +52,13 @@ New Features
|
||||
an optional ``tls`` option which specifies either a previously configured
|
||||
``tls`` statement or ``ephemeral``. [GL #2392]
|
||||
|
||||
- ``named`` now has initial support for DNS-over-HTTP(S). Both
|
||||
encrypted (via TLS) and unencrypted HTTP/2 connections are supported.
|
||||
The latter are mostly there for debugging/troubleshooting
|
||||
purposes and for the means of encryption offloading to third-party
|
||||
software (as might be desirable in some environments to aid in TLS
|
||||
certificates management). [GL !4566]
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -7,17 +7,21 @@ libisccfg_la_HEADERS = \
|
||||
include/isccfg/aclconf.h \
|
||||
include/isccfg/cfg.h \
|
||||
include/isccfg/grammar.h \
|
||||
include/isccfg/httpconf.h \
|
||||
include/isccfg/kaspconf.h \
|
||||
include/isccfg/log.h \
|
||||
include/isccfg/namedconf.h
|
||||
include/isccfg/namedconf.h \
|
||||
include/isccfg/tlsconf.h
|
||||
|
||||
libisccfg_la_SOURCES = \
|
||||
$(libisccfg_la_HEADERS) \
|
||||
aclconf.c \
|
||||
httpconf.c \
|
||||
dnsconf.c \
|
||||
kaspconf.c \
|
||||
log.c \
|
||||
namedconf.c \
|
||||
tlsconf.c \
|
||||
parser.c
|
||||
|
||||
libisccfg_la_CPPFLAGS = \
|
||||
|
180
lib/isccfg/httpconf.c
Normal file
180
lib/isccfg/httpconf.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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 https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <isccfg/grammar.h>
|
||||
#include <isccfg/httpconf.h>
|
||||
|
||||
void
|
||||
cfg_http_storage_init(isc_mem_t *mctx, isc_cfg_http_storage_t *storage) {
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
memset(storage, 0, sizeof(*storage));
|
||||
isc_mem_attach(mctx, &storage->mctx);
|
||||
ISC_LIST_INIT(storage->list);
|
||||
}
|
||||
|
||||
void
|
||||
cfg_http_storage_uninit(isc_cfg_http_storage_t *storage) {
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
cfg_http_storage_clear(storage);
|
||||
isc_mem_detach(&storage->mctx);
|
||||
}
|
||||
|
||||
void
|
||||
cfg_http_storage_clear(isc_cfg_http_storage_t *storage) {
|
||||
isc_mem_t *mctx = NULL;
|
||||
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
mctx = storage->mctx;
|
||||
|
||||
if (!ISC_LIST_EMPTY(storage->list)) {
|
||||
isc_cfg_http_obj_t *http = ISC_LIST_HEAD(storage->list);
|
||||
while (http != NULL) {
|
||||
isc_cfg_http_obj_t *next = ISC_LIST_NEXT(http, link);
|
||||
ISC_LIST_DEQUEUE(storage->list, http, link);
|
||||
storage->count--;
|
||||
|
||||
isc_mem_free(mctx, http->name);
|
||||
|
||||
if (!ISC_LIST_EMPTY(http->endpoints)) {
|
||||
isc_cfg_http_endpoint_t *ep =
|
||||
ISC_LIST_HEAD(http->endpoints);
|
||||
while (ep != NULL) {
|
||||
isc_cfg_http_endpoint_t *epnext =
|
||||
ISC_LIST_NEXT(ep, link);
|
||||
isc_mem_free(mctx, ep->path);
|
||||
isc_mem_put(mctx, ep, sizeof(*ep));
|
||||
ep = epnext;
|
||||
http->count--;
|
||||
}
|
||||
}
|
||||
|
||||
isc_mem_put(mctx, http, sizeof(*http));
|
||||
http = next;
|
||||
}
|
||||
}
|
||||
|
||||
INSIST(storage->count == 0);
|
||||
}
|
||||
|
||||
isc_cfg_http_obj_t *
|
||||
cfg_http_find(const char *name, isc_cfg_http_storage_t *storage) {
|
||||
isc_cfg_http_obj_t *http = NULL;
|
||||
REQUIRE(name != NULL && *name != '\0');
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
for (http = ISC_LIST_HEAD(storage->list); http != NULL;
|
||||
http = ISC_LIST_NEXT(http, link))
|
||||
{
|
||||
if (strcasecmp(name, http->name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (http);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
push_http_obj(const cfg_obj_t *map, isc_cfg_http_storage_t *storage) {
|
||||
isc_mem_t *mctx = storage->mctx;
|
||||
isc_cfg_http_obj_t *new;
|
||||
const cfg_obj_t *endpoints = NULL;
|
||||
const cfg_listelt_t *elt;
|
||||
|
||||
if (!cfg_obj_ismap(map) || map->value.map.id == NULL ||
|
||||
!cfg_obj_isstring(map->value.map.id))
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_http_find(cfg_obj_asstring(map->value.map.id), storage) != NULL)
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_map_get(map, "endpoints", &endpoints) != ISC_R_SUCCESS ||
|
||||
!cfg_obj_islist(endpoints))
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
INSIST(endpoints != NULL);
|
||||
|
||||
new = isc_mem_get(mctx, sizeof(*new));
|
||||
memset(new, 0, sizeof(*new));
|
||||
ISC_LIST_INIT(new->endpoints);
|
||||
new->name = isc_mem_strdup(mctx, cfg_obj_asstring(map->value.map.id));
|
||||
|
||||
for (elt = cfg_list_first(endpoints); elt != NULL;
|
||||
elt = cfg_list_next(elt)) {
|
||||
isc_cfg_http_endpoint_t *newep = NULL;
|
||||
const cfg_obj_t *endp = cfg_listelt_value(elt);
|
||||
newep = isc_mem_get(mctx, sizeof(*newep));
|
||||
ISC_LINK_INIT(newep, link);
|
||||
newep->path = isc_mem_strdup(mctx, cfg_obj_asstring(endp));
|
||||
|
||||
ISC_LIST_PREPEND(new->endpoints, newep, link);
|
||||
new->count++;
|
||||
}
|
||||
|
||||
ISC_LINK_INIT(new, link);
|
||||
ISC_LIST_PREPEND(storage->list, new, link);
|
||||
storage->count++;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
cfg_http_storage_load(const cfg_obj_t *cfg_ctx,
|
||||
isc_cfg_http_storage_t *storage) {
|
||||
bool found = false;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
const cfg_obj_t *http = NULL;
|
||||
const cfg_listelt_t *elt;
|
||||
const cfg_obj_t *map = NULL;
|
||||
|
||||
REQUIRE(cfg_ctx != NULL);
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
cfg_http_storage_clear(storage);
|
||||
result = cfg_map_get(cfg_ctx, "http", &http);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* No statements found, but it is fine. */
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
INSIST(http != NULL);
|
||||
|
||||
for (elt = cfg_list_first(http); elt != NULL; elt = cfg_list_next(elt))
|
||||
{
|
||||
map = cfg_listelt_value(elt);
|
||||
INSIST(map != NULL);
|
||||
found = true;
|
||||
result = push_http_obj(map, storage);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
if (found == true && storage->count == 0) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
69
lib/isccfg/include/isccfg/httpconf.h
Normal file
69
lib/isccfg/include/isccfg/httpconf.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#ifndef ISCCFG_HTTPCONF_H
|
||||
#define ISCCFG_HTTPCONF_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
|
||||
#include <isccfg/cfg.h>
|
||||
#include <isccfg/tlsconf.h>
|
||||
|
||||
typedef struct isc_cfg_http_endpoint {
|
||||
char *path;
|
||||
LINK(struct isc_cfg_http_endpoint) link;
|
||||
} isc_cfg_http_endpoint_t;
|
||||
|
||||
typedef struct isc_cfg_http_obj {
|
||||
char *name;
|
||||
LINK(struct isc_cfg_http_obj) link;
|
||||
ISC_LIST(isc_cfg_http_endpoint_t) endpoints;
|
||||
size_t count;
|
||||
} isc_cfg_http_obj_t;
|
||||
|
||||
typedef struct isc_cfg_http_storage {
|
||||
isc_mem_t *mctx;
|
||||
ISC_LIST(isc_cfg_http_obj_t) list;
|
||||
size_t count;
|
||||
} isc_cfg_http_storage_t;
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
void
|
||||
cfg_http_storage_init(isc_mem_t *mctx, isc_cfg_http_storage_t *storage);
|
||||
|
||||
void
|
||||
cfg_http_storage_uninit(isc_cfg_http_storage_t *storage);
|
||||
|
||||
isc_result_t
|
||||
cfg_http_storage_load(const cfg_obj_t * cfg_ctx,
|
||||
isc_cfg_http_storage_t *storage);
|
||||
|
||||
isc_cfg_http_obj_t *
|
||||
cfg_http_find(const char *name, isc_cfg_http_storage_t *storage);
|
||||
|
||||
void
|
||||
cfg_http_storage_clear(isc_cfg_http_storage_t *storage);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISCCFG_HTTPCONF_H */
|
69
lib/isccfg/include/isccfg/tlsconf.h
Normal file
69
lib/isccfg/include/isccfg/tlsconf.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#ifndef ISCCFG_TLSCONF_H
|
||||
#define ISCCFG_TLSCONF_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/list.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
|
||||
#include <isccfg/cfg.h>
|
||||
|
||||
typedef struct isc_cfg_tls_obj {
|
||||
char *name;
|
||||
char *key_file;
|
||||
char *cert_file;
|
||||
char *dh_param;
|
||||
char *protocols;
|
||||
char *ciphers;
|
||||
LINK(struct isc_cfg_tls_obj) link;
|
||||
} isc_cfg_tls_obj_t;
|
||||
|
||||
typedef struct isc_cfg_tls_data_storage {
|
||||
isc_mem_t *mctx;
|
||||
size_t count;
|
||||
ISC_LIST(isc_cfg_tls_obj_t) list;
|
||||
} isc_cfg_tls_data_storage_t;
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
void
|
||||
cfg_tls_storage_init(isc_mem_t *mctx, isc_cfg_tls_data_storage_t *storage);
|
||||
|
||||
void
|
||||
cfg_tls_storage_uninit(isc_cfg_tls_data_storage_t *storage);
|
||||
|
||||
isc_result_t
|
||||
cfg_tls_storage_load(const cfg_obj_t * cfg_ctx,
|
||||
isc_cfg_tls_data_storage_t *storage);
|
||||
|
||||
isc_cfg_tls_obj_t *
|
||||
cfg_tls_storage_find(const char *name, isc_cfg_tls_data_storage_t *storage);
|
||||
/*
|
||||
* Looks for TLS key/certificate pair.
|
||||
*/
|
||||
|
||||
void
|
||||
cfg_tls_storage_clear(isc_cfg_tls_data_storage_t *storage);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISCCFG_TLSCONF_H */
|
@ -81,6 +81,7 @@ static cfg_type_t cfg_type_bracketed_dscpsockaddrlist;
|
||||
static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
|
||||
static cfg_type_t cfg_type_bracketed_netaddrlist;
|
||||
static cfg_type_t cfg_type_bracketed_sockaddrnameportlist;
|
||||
static cfg_type_t cfg_type_bracketed_qstring_list;
|
||||
static cfg_type_t cfg_type_controls;
|
||||
static cfg_type_t cfg_type_controls_sockaddr;
|
||||
static cfg_type_t cfg_type_destinationlist;
|
||||
@ -91,6 +92,7 @@ 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_description;
|
||||
static cfg_type_t cfg_type_ixfrdifftype;
|
||||
static cfg_type_t cfg_type_ixfrratio;
|
||||
static cfg_type_t cfg_type_key;
|
||||
@ -108,6 +110,7 @@ static cfg_type_t cfg_type_optional_allow;
|
||||
static cfg_type_t cfg_type_optional_class;
|
||||
static cfg_type_t cfg_type_optional_dscp;
|
||||
static cfg_type_t cfg_type_optional_facility;
|
||||
static cfg_type_t cfg_type_optional_http;
|
||||
static cfg_type_t cfg_type_optional_keyref;
|
||||
static cfg_type_t cfg_type_optional_port;
|
||||
static cfg_type_t cfg_type_optional_uint32;
|
||||
@ -151,6 +154,7 @@ static cfg_tuplefielddef_t listenon_fields[] = {
|
||||
{ "port", &cfg_type_optional_port, 0 },
|
||||
{ "dscp", &cfg_type_optional_dscp, 0 },
|
||||
{ "tls", &cfg_type_optional_tls, 0 },
|
||||
{ "http", &cfg_type_optional_http, 0 },
|
||||
{ "acl", &cfg_type_bracketed_aml, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
@ -1088,6 +1092,7 @@ static cfg_clausedef_t namedconf_clauses[] = {
|
||||
{ "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "dnssec-policy", &cfg_type_dnssecpolicy, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "http", &cfg_type_http_description, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "logging", &cfg_type_logging, 0 },
|
||||
{ "lwres", NULL, CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_ANCIENT },
|
||||
{ "masters", &cfg_type_primaries, CFG_CLAUSEFLAG_MULTI },
|
||||
@ -1221,6 +1226,8 @@ static cfg_clausedef_t options_clauses[] = {
|
||||
{ "pid-file", &cfg_type_qstringornone, 0 },
|
||||
{ "port", &cfg_type_uint32, 0 },
|
||||
{ "tls-port", &cfg_type_uint32, 0 },
|
||||
{ "http-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 },
|
||||
@ -3853,3 +3860,31 @@ static cfg_type_t cfg_type_optional_tls = {
|
||||
"tlsoptional", parse_optional_keyvalue, print_keyvalue,
|
||||
doc_optional_keyvalue, &cfg_rep_string, &tls_kw
|
||||
};
|
||||
|
||||
/* http and https */
|
||||
|
||||
static cfg_type_t cfg_type_bracketed_qstring_list = { "bracketed_qstring_list",
|
||||
cfg_parse_bracketed_list,
|
||||
cfg_print_bracketed_list,
|
||||
cfg_doc_bracketed_list,
|
||||
&cfg_rep_list,
|
||||
&cfg_type_qstring };
|
||||
|
||||
static cfg_clausedef_t cfg_http_description_clauses[] = {
|
||||
{ "endpoints", &cfg_type_bracketed_qstring_list, 0 }, { NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
static cfg_clausedef_t *http_description_clausesets[] = {
|
||||
cfg_http_description_clauses, NULL
|
||||
};
|
||||
|
||||
static cfg_type_t cfg_type_http_description = {
|
||||
"http_desc", cfg_parse_named_map, cfg_print_map,
|
||||
cfg_doc_map, &cfg_rep_map, http_description_clausesets
|
||||
};
|
||||
|
||||
static keyword_type_t http_kw = { "http", &cfg_type_astring };
|
||||
static cfg_type_t cfg_type_optional_http = {
|
||||
"http_optional", parse_optional_keyvalue, print_keyvalue,
|
||||
doc_optional_keyvalue, &cfg_rep_string, &http_kw
|
||||
};
|
||||
|
194
lib/isccfg/tlsconf.c
Normal file
194
lib/isccfg/tlsconf.c
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* 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 https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <isccfg/grammar.h>
|
||||
#include <isccfg/tlsconf.h>
|
||||
|
||||
void
|
||||
cfg_tls_storage_init(isc_mem_t *mctx, isc_cfg_tls_data_storage_t *storage) {
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
memset(storage, 0, sizeof(*storage));
|
||||
isc_mem_attach(mctx, &storage->mctx);
|
||||
ISC_LIST_INIT(storage->list);
|
||||
}
|
||||
|
||||
void
|
||||
cfg_tls_storage_uninit(isc_cfg_tls_data_storage_t *storage) {
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
cfg_tls_storage_clear(storage);
|
||||
isc_mem_detach(&storage->mctx);
|
||||
}
|
||||
|
||||
void
|
||||
cfg_tls_storage_clear(isc_cfg_tls_data_storage_t *storage) {
|
||||
isc_mem_t *mctx = NULL;
|
||||
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
mctx = storage->mctx;
|
||||
|
||||
if (!ISC_LIST_EMPTY(storage->list)) {
|
||||
isc_cfg_tls_obj_t *tls_obj = ISC_LIST_HEAD(storage->list);
|
||||
while (tls_obj != NULL) {
|
||||
isc_cfg_tls_obj_t *next = ISC_LIST_NEXT(tls_obj, link);
|
||||
ISC_LIST_DEQUEUE(storage->list, tls_obj, link);
|
||||
storage->count--;
|
||||
|
||||
isc_mem_free(mctx, tls_obj->name);
|
||||
isc_mem_free(mctx, tls_obj->key_file);
|
||||
isc_mem_free(mctx, tls_obj->cert_file);
|
||||
|
||||
if (tls_obj->dh_param != NULL) {
|
||||
isc_mem_free(mctx, tls_obj->dh_param);
|
||||
}
|
||||
|
||||
if (tls_obj->protocols != NULL) {
|
||||
isc_mem_free(mctx, tls_obj->protocols);
|
||||
}
|
||||
|
||||
if (tls_obj->ciphers != NULL) {
|
||||
isc_mem_free(mctx, tls_obj->ciphers);
|
||||
}
|
||||
|
||||
isc_mem_put(mctx, tls_obj, sizeof(*tls_obj));
|
||||
tls_obj = next;
|
||||
}
|
||||
}
|
||||
|
||||
INSIST(storage->count == 0);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
push_tls_obj(const cfg_obj_t *map, isc_cfg_tls_data_storage_t *storage) {
|
||||
isc_mem_t *mctx = storage->mctx;
|
||||
isc_cfg_tls_obj_t *new = NULL;
|
||||
const cfg_obj_t *key_file = NULL, *cert_file = NULL, *dh_param = NULL,
|
||||
*protocols = NULL, *ciphers = NULL;
|
||||
|
||||
if (!cfg_obj_ismap(map) || map->value.map.id == NULL ||
|
||||
!cfg_obj_isstring(map->value.map.id))
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_tls_storage_find(cfg_obj_asstring(map->value.map.id),
|
||||
storage) != NULL) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (cfg_map_get(map, "key-file", &key_file) != ISC_R_SUCCESS ||
|
||||
!cfg_obj_isstring(key_file))
|
||||
{
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
INSIST(key_file != NULL);
|
||||
|
||||
if (cfg_map_get(map, "cert-file", &cert_file) != ISC_R_SUCCESS) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
INSIST(cert_file != NULL);
|
||||
|
||||
(void)cfg_map_get(map, "dh-param", &dh_param);
|
||||
(void)cfg_map_get(map, "protocols", &protocols);
|
||||
(void)cfg_map_get(map, "ciphers", &ciphers);
|
||||
|
||||
new = isc_mem_get(mctx, sizeof(*new));
|
||||
*new = (isc_cfg_tls_obj_t){
|
||||
.name = isc_mem_strdup(mctx,
|
||||
cfg_obj_asstring(map->value.map.id)),
|
||||
.key_file = isc_mem_strdup(mctx, cfg_obj_asstring(key_file)),
|
||||
.cert_file = isc_mem_strdup(mctx, cfg_obj_asstring(cert_file)),
|
||||
};
|
||||
|
||||
if (dh_param != NULL && cfg_obj_isstring(dh_param)) {
|
||||
new->dh_param = isc_mem_strdup(mctx,
|
||||
cfg_obj_asstring(dh_param));
|
||||
}
|
||||
|
||||
if (protocols != NULL && cfg_obj_isstring(protocols)) {
|
||||
new->protocols = isc_mem_strdup(mctx,
|
||||
cfg_obj_asstring(protocols));
|
||||
}
|
||||
|
||||
if (ciphers != NULL && cfg_obj_isstring(ciphers)) {
|
||||
new->ciphers = isc_mem_strdup(mctx, cfg_obj_asstring(ciphers));
|
||||
}
|
||||
|
||||
ISC_LINK_INIT(new, link);
|
||||
ISC_LIST_PREPEND(storage->list, new, link);
|
||||
storage->count++;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
cfg_tls_storage_load(const cfg_obj_t *cfg_ctx,
|
||||
isc_cfg_tls_data_storage_t *storage) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
bool found = false;
|
||||
const cfg_obj_t *tls = NULL;
|
||||
const cfg_listelt_t *elt;
|
||||
const cfg_obj_t *map = NULL;
|
||||
|
||||
REQUIRE(cfg_ctx != NULL);
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
result = cfg_map_get(cfg_ctx, "tls", &tls);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* No tls statements found, but it is fine. */
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
INSIST(tls != NULL);
|
||||
|
||||
cfg_tls_storage_clear(storage);
|
||||
|
||||
for (elt = cfg_list_first(tls); elt != NULL; elt = cfg_list_next(elt)) {
|
||||
map = cfg_listelt_value(elt);
|
||||
INSIST(map != NULL);
|
||||
found = true;
|
||||
result = push_tls_obj(map, storage);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
if (found == true && storage->count == 0) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_cfg_tls_obj_t *
|
||||
cfg_tls_storage_find(const char *name, isc_cfg_tls_data_storage_t *storage) {
|
||||
isc_cfg_tls_obj_t *tls_obj = NULL;
|
||||
REQUIRE(storage != NULL);
|
||||
|
||||
if (name == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
for (tls_obj = ISC_LIST_HEAD(storage->list); tls_obj != NULL;
|
||||
tls_obj = ISC_LIST_NEXT(tls_obj, link))
|
||||
{
|
||||
if (strcasecmp(name, tls_obj->name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (tls_obj);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user