Add support for Strict/Mutual TLS to dig
This commit adds support for Strict/Mutual TLS to dig. The new command-line options and their behaviour are modelled after kdig (+tls-ca, +tls-hostname, +tls-certfile, +tls-keyfile) for compatibility reasons. That is, using +tls-* is sufficient to enable DoT in dig, implying +tls-ca If there is no other DNS transport specified via command-line, specifying any of +tls-* options makes dig use DoT. In this case, its behaviour is the same as if +tls-ca is specified: that is, the remote peer's certificate is verified using the platform-specific intermediate CA certificates store. This behaviour is introduced for compatibility with kdig.
This commit is contained in:
170
bin/dig/dig.c
170
bin/dig/dig.c
@@ -289,6 +289,14 @@ help(void) {
|
||||
" +[no]tcp (TCP mode (+[no]vc))\n"
|
||||
" +timeout=### (Set query timeout) [5]\n"
|
||||
" +[no]tls (DNS-over-TLS mode)\n"
|
||||
" +[no]tls-ca[=file] (Enable remote server's "
|
||||
"TLS certificate validation)\n"
|
||||
" +[no]tls-hostname=hostname (Explicitly set "
|
||||
"the expected TLS hostname)\n"
|
||||
" +[no]tls-certfile=file (Load client TLS "
|
||||
"certificate chain from file)\n"
|
||||
" +[no]tls-keyfile=file (Load client TLS "
|
||||
"private key from file)\n"
|
||||
" +[no]trace (Trace delegation down "
|
||||
"from root "
|
||||
"[+dnssec])\n"
|
||||
@@ -340,7 +348,7 @@ received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
|
||||
} else {
|
||||
printf(";; Query time: %ld msec\n", (long)diff / 1000);
|
||||
}
|
||||
if (query->lookup->tls_mode) {
|
||||
if (dig_lookup_is_tls(query->lookup)) {
|
||||
proto = "TLS";
|
||||
} else if (query->lookup->https_mode) {
|
||||
if (query->lookup->http_plain) {
|
||||
@@ -1015,6 +1023,128 @@ printgreeting(int argc, char **argv, dig_lookup_t *lookup) {
|
||||
}
|
||||
}
|
||||
|
||||
#define FULLCHECK(A) \
|
||||
do { \
|
||||
size_t _l = strlen(cmd); \
|
||||
if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \
|
||||
goto invalid_option; \
|
||||
} while (0)
|
||||
#define FULLCHECK2(A, B) \
|
||||
do { \
|
||||
size_t _l = strlen(cmd); \
|
||||
if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
|
||||
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
|
||||
goto invalid_option; \
|
||||
} while (0)
|
||||
#define FULLCHECK6(A, B, C, D, E, F) \
|
||||
do { \
|
||||
size_t _l = strlen(cmd); \
|
||||
if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
|
||||
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0) && \
|
||||
(_l >= sizeof(C) || strncasecmp(cmd, C, _l) != 0) && \
|
||||
(_l >= sizeof(D) || strncasecmp(cmd, D, _l) != 0) && \
|
||||
(_l >= sizeof(E) || strncasecmp(cmd, E, _l) != 0) && \
|
||||
(_l >= sizeof(F) || strncasecmp(cmd, F, _l) != 0)) \
|
||||
goto invalid_option; \
|
||||
} while (0)
|
||||
|
||||
static bool
|
||||
plus_tls_options(const char *cmd, const char *value, const bool state,
|
||||
dig_lookup_t *lookup) {
|
||||
/*
|
||||
* Using TLS implies "TCP-like" mode.
|
||||
*/
|
||||
if (!lookup->tcp_mode_set) {
|
||||
lookup->tcp_mode = state;
|
||||
}
|
||||
switch (cmd[3]) {
|
||||
case '-':
|
||||
/*
|
||||
* Assume that if any of the +tls-* options are set, then we
|
||||
* need to verify the remote certificate (compatibility with
|
||||
* kdig).
|
||||
*/
|
||||
if (state) {
|
||||
lookup->tls_ca_set = state;
|
||||
}
|
||||
switch (cmd[4]) {
|
||||
case 'c':
|
||||
switch (cmd[5]) {
|
||||
case 'a':
|
||||
FULLCHECK("tls-ca");
|
||||
lookup->tls_ca_set = state;
|
||||
if (state && value != NULL) {
|
||||
lookup->tls_ca_file =
|
||||
isc_mem_strdup(mctx, value);
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
FULLCHECK("tls-certfile");
|
||||
lookup->tls_cert_file_set = state;
|
||||
if (state) {
|
||||
if (value != NULL && *value != '\0') {
|
||||
lookup->tls_cert_file =
|
||||
isc_mem_strdup(mctx,
|
||||
value);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
";; TLS certificate "
|
||||
"file is "
|
||||
"not specified\n");
|
||||
goto invalid_option;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
FULLCHECK("tls-hostname");
|
||||
lookup->tls_hostname_set = state;
|
||||
if (state) {
|
||||
if (value != NULL && *value != '\0') {
|
||||
lookup->tls_hostname =
|
||||
isc_mem_strdup(mctx, value);
|
||||
} else {
|
||||
fprintf(stderr, ";; TLS hostname is "
|
||||
"not specified\n");
|
||||
goto invalid_option;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'k':
|
||||
FULLCHECK("tls-keyfile");
|
||||
lookup->tls_key_file_set = state;
|
||||
if (state) {
|
||||
if (value != NULL && *value != '\0') {
|
||||
lookup->tls_key_file =
|
||||
isc_mem_strdup(mctx, value);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
";; TLS private key file is "
|
||||
"not specified\n");
|
||||
goto invalid_option;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case '\0':
|
||||
FULLCHECK("tls");
|
||||
lookup->tls_mode = state;
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
|
||||
return true;
|
||||
invalid_option:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*%
|
||||
* We're not using isc_commandline_parse() here since the command line
|
||||
* syntax of dig is quite a bit different from that which can be described
|
||||
@@ -1044,31 +1174,6 @@ plus_option(char *option, bool is_batchfile, bool *need_clone,
|
||||
/* parse the rest of the string */
|
||||
value = strtok_r(NULL, "", &last);
|
||||
|
||||
#define FULLCHECK(A) \
|
||||
do { \
|
||||
size_t _l = strlen(cmd); \
|
||||
if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \
|
||||
goto invalid_option; \
|
||||
} while (0)
|
||||
#define FULLCHECK2(A, B) \
|
||||
do { \
|
||||
size_t _l = strlen(cmd); \
|
||||
if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
|
||||
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
|
||||
goto invalid_option; \
|
||||
} while (0)
|
||||
#define FULLCHECK6(A, B, C, D, E, F) \
|
||||
do { \
|
||||
size_t _l = strlen(cmd); \
|
||||
if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
|
||||
(_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0) && \
|
||||
(_l >= sizeof(C) || strncasecmp(cmd, C, _l) != 0) && \
|
||||
(_l >= sizeof(D) || strncasecmp(cmd, D, _l) != 0) && \
|
||||
(_l >= sizeof(E) || strncasecmp(cmd, E, _l) != 0) && \
|
||||
(_l >= sizeof(F) || strncasecmp(cmd, F, _l) != 0)) \
|
||||
goto invalid_option; \
|
||||
} while (0)
|
||||
|
||||
switch (cmd[0]) {
|
||||
case 'a':
|
||||
switch (cmd[1]) {
|
||||
@@ -1937,10 +2042,15 @@ plus_option(char *option, bool is_batchfile, bool *need_clone,
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
FULLCHECK("tls");
|
||||
lookup->tls_mode = state;
|
||||
if (!lookup->tcp_mode_set) {
|
||||
lookup->tcp_mode = state;
|
||||
switch (cmd[2]) {
|
||||
case 's':
|
||||
if (!plus_tls_options(cmd, value, state,
|
||||
lookup)) {
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
|
||||
@@ -632,6 +632,24 @@ abbreviation is unambiguous; for example, ``+cd`` is equivalent to
|
||||
name servers. When this option is in use, the port number defaults
|
||||
to 853.
|
||||
|
||||
``+[no]tls-ca[=file-name]``
|
||||
This option enables remote server TLS certificate validation for
|
||||
DNS transports, relying on TLS. Certificate authorities
|
||||
certificates are loaded from the specified PEM file
|
||||
(``file-name``). If the file is not specified, the default
|
||||
certificates from the global certificates store are used.
|
||||
|
||||
``+[no]tls-certfile=file-name`` and ``+[no]tls-keyfile=file-name``
|
||||
These options set the state of certificate-based client
|
||||
authentication for DNS transports, relying on TLS. Both certificate
|
||||
chain file and private key file are expected to be in PEM format.
|
||||
Both options must be specified at the same time.
|
||||
|
||||
``+[no]tls-hostname=hostname``
|
||||
This option makes ``dig`` use the provided hostname during remote
|
||||
server TLS certificate verification. Otherwise, the DNS server name
|
||||
is used. This option has no effect if ``+tls-ca`` is not specified.
|
||||
|
||||
.. option:: +[no]topdown
|
||||
|
||||
This feature is related to ``dig +sigchase``, which is obsolete and
|
||||
|
||||
@@ -639,6 +639,8 @@ make_empty_lookup(void) {
|
||||
ISC_LIST_INIT(looknew->q);
|
||||
ISC_LIST_INIT(looknew->my_server_list);
|
||||
|
||||
looknew->tls_ctx_cache = isc_tlsctx_cache_new(mctx);
|
||||
|
||||
isc_refcount_init(&looknew->references, 1);
|
||||
|
||||
looknew->magic = DIG_LOOKUP_MAGIC;
|
||||
@@ -729,6 +731,30 @@ clone_lookup(dig_lookup_t *lookold, bool servers) {
|
||||
looknew->https_get = lookold->https_get;
|
||||
looknew->http_plain = lookold->http_plain;
|
||||
|
||||
looknew->tls_ca_set = lookold->tls_ca_set;
|
||||
if (lookold->tls_ca_file != NULL) {
|
||||
looknew->tls_ca_file = isc_mem_strdup(mctx,
|
||||
lookold->tls_ca_file);
|
||||
};
|
||||
|
||||
looknew->tls_hostname_set = lookold->tls_hostname_set;
|
||||
if (lookold->tls_hostname != NULL) {
|
||||
looknew->tls_hostname = isc_mem_strdup(mctx,
|
||||
lookold->tls_hostname);
|
||||
}
|
||||
|
||||
looknew->tls_key_file_set = lookold->tls_key_file_set;
|
||||
if (lookold->tls_key_file != NULL) {
|
||||
looknew->tls_key_file = isc_mem_strdup(mctx,
|
||||
lookold->tls_key_file);
|
||||
}
|
||||
|
||||
looknew->tls_cert_file_set = lookold->tls_cert_file_set;
|
||||
if (lookold->tls_cert_file != NULL) {
|
||||
looknew->tls_cert_file = isc_mem_strdup(mctx,
|
||||
lookold->tls_cert_file);
|
||||
}
|
||||
|
||||
looknew->showbadcookie = lookold->showbadcookie;
|
||||
looknew->sendcookie = lookold->sendcookie;
|
||||
looknew->seenbadcookie = lookold->seenbadcookie;
|
||||
@@ -794,6 +820,11 @@ clone_lookup(dig_lookup_t *lookold, bool servers) {
|
||||
dns_fixedname_name(&looknew->fdomain));
|
||||
|
||||
if (servers) {
|
||||
if (lookold->tls_ctx_cache != NULL) {
|
||||
isc_tlsctx_cache_detach(&looknew->tls_ctx_cache);
|
||||
isc_tlsctx_cache_attach(lookold->tls_ctx_cache,
|
||||
&looknew->tls_ctx_cache);
|
||||
}
|
||||
clone_server_list(lookold->my_server_list,
|
||||
&looknew->my_server_list);
|
||||
}
|
||||
@@ -1574,6 +1605,26 @@ _destroy_lookup(dig_lookup_t *lookup) {
|
||||
isc_mem_free(mctx, lookup->https_path);
|
||||
}
|
||||
|
||||
if (lookup->tls_ctx_cache != NULL) {
|
||||
isc_tlsctx_cache_detach(&lookup->tls_ctx_cache);
|
||||
}
|
||||
|
||||
if (lookup->tls_ca_file != NULL) {
|
||||
isc_mem_free(mctx, lookup->tls_ca_file);
|
||||
}
|
||||
|
||||
if (lookup->tls_hostname != NULL) {
|
||||
isc_mem_free(mctx, lookup->tls_hostname);
|
||||
}
|
||||
|
||||
if (lookup->tls_key_file != NULL) {
|
||||
isc_mem_free(mctx, lookup->tls_key_file);
|
||||
}
|
||||
|
||||
if (lookup->tls_cert_file != NULL) {
|
||||
isc_mem_free(mctx, lookup->tls_cert_file);
|
||||
}
|
||||
|
||||
isc_mem_free(mctx, lookup);
|
||||
}
|
||||
|
||||
@@ -2688,6 +2739,106 @@ _cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line) {
|
||||
check_if_done();
|
||||
}
|
||||
|
||||
static isc_tlsctx_t *
|
||||
get_create_tls_context(dig_query_t *query, const bool is_https) {
|
||||
isc_result_t result;
|
||||
isc_tlsctx_t *ctx = NULL, *found_ctx = NULL;
|
||||
isc_tls_cert_store_t *store = NULL, *found_store = NULL;
|
||||
char tlsctxname[ISC_SOCKADDR_FORMATSIZE];
|
||||
const uint16_t family = isc_sockaddr_pf(&query->sockaddr) == PF_INET6
|
||||
? AF_INET6
|
||||
: AF_INET;
|
||||
isc_tlsctx_cache_transport_t transport =
|
||||
is_https ? isc_tlsctx_cache_https : isc_tlsctx_cache_tls;
|
||||
const bool hostname_ignore_subject = !is_https;
|
||||
|
||||
if (query->lookup->tls_key_file_set != query->lookup->tls_cert_file_set)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
isc_sockaddr_format(&query->sockaddr, tlsctxname, sizeof(tlsctxname));
|
||||
|
||||
result = isc_tlsctx_cache_find(query->lookup->tls_ctx_cache, tlsctxname,
|
||||
transport, family, &found_ctx,
|
||||
&found_store);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (query->lookup->tls_ca_set) {
|
||||
if (found_store == NULL) {
|
||||
result = isc_tls_cert_store_create(
|
||||
query->lookup->tls_ca_file, &store);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
store = found_store;
|
||||
}
|
||||
}
|
||||
|
||||
result = isc_tlsctx_createclient(&ctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (store != NULL) {
|
||||
const char *hostname =
|
||||
query->lookup->tls_hostname_set
|
||||
? query->lookup->tls_hostname
|
||||
: query->userarg;
|
||||
/*
|
||||
* According to RFC 8310, Subject field MUST NOT be
|
||||
* inspected when verifying hostname for DoT. Only
|
||||
* SubjectAltName must be checked. That is NOT the case
|
||||
* for HTTPS.
|
||||
*/
|
||||
result = isc_tlsctx_enable_peer_verification(
|
||||
ctx, false, store, hostname,
|
||||
hostname_ignore_subject);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
if (query->lookup->tls_key_file_set &&
|
||||
query->lookup->tls_cert_file_set) {
|
||||
result = isc_tlsctx_load_certificate(
|
||||
ctx, query->lookup->tls_key_file,
|
||||
query->lookup->tls_cert_file);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_https) {
|
||||
isc_tlsctx_enable_dot_client_alpn(ctx);
|
||||
}
|
||||
|
||||
#if HAVE_LIBNGHTTP2
|
||||
if (is_https) {
|
||||
isc_tlsctx_enable_http2client_alpn(ctx);
|
||||
}
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
|
||||
result = isc_tlsctx_cache_add(query->lookup->tls_ctx_cache,
|
||||
tlsctxname, transport, family,
|
||||
ctx, store, NULL, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
return (ctx);
|
||||
}
|
||||
|
||||
INSIST(!query->lookup->tls_ca_set || found_store != NULL);
|
||||
return (found_ctx);
|
||||
failure:
|
||||
if (ctx != NULL && found_ctx != ctx) {
|
||||
isc_tlsctx_free(&ctx);
|
||||
}
|
||||
if (store != NULL && store != found_store) {
|
||||
isc_tls_cert_store_free(&store);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg);
|
||||
|
||||
@@ -2701,18 +2852,22 @@ start_tcp(dig_query_t *query) {
|
||||
isc_result_t result;
|
||||
dig_query_t *next = NULL;
|
||||
dig_query_t *connectquery = NULL;
|
||||
isc_tlsctx_t *tlsctx = NULL;
|
||||
bool tls_mode = false;
|
||||
REQUIRE(DIG_VALID_QUERY(query));
|
||||
|
||||
debug("start_tcp(%p)", query);
|
||||
|
||||
query_attach(query, &query->lookup->current_query);
|
||||
|
||||
tls_mode = dig_lookup_is_tls(query->lookup);
|
||||
|
||||
/*
|
||||
* For TLS connections, we want to override the default
|
||||
* port number.
|
||||
*/
|
||||
if (!port_set) {
|
||||
if (query->lookup->tls_mode) {
|
||||
if (tls_mode) {
|
||||
port = 853;
|
||||
} else if (query->lookup->https_mode &&
|
||||
!query->lookup->http_plain) {
|
||||
@@ -2792,14 +2947,15 @@ start_tcp(dig_query_t *query) {
|
||||
|
||||
query_attach(query, &connectquery);
|
||||
|
||||
if (query->lookup->tls_mode) {
|
||||
result = isc_tlsctx_createclient(&query->tlsctx);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
isc_tlsctx_enable_dot_client_alpn(query->tlsctx);
|
||||
if (tls_mode) {
|
||||
tlsctx = get_create_tls_context(connectquery, false);
|
||||
if (tlsctx == NULL) {
|
||||
goto failure_tls;
|
||||
}
|
||||
isc_nm_tlsdnsconnect(netmgr, &localaddr,
|
||||
&query->sockaddr, tcp_connected,
|
||||
connectquery, local_timeout,
|
||||
query->tlsctx);
|
||||
tlsctx);
|
||||
#if HAVE_LIBNGHTTP2
|
||||
} else if (query->lookup->https_mode) {
|
||||
char uri[4096] = { 0 };
|
||||
@@ -2809,17 +2965,17 @@ start_tcp(dig_query_t *query) {
|
||||
uri, sizeof(uri));
|
||||
|
||||
if (!query->lookup->http_plain) {
|
||||
result =
|
||||
isc_tlsctx_createclient(&query->tlsctx);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
isc_tlsctx_enable_http2client_alpn(
|
||||
query->tlsctx);
|
||||
tlsctx = get_create_tls_context(connectquery,
|
||||
true);
|
||||
if (tlsctx == NULL) {
|
||||
goto failure_tls;
|
||||
}
|
||||
}
|
||||
|
||||
isc_nm_httpconnect(netmgr, &localaddr, &query->sockaddr,
|
||||
uri, !query->lookup->https_get,
|
||||
tcp_connected, connectquery,
|
||||
query->tlsctx, local_timeout);
|
||||
tcp_connected, connectquery, tlsctx,
|
||||
local_timeout);
|
||||
#endif
|
||||
} else {
|
||||
isc_nm_tcpdnsconnect(netmgr, &localaddr,
|
||||
@@ -2846,6 +3002,29 @@ start_tcp(dig_query_t *query) {
|
||||
start_tcp(next);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
failure_tls:
|
||||
if (query->lookup->tls_key_file_set != query->lookup->tls_cert_file_set)
|
||||
{
|
||||
dighost_warning(
|
||||
"both TLS client certificate and key file must be "
|
||||
"specified a the same time");
|
||||
} else {
|
||||
dighost_warning("TLS context cannot be created");
|
||||
}
|
||||
|
||||
if (ISC_LINK_LINKED(query, link)) {
|
||||
next = ISC_LIST_NEXT(query, link);
|
||||
} else {
|
||||
next = NULL;
|
||||
}
|
||||
query_detach(&query);
|
||||
if (next == NULL) {
|
||||
clear_current_lookup();
|
||||
} else {
|
||||
start_tcp(next);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3250,16 +3429,27 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
||||
LOCK_LOOKUP;
|
||||
lookup_attach(query->lookup, &l);
|
||||
|
||||
if (query->tlsctx != NULL) {
|
||||
isc_tlsctx_free(&query->tlsctx);
|
||||
}
|
||||
|
||||
if (eresult == ISC_R_CANCELED || query->canceled) {
|
||||
if (eresult == ISC_R_CANCELED || eresult == ISC_R_TLSBADPEERCERT ||
|
||||
query->canceled)
|
||||
{
|
||||
debug("in cancel handler");
|
||||
isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
|
||||
if (eresult == ISC_R_TLSBADPEERCERT) {
|
||||
dighost_warning(
|
||||
"TLS peer certificate verification for "
|
||||
"%s failed: %s",
|
||||
sockstr,
|
||||
isc_nm_verify_tls_peer_result_string(handle));
|
||||
} else if (query->lookup->rdtype == dns_rdatatype_ixfr ||
|
||||
query->lookup->rdtype == dns_rdatatype_axfr)
|
||||
{
|
||||
puts("; Transfer failed.");
|
||||
}
|
||||
|
||||
if (!query->canceled) {
|
||||
cancel_lookup(l);
|
||||
}
|
||||
|
||||
query_detach(&query);
|
||||
lookup_detach(&l);
|
||||
clear_current_lookup();
|
||||
@@ -4571,3 +4761,12 @@ dig_idnsetup(dig_lookup_t *lookup, bool active) {
|
||||
return;
|
||||
#endif /* HAVE_LIBIDN2 */
|
||||
}
|
||||
|
||||
bool
|
||||
dig_lookup_is_tls(const dig_lookup_t *lookup) {
|
||||
if (lookup->tls_mode || (lookup->tls_ca_set && !lookup->https_mode)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
@@ -177,6 +177,17 @@ struct dig_lookup {
|
||||
bool https_get;
|
||||
char *https_path;
|
||||
};
|
||||
struct {
|
||||
bool tls_ca_set;
|
||||
char *tls_ca_file;
|
||||
bool tls_hostname_set;
|
||||
char *tls_hostname;
|
||||
bool tls_cert_file_set;
|
||||
char *tls_cert_file;
|
||||
bool tls_key_file_set;
|
||||
char *tls_key_file;
|
||||
isc_tlsctx_cache_t *tls_ctx_cache;
|
||||
};
|
||||
};
|
||||
|
||||
/*% The dig_query structure */
|
||||
@@ -209,7 +220,6 @@ struct dig_query {
|
||||
isc_time_t time_recv;
|
||||
uint64_t byte_count;
|
||||
isc_timer_t *timer;
|
||||
isc_tlsctx_t *tlsctx;
|
||||
};
|
||||
|
||||
struct dig_server {
|
||||
@@ -447,4 +457,7 @@ dig_idnsetup(dig_lookup_t *lookup, bool active);
|
||||
void
|
||||
dig_shutdown(void);
|
||||
|
||||
bool
|
||||
dig_lookup_is_tls(const dig_lookup_t *lookup);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
@@ -734,6 +734,26 @@ to 853.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \fB+[no]tls\-ca[=file\-name]\fP
|
||||
This option enables remote server TLS certificate validation for
|
||||
DNS transports, relying on TLS. Certificate authorities
|
||||
certificates are loaded from the specified PEM file
|
||||
(\fBfile\-name\fP). If the file is not specified, the default
|
||||
certificates from the global certificates store are used.
|
||||
.TP
|
||||
.B \fB+[no]tls\-certfile=file\-name\fP and \fB+[no]tls\-keyfile=file\-name\fP
|
||||
These options set the state of certificate\-based client
|
||||
authentication for DNS transports, relying on TLS. Both certificate
|
||||
chain file and private key file are expected to be in PEM format.
|
||||
Both options must be specified at the same time.
|
||||
.TP
|
||||
.B \fB+[no]tls\-hostname=hostname\fP
|
||||
This option makes \fBdig\fP use the provided hostname during remote
|
||||
server TLS certificate verification. Otherwise, the DNS server name
|
||||
is used. This option has no effect if \fB+tls\-ca\fP is not specified.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B +[no]topdown
|
||||
This feature is related to \fBdig +sigchase\fP, which is obsolete and
|
||||
has been removed. Use \fBdelv\fP instead.
|
||||
|
||||
Reference in New Issue
Block a user