# 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\
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);
static void
parse_port(char *arg) {
- enum { DNSPORT, TLSPORT } ptype = DNSPORT;
+ enum { DNSPORT, TLSPORT, HTTPSPORT, HTTPPORT } ptype = DNSPORT;
char *value = arg;
int port;
} 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");
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();
dyndb string quoted_string {
unspecified-text };
+HTTP
+^^^^
+
+::
+
+ http string {
+ endpoints { quoted_string; ... };
+ };
+
KEY
^^^
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;
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 );
``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.
--- /dev/null
+/*
+ * 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; };
+};
--- /dev/null
+/*
+ * 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; };
+};
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" \
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)"
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."
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
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
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
\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.
.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
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;
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 );
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) \
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
--- /dev/null
+::
+
+ http <string> {
+ endpoints { <quoted_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>;
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>;
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 );
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>;
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>;
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 );
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>;
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 );
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
~~~~~~~~~~~~~~~~
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 = \
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
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;
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;
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;
{ "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 }
};
{ "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 },
{ "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 },
"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
+};
--- /dev/null
+/*
+ * 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);
+}