Merge remote-tracking branch 'sara/feature/tls_auth_api' into features/tls_auth_api

This commit is contained in:
Willem Toorop 2015-10-21 15:34:57 +02:00
commit 3cc44ffcb1
13 changed files with 232 additions and 53 deletions

View File

@ -3,6 +3,12 @@
(ldns still necessary to be able to run tests though)
* Bugfix: DNSSEC code finding zone cut with redirects + pursuing unsigned
DS answers close to the root. Thanks Theogene Bucuti!
* Default port for TLS changed to 853
* Unofficial extension to the API to allow TLS hostname verification to be
required for stub mode when using only TLS as a transport.
When required a hostname must be supplied in the
'hostname' field of the upstream_list dict and the TLS cipher suites are
restricted to the 4 AEAD suites recommended in RFC7525.
* 2015-09-09: Version 0.3.3
* Fix clearing upstream events on shutdown

View File

@ -87,7 +87,7 @@ External dependencies are linked outside the getdns API build tree (we rely on c
* [libunbound from NLnet Labs](http://www.nlnetlabs.nl/projects/unbound/) version 1.4.16 or later
* [libidn from the FSF](http://www.gnu.org/software/libidn/) version 1.
* [libssl from the OpenSSL Project](https://www.openssl.org/) version 0.9.7 or later. (Note: version 1.0.2 or later is required for TLS support)
* [libssl from the OpenSSL Project](https://www.openssl.org/) version 0.9.7 or later. (Note: version 1.0.1 or later is required for TLS support, version 1.0.2 or later is required for TLS hostname authentication)
* Doxygen is used to generate documentation, while this is not technically necessary for the build it makes things a lot more pleasant.
You have to install the library and also the library-devel (or -dev) for your
@ -226,7 +226,7 @@ To install the [event loop integration libraries](https://github.com/getdnsapi/g
Note that in order to compile the examples, the `--with-libevent` switch is required.
As of the 0.2.0 release, when installing via Homebrew, the trust anchor is expected to be located at `$(brew --prefix)/etc/getdns-root.key`. Additionally, the OpenSSL library installed by Homebrew is linked against. Note that the Homebrew OpenSSL installation clones the Keychain certificates to the default OpenSSL location so TLS authentication should work out of the box.
As of the 0.2.0 release, when installing via Homebrew, the trust anchor is expected to be located at `$(brew --prefix)/etc/getdns-root.key`. Additionally, the OpenSSL library installed by Homebrew is linked against. Note that the Homebrew OpenSSL installation clones the Keychain certificates to the default OpenSSL location so TLS certificate authentication should work out of the box.
Contributors
============

View File

@ -105,10 +105,15 @@ AC_DEFUN([ACX_SSL_CHECKS], [
AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
dnl Authentication now requires 1.0.2, which supports TLSv1.2
AC_CHECK_LIB(ssl, SSL_CTX_get0_param,AC_DEFINE([HAVE_LIBSSL_102], [1],
[Define if you have libssl 1.0.2 or later]),[AC_MSG_WARN([libssl 1.0.2 or higher is required for TLS authentication. TLS will not be available.])])
])dnl End of ACX_SSL_CHECKS
dnl TLS v1.2 requires OpenSSL 1.0.1
AC_CHECK_LIB(ssl, TLSv1_2_client_method,AC_DEFINE([HAVE_TLS_v1_2], [1],
[Define if you have libssl with tls 1.2]),[AC_MSG_WARN([Cannot find TLSv1_2_client_method in libssl library. TLS will not be available.])])
dnl Native OpenSSL hostname verification requires OpenSSL 1.0.2
AC_CHECK_LIB(ssl, SSL_CTX_get0_param,AC_DEFINE([HAVE_SSL_HN_AUTH], [1],
[Define if you have libssl with host name verification]),[AC_MSG_WARN([Cannot find SSL_CTX_get0_param in libssl library. TLS hostname verification will not be available.])])
])
dnl Check for SSL, where SSL is mandatory
dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found

View File

@ -84,6 +84,8 @@ static struct const_info consts_info[] = {
{ 1201, "GETDNS_TRANSPORT_TCP", GETDNS_TRANSPORT_TCP_TEXT },
{ 1202, "GETDNS_TRANSPORT_TLS", GETDNS_TRANSPORT_TLS_TEXT },
{ 1203, "GETDNS_TRANSPORT_STARTTLS", GETDNS_TRANSPORT_STARTTLS_TEXT },
{ 1300, "GETDNS_AUTHENTICATION_NONE", GETDNS_AUTHENTICATION_NONE_TEXT },
{ 1301, "GETDNS_AUTHENTICATION_HOSTNAME", GETDNS_AUTHENTICATION_HOSTNAME_TEXT },
};
static int const_info_cmp(const void *a, const void *b)

View File

@ -56,10 +56,10 @@
#define GETDNS_PORT_ZERO 0
#define GETDNS_PORT_DNS 53
#define GETDNS_PORT_DNS_OVER_TLS 1021
#define GETDNS_PORT_DNS_OVER_TLS 853
#define GETDNS_STR_PORT_ZERO "0"
#define GETDNS_STR_PORT_DNS "53"
#define GETDNS_STR_PORT_DNS_OVER_TLS "1021"
#define GETDNS_STR_PORT_DNS_OVER_TLS "853"
void *plain_mem_funcs_user_arg = MF_PLAIN;
@ -567,8 +567,10 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
upstream->tcp.write_error = 0;
upstream->writes_done = 0;
upstream->responses_received = 0;
if (upstream->tls_hs_state != GETDNS_HS_FAILED)
if (upstream->tls_hs_state != GETDNS_HS_FAILED) {
upstream->tls_hs_state = GETDNS_HS_NONE;
upstream->tls_auth_failed = 0;
}
/* Now TLS stuff*/
if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj);
@ -627,6 +629,7 @@ upstream_init(getdns_upstream *upstream,
upstream->starttls_req = NULL;
upstream->transport = GETDNS_TRANSPORT_TCP;
upstream->tls_hs_state = GETDNS_HS_NONE;
upstream->tls_auth_failed = 0;
upstream->tls_auth_name[0] = '\0';
upstream->tcp.write_error = 0;
upstream->loop = NULL;
@ -897,6 +900,8 @@ getdns_context_create_with_extended_memory_functions(
result->edns_maximum_udp_payload_size = -1;
if ((r = create_default_dns_transports(result)))
goto error;
result->tls_auth = GETDNS_AUTHENTICATION_NONE;
result->tls_auth_min = GETDNS_AUTHENTICATION_NONE;
result->limit_outstanding_queries = 0;
result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
@ -1257,8 +1262,7 @@ getdns_set_base_dns_transports(
return GETDNS_RETURN_INVALID_PARAMETER;
if (!(new_transports = GETDNS_XMALLOC(context->my_mf,
getdns_transport_list_t, transport_count)))
getdns_transport_list_t, transport_count)))
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
if (context->dns_transports)
@ -1269,7 +1273,6 @@ getdns_set_base_dns_transports(
memcpy(context->dns_transports, transports,
transport_count * sizeof(getdns_transport_list_t));
context->dns_transport_count = transport_count;
dispatch_updated(context, GETDNS_CONTEXT_CODE_NAMESPACES);
return GETDNS_RETURN_GOOD;
}
@ -1418,6 +1421,26 @@ getdns_context_set_dns_transport_list(getdns_context *context,
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_dns_transport_list */
/*
* getdns_context_set_tls_authentication
*
*/
getdns_return_t
getdns_context_set_tls_authentication(getdns_context *context,
getdns_tls_authentication_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
if (value != GETDNS_AUTHENTICATION_NONE &&
value != GETDNS_AUTHENTICATION_HOSTNAME) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
context->tls_auth = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_tls_authentication_list */
static void
set_ub_limit_outstanding_queries(struct getdns_context* context, uint16_t value) {
/* num-queries-per-thread */
@ -2173,20 +2196,38 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
}
/* Transport can in theory be set per query in stub mode */
if (context->resolution_type == GETDNS_RESOLUTION_STUB) {
if (tls_is_in_transports_list(context) == 1 &&
context->tls_ctx == NULL) {
#ifdef HAVE_LIBSSL_102
if (context->resolution_type == GETDNS_RESOLUTION_STUB &&
tls_is_in_transports_list(context) == 1) {
if (context->tls_ctx == NULL) {
#ifdef HAVE_TLS_v1_2
/* Create client context, use TLS v1.2 only for now */
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
#endif
if(context->tls_ctx == NULL)
return GETDNS_RETURN_BAD_CONTEXT;
SSL_CTX_set_verify(context->tls_ctx, SSL_VERIFY_PEER, NULL);
/* Be strict and only use the cipher suites recommended in RFC7525
Unless we later fallback to oppotunistic. */
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EDH+aRSA+AESGCM";
if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS))
return GETDNS_RETURN_BAD_CONTEXT;
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx))
return GETDNS_RETURN_BAD_CONTEXT;
#else
if (tls_only_is_in_transports_list(context) == 1)
return GETDNS_RETURN_BAD_CONTEXT;
/* A null tls_ctx will make TLS fail and fallback to the other
transports will kick-in.*/
#endif
}
if (tls_only_is_in_transports_list(context) == 1 &&
context->tls_auth == GETDNS_AUTHENTICATION_HOSTNAME) {
context->tls_auth_min = GETDNS_AUTHENTICATION_HOSTNAME;
/* TODO: If no auth data provided for any upstream, fail here */
}
else {
context->tls_auth_min = GETDNS_AUTHENTICATION_NONE;
}
}
/* Block use of STARTTLS/TLS ONLY in recursive mode as it won't work */
/* Note: If TLS is used in recursive mode this will try TLS on port
* 53 so it is blocked here. So is 'STARTTLS only' at the moment. */

View File

@ -102,6 +102,7 @@ typedef struct getdns_upstream {
getdns_eventloop *loop;
getdns_tcp_state tcp;
char tls_auth_name[256];
size_t tls_auth_failed;
/* Pipelining of TCP network requests */
getdns_network_req *write_queue;
@ -145,6 +146,8 @@ struct getdns_context {
getdns_upstreams *upstreams;
uint16_t limit_outstanding_queries;
uint32_t dnssec_allowed_skew;
getdns_tls_authentication_t tls_auth; /* What user requested for TLS*/
getdns_tls_authentication_t tls_auth_min; /* Derived minimum auth allowed*/
getdns_transport_list_t *dns_transports;
size_t dns_transport_count;

View File

@ -208,6 +208,23 @@ typedef enum getdns_transport_list_t {
*/
/* Authentication options used when doing TLS */
typedef enum getdns_tls_authentication_t {
GETDNS_AUTHENTICATION_NONE = 1300,
GETDNS_AUTHENTICATION_HOSTNAME = 1301,
} getdns_tls_authentication_t;
/**
* \defgroup Base authentication texts
* @{
*/
#define GETDNS_AUTHENTICATION_NONE_TEXT "See getdns_context_set_tls_authentication()"
#define GETDNS_AUTHENTICATION_HOSTNAME_TEXT "See getdns_context_set_tls_authentication()"
/** @}
*/
/* Suffix appending methods */
typedef enum getdns_append_name_t {
GETDNS_APPEND_NAME_ALWAYS = 550,
@ -247,7 +264,8 @@ typedef enum getdns_context_code_t {
GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW = 614,
GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS = 615,
GETDNS_CONTEXT_CODE_TIMEOUT = 616,
GETDNS_CONTEXT_CODE_IDLE_TIMEOUT = 617
GETDNS_CONTEXT_CODE_IDLE_TIMEOUT = 617,
GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION = 618
} getdns_context_code_t;
/**
@ -272,6 +290,7 @@ typedef enum getdns_context_code_t {
#define GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS_TEXT "Change related to getdns_context_set_memory_functions"
#define GETDNS_CONTEXT_CODE_TIMEOUT_TEXT "Change related to getdns_context_set_timeout"
#define GETDNS_CONTEXT_CODE_IDLE_TIMEOUT_TEXT "Change related to getdns_context_set_idle_timeout"
#define GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION_TEXT "Change related to getdns_context_set_tls_authentication"
/** @}
*/
@ -347,6 +366,7 @@ typedef enum getdns_callback_type_t {
/** @}
*/
/**
* \defgroup rrtypes RR Types
* @{
@ -975,6 +995,10 @@ getdns_return_t
getdns_context_set_dns_transport_list(getdns_context *context,
size_t transport_count, getdns_transport_list_t *transports);
getdns_return_t
getdns_context_set_tls_authentication(getdns_context *context,
getdns_tls_authentication_t value);
getdns_return_t
getdns_context_set_idle_timeout(getdns_context *context, uint64_t timeout);

View File

@ -51,6 +51,7 @@ getdns_context_set_resolution_type
getdns_context_set_return_dnssec_status
getdns_context_set_suffix
getdns_context_set_timeout
getdns_context_set_tls_authentication
getdns_context_set_update_callback
getdns_context_set_upstream_recursive_servers
getdns_context_set_use_threads

View File

@ -104,6 +104,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
net_req->transport_current = 0;
memcpy(net_req->transports, owner->context->dns_transports,
net_req->transport_count * sizeof(getdns_transport_list_t));
net_req->tls_auth_min = owner->context->tls_auth_min;
memset(&net_req->event, 0, sizeof(net_req->event));
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
net_req->query_id = 0;

View File

@ -32,6 +32,7 @@
*/
#include <openssl/err.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
#include "config.h"
#include <fcntl.h>
@ -563,7 +564,7 @@ upstream_tls_timeout_cb(void *userarg)
tls_cleanup(upstream);
/* Need to handle the case where the far end doesn't respond to a
* TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@1021).
* TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853).
* For that case the socket never becomes writable so doesn't trigger any
* callbacks. If so then clear out the queue in one go.*/
int ret;
@ -590,7 +591,7 @@ stub_tls_timeout_cb(void *userarg)
tls_cleanup(upstream);
/* Need to handle the case where the far end doesn't respond to a
* TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@1021).
* TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853).
* For that case the socket never becomes writable so doesn't trigger any
* callbacks. If so then clear out the queue in one go.*/
int ret;
@ -819,19 +820,50 @@ tls_failed(getdns_upstream *upstream)
/* No messages should be scheduled onto an upstream in this state */
return ((upstream->transport == GETDNS_TRANSPORT_TLS ||
upstream->transport == GETDNS_TRANSPORT_STARTTLS) &&
upstream->tls_hs_state == GETDNS_HS_FAILED) ? 1: 0;
upstream->tls_hs_state == GETDNS_HS_FAILED) ? 1 : 0;
}
static int
tls_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) {
return (netreq->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME &&
upstream->tls_auth_failed) ? 0 : 1;
}
int
tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
int err;
err = X509_STORE_CTX_get_error(ctx);
const char * err_str;
err_str = X509_verify_cert_error_string(err);
DEBUG_STUB("--- %s, VERIFY RESULT: %s\n", __FUNCTION__, err_str);
/*Always proceed without changing result*/
return preverify_ok;
}
int
tls_verify_callback_with_fallback(int preverify_ok, X509_STORE_CTX *ctx) {
int err;
err = X509_STORE_CTX_get_error(ctx);
const char * err_str;
err_str = X509_verify_cert_error_string(err);
DEBUG_STUB("--- %s, VERIFY RESULT: (%d) \"%s\"\n", __FUNCTION__, err, err_str);
/*Proceed if error is hostname mismatch*/
if (err == X509_V_ERR_HOSTNAME_MISMATCH) {
DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__);
return 1;
}
else
return preverify_ok;
}
static SSL*
tls_create_object(getdns_context *context, int fd, const char* auth_name)
tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
{
#ifdef HAVE_LIBSSL_102
/* Create SSL instance */
if (context->tls_ctx == NULL || auth_name == NULL)
getdns_context *context = dnsreq->context;
if (context->tls_ctx == NULL)
return NULL;
SSL* ssl = SSL_new(context->tls_ctx);
X509_VERIFY_PARAM *param;
if(!ssl)
return NULL;
/* Connect the SSL object with a file descriptor */
@ -839,16 +871,56 @@ tls_create_object(getdns_context *context, int fd, const char* auth_name)
SSL_free(ssl);
return NULL;
}
SSL_set_tlsext_host_name(ssl, auth_name);
param = SSL_get0_param(ssl);
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
X509_VERIFY_PARAM_set1_host(param, auth_name, 0);
/* NOTE: this code will fallback on a given upstream, without trying
authentication on other upstreams first. This is non-optimal and but avoids
multiple TLS handshakes before getting a usable connection. */
/* If we have a hostname, always use it */
if (upstream->tls_auth_name[0] != '\0') {
/*Request certificate for the auth_name*/
SSL_set_tlsext_host_name(ssl, upstream->tls_auth_name);
#ifdef HAVE_SSL_HN_AUTH
/* Set up native OpenSSL hostname verification*/
X509_VERIFY_PARAM *param;
param = SSL_get0_param(ssl);
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
X509_VERIFY_PARAM_set1_host(param, upstream->tls_auth_name, 0);
DEBUG_STUB("--- %s, HOSTNAME VERIFICATION REQUESTED \n", __FUNCTION__);
#else
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME) {
/* TODO: Trigger post-handshake custom validation*/
DEBUG_STUB("--- %s, ERROR: Authentication functionality not available\n", __FUNCTION__);
upstream->tls_hs_state = GETDNS_HS_FAILED;
upstream->tls_auth_failed = 1;
return NULL;
}
#endif
/* Allow fallback to oppotunisitc if settings permit it*/
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME)
SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
else {
SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback);
SSL_CTX_set_cipher_list(context->tls_ctx, NULL);
}
} else {
/* Lack of host name is OK unless only authenticated TLS is specified*/
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME) {
DEBUG_STUB("--- %s, ERROR: No host name provided for authentication\n", __FUNCTION__);
upstream->tls_hs_state = GETDNS_HS_FAILED;
upstream->tls_auth_failed = 1;
return NULL;
} else {
DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__);
upstream->tls_auth_failed = 1;
SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback);
SSL_CTX_set_cipher_list(context->tls_ctx, NULL);
}
}
SSL_set_connect_state(ssl);
(void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
return ssl;
#else
return NULL;
#endif
}
static int
@ -905,6 +977,9 @@ tls_do_handshake(getdns_upstream *upstream)
}
}
upstream->tls_hs_state = GETDNS_HS_DONE;
r = SSL_get_verify_result(upstream->tls_obj);
if (r == X509_V_ERR_HOSTNAME_MISMATCH)
upstream->tls_auth_failed = 1;
/* Reset timeout on success*/
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->event.read_cb = NULL;
@ -1045,6 +1120,8 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
int q = tls_connected(upstream);
if (q != 0)
return q;
if (!tls_auth_status_ok(upstream, netreq))
return STUB_TLS_SETUP_ERROR;
/* Do we have remaining data that we could not write before? */
if (! tcp->write_buf) {
@ -1313,9 +1390,9 @@ upstream_read_cb(void *userarg)
if (netreq->owner == upstream->starttls_req) {
dnsreq = netreq->owner;
if (is_starttls_response(netreq)) {
upstream->tls_obj = tls_create_object(dnsreq->context,
upstream->tls_obj = tls_create_object(dnsreq,
upstream->fd,
upstream->tls_auth_name);
upstream);
if (upstream->tls_obj == NULL)
upstream->tls_hs_state = GETDNS_HS_FAILED;
upstream->tls_hs_state = GETDNS_HS_WRITE;
@ -1451,7 +1528,8 @@ netreq_upstream_write_cb(void *userarg)
static int
upstream_transport_valid(getdns_upstream *upstream,
getdns_transport_list_t transport)
getdns_transport_list_t transport,
getdns_network_req *netreq)
{
/* Single shot UDP, uses same upstream as plain TCP. */
if (transport == GETDNS_TRANSPORT_UDP)
@ -1472,7 +1550,7 @@ upstream_transport_valid(getdns_upstream *upstream,
/* Otherwise, transport must match, and not have failed */
if (upstream->transport != transport)
return 0;
if (tls_failed(upstream))
if (tls_failed(upstream) || !tls_auth_status_ok(upstream, netreq))
return 0;
return 1;
}
@ -1500,7 +1578,7 @@ upstream_select(getdns_network_req *netreq, getdns_transport_list_t transport)
DEBUG_STUB(" current upstream: %d of %d \n",(int)i, (int)upstreams->count);
do {
if (upstreams->upstreams[i].to_retry > 0 &&
upstream_transport_valid(&upstreams->upstreams[i], transport)) {
upstream_transport_valid(&upstreams->upstreams[i], transport, netreq)) {
upstreams->current = i;
DEBUG_STUB(" selected upstream: %d\n",(int)i);
return &upstreams->upstreams[i];
@ -1512,11 +1590,11 @@ upstream_select(getdns_network_req *netreq, getdns_transport_list_t transport)
upstream = upstreams->upstreams;
for (i = 0; i < upstreams->count; i++)
if (upstreams->upstreams[i].back_off < upstream->back_off &&
upstream_transport_valid(&upstreams->upstreams[i], transport))
upstream_transport_valid(&upstreams->upstreams[i], transport, netreq))
upstream = &upstreams->upstreams[i];
/* Need to check again that the transport is valid */
if (!upstream_transport_valid(upstream, transport)) {
if (!upstream_transport_valid(upstream, transport, netreq)) {
DEBUG_STUB(" ! No valid upstream available\n");
return NULL;
}
@ -1555,7 +1633,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
return upstream->fd;
fd = tcp_connect(upstream, transport);
if (fd == -1) return -1;
upstream->tls_obj = tls_create_object(dnsreq->context, fd, upstream->tls_auth_name);
upstream->tls_obj = tls_create_object(dnsreq, fd, upstream);
if (upstream->tls_obj == NULL) {
close(fd);
return -1;
@ -1598,6 +1676,7 @@ find_upstream_for_specific_transport(getdns_network_req *netreq,
getdns_transport_list_t transport,
int *fd)
{
// TODO[TLS]: Need to loop over upstreams here!!
getdns_upstream *upstream = upstream_select(netreq, transport);
if (!upstream)
return NULL;

View File

@ -371,9 +371,11 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-a\tPerform asynchronous resolution "
"(default = synchronous)\n");
fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n");
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n");
fprintf(out, "\t-D\tSet edns0 do bit\n");
fprintf(out, "\t-d\tclear edns0 do bit\n");
fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n");
fprintf(out, "\t-F <filename>\tread the queries from the specified file\n");
fprintf(out, "\t-G\tgeneral lookup\n");
fprintf(out, "\t-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n");
@ -382,13 +384,15 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-I\tInteractive mode (> 1 queries on same context)\n");
fprintf(out, "\t-j\tOutput json response dict\n");
fprintf(out, "\t-J\tPretty print json response dict\n");
fprintf(out, "\t-n\tSet TLS authentication mode to NONE (default)\n");
fprintf(out, "\t-m\tSet TLS authentication mode to HOSTNAME\n");
fprintf(out, "\t-p\tPretty print response dict\n");
fprintf(out, "\t-r\tSet recursing resolution type\n");
fprintf(out, "\t-q\tQuiet mode - don't print response\n");
fprintf(out, "\t-R\tPrint root trust anchors\n");
fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n");
fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n");
fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n");
fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n");
fprintf(out, "\t-T\tSet transport to TCP only\n");
fprintf(out, "\t-O\tSet transport to TCP only keep connections open\n");
fprintf(out, "\t-L\tSet transport to TLS only keep connections open\n");
@ -398,8 +402,7 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-U\tSet transport to UDP only\n");
fprintf(out, "\t-l <transports>\tSet transport list. List can contain 1 of each of the characters\n");
fprintf(out, "\t\t\t U T L S for UDP, TCP, TLS or STARTTLS e.g 'UT' or 'LST' \n");
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
fprintf(out, "\t-q\tQuiet mode - don't print response\n");
}
static getdns_return_t validate_chain(getdns_dict *response)
@ -695,6 +698,14 @@ getdns_return_t parse_args(int argc, char **argv)
case 'k':
print_trust_anchors = 1;
break;
case 'n':
getdns_context_set_tls_authentication(context,
GETDNS_AUTHENTICATION_NONE);
break;
case 'm':
getdns_context_set_tls_authentication(context,
GETDNS_AUTHENTICATION_HOSTNAME);
break;
case 'p':
json = 0;
case 'q':
@ -862,6 +873,9 @@ getdns_return_t do_the_call(void)
}
if (r == GETDNS_RETURN_GOOD && !batch_mode)
getdns_context_run(context);
if (r != GETDNS_RETURN_GOOD)
fprintf(stderr, "An error occurred: %d '%s'\n", r,
getdns_get_errorstr_by_id(r));
} else {
switch (calltype) {
case GENERAL:

View File

@ -55,7 +55,7 @@ usage () {
echo "can be specified via the command line option."
echo
echo "usage: test_transport.sh"
ehco " -p path to getdns_query binary"
echo " -p path to getdns_query binary"
echo " -s server configured for only TCP and UDP"
echo " -t server configured for TLS, STARTTLS, TCP and UDP"
echo " (This must include the hostname e.g. 185.49.141.38~www.dnssec-name-and-shame.com)"
@ -77,20 +77,22 @@ echo $TLS_SERVER_IP_NO_NAME
GOOD_QUERIES=(
"-s -A -q getdnsapi.net -l U @${SERVER_IP} "
"-s -A -q getdnsapi.net -l T @${SERVER_IP} "
"-s -A -q getdnsapi.net -l L @${TLS_SERVER_IP}"
"-s -A -q getdnsapi.net -l S @${TLS_SERVER_IP}")
"-s -A -q getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP}")
#"-s -A -q getdnsapi.net -l S @${TLS_SERVER_IP_NO_NAME}")
GOOD_FALLBACK_QUERIES=(
"-s -A -q getdnsapi.net -l LT @${SERVER_IP}"
"-s -A -q getdnsapi.net -l LT @${SERVER_IP}"
"-s -A -q getdnsapi.net -l LT @${TLS_SERVER_IP_NO_NAME}"
"-s -A -q getdnsapi.net -l L @${SERVER_IP} @${TLS_SERVER_IP}"
"-s -A -q getdnsapi.net -l LT -m @${TLS_SERVER_IP_NO_NAME}"
"-s -A -q getdnsapi.net -l L @${SERVER_IP} @${TLS_SERVER_IP_NO_NAME}"
"-s -G -q DNSKEY getdnsapi.net -l UT @${SERVER_IP} -b 512 -D")
NOT_AVAILABLE_QUERIES=(
"-s -A -q getdnsapi.net -l L @${SERVER_IP} "
"-s -A -q getdnsapi.net -l S @${SERVER_IP} "
"-s -A -q getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME} "
#"-s -A -q getdnsapi.net -l S @${SERVER_IP} "
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} "
"-s -G -q DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D")
echo "Starting transport test"

View File

@ -213,8 +213,9 @@ typedef struct getdns_network_req
struct getdns_upstream *upstream;
int fd;
getdns_transport_list_t transports[GETDNS_TRANSPORTS_MAX];
size_t transport_count;
size_t transport_current;
size_t transport_count;
size_t transport_current;
getdns_tls_authentication_t tls_auth_min;
getdns_eventloop_event event;
getdns_tcp_state tcp;
uint16_t query_id;