mirror of https://github.com/getdnsapi/getdns.git
Add TLS 1.3 test.
Add a new item tls_version to call_reporting, containing the OpenSSL version string for the name of the protocol used for the connection. The test does a normal lookup, but first sets the cipher list to TLS1.3 only ciphers. This will cause a Bad Context error at search time, so we can tell if the underlying OpenSSL library lacks TLS 1.3. The check the call reporting for a TLS version of "TLSv1.3".
This commit is contained in:
parent
62ad159f15
commit
0291e205fd
|
@ -211,6 +211,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
||||||
net_req->debug_tls_auth_status = GETDNS_AUTH_NONE;
|
net_req->debug_tls_auth_status = GETDNS_AUTH_NONE;
|
||||||
net_req->debug_tls_peer_cert.size = 0;
|
net_req->debug_tls_peer_cert.size = 0;
|
||||||
net_req->debug_tls_peer_cert.data = NULL;
|
net_req->debug_tls_peer_cert.data = NULL;
|
||||||
|
net_req->debug_tls_version = NULL;
|
||||||
net_req->debug_udp = 0;
|
net_req->debug_udp = 0;
|
||||||
|
|
||||||
/* Scheduling, touch only via _getdns_netreq_change_state!
|
/* Scheduling, touch only via _getdns_netreq_change_state!
|
||||||
|
|
14
src/stub.c
14
src/stub.c
|
@ -1687,12 +1687,14 @@ upstream_write_cb(void *userarg)
|
||||||
remove_from_write_queue(upstream, netreq);
|
remove_from_write_queue(upstream, netreq);
|
||||||
|
|
||||||
if (netreq->owner->return_call_reporting &&
|
if (netreq->owner->return_call_reporting &&
|
||||||
netreq->upstream->tls_obj &&
|
netreq->upstream->tls_obj) {
|
||||||
netreq->debug_tls_peer_cert.data == NULL &&
|
if (netreq->debug_tls_peer_cert.data == NULL &&
|
||||||
(cert = SSL_get_peer_certificate(netreq->upstream->tls_obj))) {
|
(cert = SSL_get_peer_certificate(netreq->upstream->tls_obj))) {
|
||||||
netreq->debug_tls_peer_cert.size = i2d_X509(
|
netreq->debug_tls_peer_cert.size = i2d_X509(
|
||||||
cert, &netreq->debug_tls_peer_cert.data);
|
cert, &netreq->debug_tls_peer_cert.data);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
|
}
|
||||||
|
netreq->debug_tls_version = SSL_get_version(netreq->upstream->tls_obj);
|
||||||
}
|
}
|
||||||
/* Need this because auth status is reset on connection close */
|
/* Need this because auth status is reset on connection close */
|
||||||
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
|
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
|
||||||
|
|
|
@ -54,6 +54,13 @@
|
||||||
|
|
||||||
#define EDNS0_PADDING_CODE 12
|
#define EDNS0_PADDING_CODE 12
|
||||||
|
|
||||||
|
static const char TLS13_CIPHER_SUITE[] =
|
||||||
|
"TLS13-AES-256-GCM-SHA384:"
|
||||||
|
"TLS13-CHACHA20-POLY1305-SHA256:"
|
||||||
|
"TLS13-AES-128-GCM-SHA256:"
|
||||||
|
"TLS13-AES-128-CCM-8-SHA256:"
|
||||||
|
"TLS13-AES-128-CCM-SHA256";
|
||||||
|
|
||||||
#define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""
|
#define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""
|
||||||
|
|
||||||
/* Plugin exit values */
|
/* Plugin exit values */
|
||||||
|
@ -298,6 +305,7 @@ static void usage()
|
||||||
" Check server support for EDNS0 padding in TLS\n"
|
" Check server support for EDNS0 padding in TLS\n"
|
||||||
" Special blocksize values are 0 = off,\n"
|
" Special blocksize values are 0 = off,\n"
|
||||||
" 1 = sensible default.\n"
|
" 1 = sensible default.\n"
|
||||||
|
" tls-1.3 Check whether server supports TLS 1.3\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Enabling monitoring mode ensures output messages and exit statuses conform\n"
|
"Enabling monitoring mode ensures output messages and exit statuses conform\n"
|
||||||
"to the requirements of monitoring plugins (www.monitoring-plugins.org).\n",
|
"to the requirements of monitoring plugins (www.monitoring-plugins.org).\n",
|
||||||
|
@ -386,7 +394,8 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
const char *name,
|
const char *name,
|
||||||
uint16_t type,
|
uint16_t type,
|
||||||
getdns_dict *extensions,
|
getdns_dict *extensions,
|
||||||
getdns_dict **response)
|
getdns_dict **response,
|
||||||
|
getdns_return_t *getdns_return)
|
||||||
{
|
{
|
||||||
getdns_return_t ret;
|
getdns_return_t ret;
|
||||||
getdns_dict *search_extensions =
|
getdns_dict *search_extensions =
|
||||||
|
@ -394,6 +403,8 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
|
|
||||||
/* We always turn on the return_call_reporting extension. */
|
/* We always turn on the return_call_reporting extension. */
|
||||||
if ((ret = getdns_dict_set_int(search_extensions, "return_call_reporting", GETDNS_EXTENSION_TRUE)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_set_int(search_extensions, "return_call_reporting", GETDNS_EXTENSION_TRUE)) != GETDNS_RETURN_GOOD) {
|
||||||
|
if (getdns_return)
|
||||||
|
*getdns_return = ret;
|
||||||
fprintf(test_info->errout,
|
fprintf(test_info->errout,
|
||||||
"Cannot set return call reporting: %s (%d)",
|
"Cannot set return call reporting: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
@ -417,11 +428,15 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
if (!extensions)
|
if (!extensions)
|
||||||
getdns_dict_destroy(search_extensions);
|
getdns_dict_destroy(search_extensions);
|
||||||
if (ret != GETDNS_RETURN_GOOD) {
|
if (ret != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
if (getdns_return) {
|
||||||
"Error resolving '%s': %s (%d)",
|
*getdns_return = ret;
|
||||||
name,
|
} else {
|
||||||
getdns_get_errorstr_by_id(ret),
|
fprintf(test_info->errout,
|
||||||
ret);
|
"Error resolving '%s': %s (%d)",
|
||||||
|
name,
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
}
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,6 +446,8 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
getdns_pretty_print_dict(*response));
|
getdns_pretty_print_dict(*response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getdns_return)
|
||||||
|
*getdns_return = ret;
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -694,7 +711,7 @@ static exit_value search_check(const struct test_info_s *test_info,
|
||||||
exit_value xit;
|
exit_value xit;
|
||||||
getdns_dict *resp;
|
getdns_dict *resp;
|
||||||
|
|
||||||
if ((xit = search(test_info, lookup_name, lookup_type, NULL, &resp)) != EXIT_OK)
|
if ((xit = search(test_info, lookup_name, lookup_type, NULL, &resp, NULL)) != EXIT_OK)
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
if ((xit = check_result(test_info, resp)) != EXIT_OK)
|
if ((xit = check_result(test_info, resp)) != EXIT_OK)
|
||||||
|
@ -1170,7 +1187,8 @@ static exit_value test_dnssec_validate(const struct test_info_s *test_info,
|
||||||
"dnssec-failed.org",
|
"dnssec-failed.org",
|
||||||
GETDNS_RRTYPE_A,
|
GETDNS_RRTYPE_A,
|
||||||
NULL,
|
NULL,
|
||||||
&response)) != EXIT_OK)
|
&response,
|
||||||
|
NULL)) != EXIT_OK)
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
uint32_t error_id, rcode;
|
uint32_t error_id, rcode;
|
||||||
|
@ -1209,7 +1227,8 @@ static exit_value test_dnssec_validate(const struct test_info_s *test_info,
|
||||||
"dnssec-failed.org",
|
"dnssec-failed.org",
|
||||||
GETDNS_RRTYPE_A,
|
GETDNS_RRTYPE_A,
|
||||||
extensions,
|
extensions,
|
||||||
&response2)) != EXIT_OK)
|
&response2,
|
||||||
|
NULL)) != EXIT_OK)
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
getdns_dict_destroy(extensions);
|
getdns_dict_destroy(extensions);
|
||||||
|
@ -1238,6 +1257,100 @@ static exit_value test_dnssec_validate(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static exit_value test_tls13(const struct test_info_s *test_info,
|
||||||
|
char ** av)
|
||||||
|
{
|
||||||
|
exit_value xit;
|
||||||
|
getdns_return_t ret;
|
||||||
|
|
||||||
|
if (*av) {
|
||||||
|
fputs("tls-1.3 takes no arguments", test_info->errout);
|
||||||
|
return EXIT_USAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set cipher list to TLS 1.3-only ciphers. If we are using
|
||||||
|
* an OpenSSL version that doesn't support TLS 1.3 this will cause
|
||||||
|
* a Bad Context error on the lookup.
|
||||||
|
*/
|
||||||
|
if ((ret = getdns_context_set_tls_cipher_list(test_info->context, TLS13_CIPHER_SUITE)) != GETDNS_RETURN_GOOD) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot set TLS 1.3 cipher list: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
getdns_dict *response;
|
||||||
|
|
||||||
|
if ((xit = search(test_info,
|
||||||
|
DEFAULT_LOOKUP_NAME,
|
||||||
|
DEFAULT_LOOKUP_TYPE,
|
||||||
|
NULL,
|
||||||
|
&response,
|
||||||
|
&ret)) != EXIT_OK) {
|
||||||
|
if (xit == EXIT_CRITICAL) {
|
||||||
|
if (ret == GETDNS_RETURN_BAD_CONTEXT) {
|
||||||
|
fputs("Your version of OpenSSL does not support TLS 1.3 ciphers. You need at least OpenSSL 1.1.1.",
|
||||||
|
test_info->errout);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
fputs("Cannot establish TLS 1.3 connection.",
|
||||||
|
test_info->errout);
|
||||||
|
return EXIT_CRITICAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return xit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((xit = get_report_info(test_info, response, NULL, NULL, NULL)) != EXIT_OK)
|
||||||
|
return xit;
|
||||||
|
|
||||||
|
getdns_list *l;
|
||||||
|
|
||||||
|
if ((ret = getdns_dict_get_list(response, "call_reporting", &l)) != GETDNS_RETURN_GOOD) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot get call report: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
getdns_dict *d;
|
||||||
|
|
||||||
|
if ((ret = getdns_list_get_dict(l, 0, &d)) != GETDNS_RETURN_GOOD) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot get call report first item: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search is forced TLS, so tls_version flag must exist. */
|
||||||
|
getdns_bindata *version;
|
||||||
|
|
||||||
|
if ((ret = getdns_dict_get_bindata(d, "tls_version", &version)) != GETDNS_RETURN_GOOD) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot get TLS version: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char TLS_1_3_SIG[] = "TLSv1.3";
|
||||||
|
|
||||||
|
if (strncmp((const char *)version->data, TLS_1_3_SIG, sizeof(TLS_1_3_SIG) - 1) != 0) {
|
||||||
|
fputs("Server does not support TLS 1.3", test_info->errout);
|
||||||
|
return EXIT_CRITICAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((xit = check_result(test_info, response)) != EXIT_OK)
|
||||||
|
return xit;
|
||||||
|
|
||||||
|
fputs("Server supports TLS 1.3", test_info->errout);
|
||||||
|
return EXIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static struct test_funcs_s
|
static struct test_funcs_s
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -1254,6 +1367,7 @@ static struct test_funcs_s
|
||||||
{ "tls-padding", true, false, test_padding },
|
{ "tls-padding", true, false, test_padding },
|
||||||
{ "keepalive", false, true, test_keepalive },
|
{ "keepalive", false, true, test_keepalive },
|
||||||
{ "dnssec-validate", false, false, test_dnssec_validate },
|
{ "dnssec-validate", false, false, test_dnssec_validate },
|
||||||
|
{ "tls-1.3", true, false, test_tls13 },
|
||||||
{ NULL, false, false, NULL }
|
{ NULL, false, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -242,6 +242,7 @@ typedef struct getdns_network_req
|
||||||
uint64_t debug_end_time;
|
uint64_t debug_end_time;
|
||||||
getdns_auth_state_t debug_tls_auth_status;
|
getdns_auth_state_t debug_tls_auth_status;
|
||||||
getdns_bindata debug_tls_peer_cert;
|
getdns_bindata debug_tls_peer_cert;
|
||||||
|
const char *debug_tls_version;
|
||||||
size_t debug_udp;
|
size_t debug_udp;
|
||||||
|
|
||||||
/* When more space is needed for the wire_data response than is
|
/* When more space is needed for the wire_data response than is
|
||||||
|
|
|
@ -920,6 +920,12 @@ _getdns_create_call_reporting_dict(
|
||||||
getdns_dict_destroy(netreq_debug);
|
getdns_dict_destroy(netreq_debug);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (getdns_dict_util_set_string(netreq_debug, "tls_version",
|
||||||
|
netreq->debug_tls_version)){
|
||||||
|
|
||||||
|
getdns_dict_destroy(netreq_debug);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (getdns_dict_set_bindata(netreq_debug, "tls_peer_cert",
|
if (getdns_dict_set_bindata(netreq_debug, "tls_peer_cert",
|
||||||
&netreq->debug_tls_peer_cert)) {
|
&netreq->debug_tls_peer_cert)) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue