mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-13 01:20:01 -04:00
XoT: add support for client-side TLS parameters
This commit adds support for client-side TLS parameters to XoT. Prior to this commit all client-side TLS contexts were using default parameters only, ignoring the options from the BIND's configuration file. Currently, the following 'tls' parameters are supported: - protocols; - ciphers; - prefer-server-ciphers.
This commit is contained in:
parent
17d9a74681
commit
7843fb4ece
4 changed files with 196 additions and 2 deletions
|
|
@ -47,6 +47,47 @@
|
|||
} \
|
||||
}
|
||||
|
||||
#define parse_transport_tls_versions(map, transport, name, setter) \
|
||||
{ \
|
||||
const cfg_obj_t *obj = NULL; \
|
||||
cfg_map_get(map, name, &obj); \
|
||||
if (obj != NULL) { \
|
||||
{ \
|
||||
uint32_t tls_protos = 0; \
|
||||
const cfg_listelt_t *proto = NULL; \
|
||||
INSIST(obj != NULL); \
|
||||
for (proto = cfg_list_first(obj); proto != 0; \
|
||||
proto = cfg_list_next(proto)) { \
|
||||
const cfg_obj_t *tls_proto_obj = \
|
||||
cfg_listelt_value(proto); \
|
||||
const char *tls_sver = \
|
||||
cfg_obj_asstring( \
|
||||
tls_proto_obj); \
|
||||
const isc_tls_protocol_version_t ver = \
|
||||
isc_tls_protocol_name_to_version( \
|
||||
tls_sver); \
|
||||
INSIST(ver != \
|
||||
ISC_TLS_PROTO_VER_UNDEFINED); \
|
||||
INSIST(isc_tls_protocol_supported( \
|
||||
ver)); \
|
||||
tls_protos |= ver; \
|
||||
} \
|
||||
if (tls_protos != 0) { \
|
||||
setter(transport, tls_protos); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define parse_transport_bool_option(map, transport, name, setter) \
|
||||
{ \
|
||||
const cfg_obj_t *obj = NULL; \
|
||||
cfg_map_get(map, name, &obj); \
|
||||
if (obj != NULL) { \
|
||||
setter(transport, cfg_obj_asboolean(obj)); \
|
||||
} \
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
add_doh_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) {
|
||||
const cfg_obj_t *doh = NULL;
|
||||
|
|
@ -71,6 +112,13 @@ add_doh_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) {
|
|||
dns_transport_set_keyfile);
|
||||
parse_transport_option(doh, transport, "cert-file",
|
||||
dns_transport_set_certfile);
|
||||
parse_transport_tls_versions(doh, transport, "protocols",
|
||||
dns_transport_set_tls_versions);
|
||||
parse_transport_option(doh, transport, "ciphers",
|
||||
dns_transport_set_ciphers);
|
||||
parse_transport_bool_option(
|
||||
doh, transport, "prefer-server-ciphers",
|
||||
dns_transport_set_prefer_server_ciphers)
|
||||
#if 0
|
||||
/*
|
||||
* The following two options need to remain unavailable until
|
||||
|
|
@ -121,6 +169,13 @@ add_tls_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) {
|
|||
dns_transport_set_keyfile);
|
||||
parse_transport_option(tls, transport, "cert-file",
|
||||
dns_transport_set_certfile);
|
||||
parse_transport_tls_versions(tls, transport, "protocols",
|
||||
dns_transport_set_tls_versions);
|
||||
parse_transport_option(tls, transport, "ciphers",
|
||||
dns_transport_set_ciphers);
|
||||
parse_transport_bool_option(
|
||||
tls, transport, "prefer-server-ciphers",
|
||||
dns_transport_set_prefer_server_ciphers)
|
||||
#if 0
|
||||
/*
|
||||
* The following two options need to remain unavailable until
|
||||
|
|
|
|||
|
|
@ -52,9 +52,20 @@ char *
|
|||
dns_transport_get_endpoint(dns_transport_t *transport);
|
||||
dns_http_mode_t
|
||||
dns_transport_get_mode(dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_ciphers(dns_transport_t *transport);
|
||||
uint32_t
|
||||
dns_transport_get_tls_versions(const dns_transport_t *transport);
|
||||
bool
|
||||
dns_transport_get_prefer_server_ciphers(const dns_transport_t *transport,
|
||||
bool *preferp);
|
||||
/*%<
|
||||
* Getter functions: return the type, cert file, key file, CA file,
|
||||
* hostname, HTTP endpoint, or HTTP mode (GET or POST) for 'transport'.
|
||||
*
|
||||
* dns_transport_get_prefer_server_ciphers() returns 'true' is value
|
||||
* was set, 'false' otherwise. The actual value is returned via
|
||||
* 'preferp' pointer.
|
||||
*/
|
||||
|
||||
void
|
||||
|
|
@ -69,6 +80,14 @@ void
|
|||
dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint);
|
||||
void
|
||||
dns_transport_set_mode(dns_transport_t *transport, dns_http_mode_t mode);
|
||||
void
|
||||
dns_transport_set_ciphers(dns_transport_t *transport, const char *ciphers);
|
||||
void
|
||||
dns_transport_set_tls_versions(dns_transport_t *transport,
|
||||
const uint32_t tls_versions);
|
||||
void
|
||||
dns_transport_set_prefer_server_ciphers(dns_transport_t *transport,
|
||||
const bool prefer);
|
||||
/*%<
|
||||
* Setter functions: set the type, cert file, key file, CA file,
|
||||
* hostname, HTTP endpoint, or HTTP mode (GET or POST) for 'transport'.
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ struct dns_transport_list {
|
|||
dns_rbt_t *transports[DNS_TRANSPORT_COUNT];
|
||||
};
|
||||
|
||||
typedef enum ternary { ter_none = 0, ter_true = 1, ter_false = 2 } ternary_t;
|
||||
|
||||
struct dns_transport {
|
||||
unsigned int magic;
|
||||
isc_refcount_t references;
|
||||
|
|
@ -46,6 +48,9 @@ struct dns_transport {
|
|||
char *keyfile;
|
||||
char *cafile;
|
||||
char *hostname;
|
||||
char *ciphers;
|
||||
uint32_t protocol_versions;
|
||||
ternary_t prefer_server_ciphers;
|
||||
} tls;
|
||||
struct {
|
||||
char *endpoint;
|
||||
|
|
@ -151,6 +156,10 @@ dns_transport_set_certfile(dns_transport_t *transport, const char *certfile) {
|
|||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (transport->tls.certfile != NULL) {
|
||||
isc_mem_free(transport->mctx, transport->tls.certfile);
|
||||
}
|
||||
|
||||
if (certfile != NULL) {
|
||||
transport->tls.certfile = isc_mem_strdup(transport->mctx,
|
||||
certfile);
|
||||
|
|
@ -163,6 +172,10 @@ dns_transport_set_keyfile(dns_transport_t *transport, const char *keyfile) {
|
|||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (transport->tls.keyfile != NULL) {
|
||||
isc_mem_free(transport->mctx, transport->tls.keyfile);
|
||||
}
|
||||
|
||||
if (keyfile != NULL) {
|
||||
transport->tls.keyfile = isc_mem_strdup(transport->mctx,
|
||||
keyfile);
|
||||
|
|
@ -175,6 +188,10 @@ dns_transport_set_cafile(dns_transport_t *transport, const char *cafile) {
|
|||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (transport->tls.cafile != NULL) {
|
||||
isc_mem_free(transport->mctx, transport->tls.cafile);
|
||||
}
|
||||
|
||||
if (cafile != NULL) {
|
||||
transport->tls.cafile = isc_mem_strdup(transport->mctx, cafile);
|
||||
}
|
||||
|
|
@ -186,6 +203,10 @@ dns_transport_set_hostname(dns_transport_t *transport, const char *hostname) {
|
|||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (transport->tls.hostname != NULL) {
|
||||
isc_mem_free(transport->mctx, transport->tls.hostname);
|
||||
}
|
||||
|
||||
if (hostname != NULL) {
|
||||
transport->tls.hostname = isc_mem_strdup(transport->mctx,
|
||||
hostname);
|
||||
|
|
@ -197,6 +218,10 @@ dns_transport_set_endpoint(dns_transport_t *transport, const char *endpoint) {
|
|||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (transport->doh.endpoint != NULL) {
|
||||
isc_mem_free(transport->mctx, transport->doh.endpoint);
|
||||
}
|
||||
|
||||
if (endpoint != NULL) {
|
||||
transport->doh.endpoint = isc_mem_strdup(transport->mctx,
|
||||
endpoint);
|
||||
|
|
@ -211,6 +236,76 @@ dns_transport_set_mode(dns_transport_t *transport, dns_http_mode_t mode) {
|
|||
transport->doh.mode = mode;
|
||||
}
|
||||
|
||||
void
|
||||
dns_transport_set_tls_versions(dns_transport_t *transport,
|
||||
const uint32_t tls_versions) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_HTTP ||
|
||||
transport->type == DNS_TRANSPORT_TLS);
|
||||
|
||||
transport->tls.protocol_versions = tls_versions;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
dns_transport_get_tls_versions(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->tls.protocol_versions);
|
||||
}
|
||||
|
||||
void
|
||||
dns_transport_set_ciphers(dns_transport_t *transport, const char *ciphers) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
if (transport->tls.ciphers != NULL) {
|
||||
isc_mem_free(transport->mctx, transport->tls.ciphers);
|
||||
}
|
||||
|
||||
if (ciphers != NULL) {
|
||||
transport->tls.ciphers = isc_mem_strdup(transport->mctx,
|
||||
ciphers);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
dns_transport_get_ciphers(dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->tls.ciphers);
|
||||
}
|
||||
|
||||
void
|
||||
dns_transport_set_prefer_server_ciphers(dns_transport_t *transport,
|
||||
const bool prefer) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
transport->tls.prefer_server_ciphers = prefer ? ter_true : ter_false;
|
||||
}
|
||||
|
||||
bool
|
||||
dns_transport_get_prefer_server_ciphers(const dns_transport_t *transport,
|
||||
bool *preferp) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(preferp != NULL);
|
||||
if (transport->tls.prefer_server_ciphers == ter_none) {
|
||||
return (false);
|
||||
} else if (transport->tls.prefer_server_ciphers == ter_true) {
|
||||
*preferp = true;
|
||||
return (true);
|
||||
} else if (transport->tls.prefer_server_ciphers == ter_false) {
|
||||
*preferp = false;
|
||||
return (true);
|
||||
}
|
||||
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
transport_destroy(dns_transport_t *transport) {
|
||||
isc_refcount_destroy(&transport->references);
|
||||
|
|
@ -231,6 +326,9 @@ transport_destroy(dns_transport_t *transport) {
|
|||
if (transport->tls.certfile != NULL) {
|
||||
isc_mem_free(transport->mctx, transport->tls.certfile);
|
||||
}
|
||||
if (transport->tls.ciphers != NULL) {
|
||||
isc_mem_free(transport->mctx, transport->tls.ciphers);
|
||||
}
|
||||
|
||||
isc_mem_putanddetach(&transport->mctx, transport, sizeof(*transport));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -946,13 +946,35 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
|
|||
&xfr->primaryaddr, xfrin_connect_done,
|
||||
connect_xfr, 30000, 0);
|
||||
break;
|
||||
case DNS_TRANSPORT_TLS:
|
||||
case DNS_TRANSPORT_TLS: {
|
||||
uint32_t tls_versions;
|
||||
const char *ciphers;
|
||||
bool prefer_server_ciphers;
|
||||
CHECK(isc_tlsctx_createclient(&xfr->tlsctx));
|
||||
if (xfr->transport != NULL) {
|
||||
tls_versions =
|
||||
dns_transport_get_tls_versions(xfr->transport);
|
||||
if (tls_versions != 0) {
|
||||
isc_tlsctx_set_protocols(xfr->tlsctx,
|
||||
tls_versions);
|
||||
}
|
||||
ciphers = dns_transport_get_ciphers(xfr->transport);
|
||||
if (ciphers != NULL) {
|
||||
isc_tlsctx_set_cipherlist(xfr->tlsctx, ciphers);
|
||||
}
|
||||
|
||||
if (dns_transport_get_prefer_server_ciphers(
|
||||
xfr->transport, &prefer_server_ciphers))
|
||||
{
|
||||
isc_tlsctx_prefer_server_ciphers(
|
||||
xfr->tlsctx, prefer_server_ciphers);
|
||||
}
|
||||
}
|
||||
isc_tlsctx_enable_dot_client_alpn(xfr->tlsctx);
|
||||
isc_nm_tlsdnsconnect(xfr->netmgr, &xfr->sourceaddr,
|
||||
&xfr->primaryaddr, xfrin_connect_done,
|
||||
connect_xfr, 30000, 0, xfr->tlsctx);
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
|
|
|
|||
Loading…
Reference in a new issue