From e710286e4522454ac75c5cb18feeb0c8cab4fea9 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Mon, 21 Sep 2015 13:02:03 +0100 Subject: [PATCH 1/7] Start work on better authentication --- m4/acx_openssl.m4 | 12 +++++++++--- src/context.c | 12 +++++++++--- src/stub.c | 17 ++++++++++++++++- src/stub.h | 2 ++ src/test/tests_transports.sh | 2 +- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 index 693075c4..e3aa4586 100644 --- a/m4/acx_openssl.m4 +++ b/m4/acx_openssl.m4 @@ -105,9 +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 TLS v1.2 requires OpenSSL 1.0.1 +AC_CHECK_LIB(ssl, TLSv1_2_client_method,AC_DEFINE([HAVE_LIBTLS1_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 End of ACX_SSL_CHECKS + +dnl Authentication for TLS requires 1.0.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. Authenticated TLS will not be available.])]) ])dnl End of ACX_SSL_CHECKS dnl Check for SSL, where SSL is mandatory diff --git a/src/context.c b/src/context.c index 0a7478c4..7e46d57e 100644 --- a/src/context.c +++ b/src/context.c @@ -2176,15 +2176,21 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, if (context->resolution_type == GETDNS_RESOLUTION_STUB) { if (tls_is_in_transports_list(context) == 1 && context->tls_ctx == NULL) { -#ifdef HAVE_LIBSSL_102 +#ifdef HAVE_LIBTLS1_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); + SSL_CTX_set_verify(context->tls_ctx, SSL_VERIFY_PEER, _getdns_tls_verify_callback); 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 + } } /* Block use of STARTTLS/TLS ONLY in recursive mode as it won't work */ diff --git a/src/stub.c b/src/stub.c index b9da8d17..6cb5ce57 100644 --- a/src/stub.c +++ b/src/stub.c @@ -827,8 +827,13 @@ tls_create_object(getdns_context *context, int fd, const char* auth_name) { #ifdef HAVE_LIBSSL_102 /* Create SSL instance */ - if (context->tls_ctx == NULL || auth_name == NULL) + if (context->tls_ctx == NULL) return NULL; + + // if (auth_name[0] == '\0') { + // DEBUG_STUB("--- %s, ERROR: No host name provided for authentication\n", __FUNCTION__); + // return NULL; + // } SSL* ssl = SSL_new(context->tls_ctx); X509_VERIFY_PARAM *param; @@ -851,6 +856,16 @@ tls_create_object(getdns_context *context, int fd, const char* auth_name) #endif } +int +_getdns_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, ERROR: %s\n", __FUNCTION__, err_str); + return 1; +} + static int tls_do_handshake(getdns_upstream *upstream) { diff --git a/src/stub.h b/src/stub.h index 41aa629a..e10c39be 100644 --- a/src/stub.h +++ b/src/stub.h @@ -41,6 +41,8 @@ getdns_return_t _getdns_submit_stub_request(getdns_network_req *netreq); void _getdns_cancel_stub_request(getdns_network_req *netreq); +int _getdns_tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx); + #endif /* stub.h */ diff --git a/src/test/tests_transports.sh b/src/test/tests_transports.sh index 98c3aec3..ec75e7ab 100755 --- a/src/test/tests_transports.sh +++ b/src/test/tests_transports.sh @@ -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)" From af617e92a749b6b47fa55eb9560361a14c209379 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 25 Sep 2015 17:28:45 +0100 Subject: [PATCH 2/7] Implement authenticaiton fallback on a given upstream (needs more work). Also need API option to set auth requirement. --- Makefile.in | 3 ++ m4/acx_openssl.m4 | 11 ++-- src/Makefile.in | 2 + src/context.c | 15 +++++- src/context.h | 3 ++ src/request-internal.c | 2 + src/stub.c | 111 +++++++++++++++++++++++++++++----------- src/test/Makefile.in | 3 ++ src/test/getdns_query.c | 3 ++ src/types-internal.h | 6 ++- 10 files changed, 120 insertions(+), 39 deletions(-) diff --git a/Makefile.in b/Makefile.in index 93ef6946..01e04555 100644 --- a/Makefile.in +++ b/Makefile.in @@ -91,6 +91,9 @@ doc: FORCE example: cd spec/example && $(MAKE) $@ +test_code: + cd src && $(MAKE) $@ + test: cd src && $(MAKE) $@ diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 index e3aa4586..4a567fd2 100644 --- a/m4/acx_openssl.m4 +++ b/m4/acx_openssl.m4 @@ -107,14 +107,13 @@ AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT]) dnl TLS v1.2 requires OpenSSL 1.0.1 -AC_CHECK_LIB(ssl, TLSv1_2_client_method,AC_DEFINE([HAVE_LIBTLS1_2], [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 End of ACX_SSL_CHECKS -dnl Authentication for TLS requires 1.0.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. Authenticated TLS will not be available.])]) -])dnl End of ACX_SSL_CHECKS +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. Native TLS hostname verification will not be available, custom code will be used.])]) +]) dnl Check for SSL, where SSL is mandatory dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found diff --git a/src/Makefile.in b/src/Makefile.in index 470f6ff2..b7f81f60 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -147,6 +147,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo libgetdns.la: $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols +test_code: FORCE + cd test && $(MAKE) $@ test: FORCE cd test && $(MAKE) $@ diff --git a/src/context.c b/src/context.c index 7e46d57e..dcae9dcb 100644 --- a/src/context.c +++ b/src/context.c @@ -897,6 +897,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_req = 1; + result->tls_auth_fallback_ok = 1; result->limit_outstanding_queries = 0; result->return_dnssec_status = GETDNS_EXTENSION_FALSE; @@ -2176,11 +2178,22 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, if (context->resolution_type == GETDNS_RESOLUTION_STUB) { if (tls_is_in_transports_list(context) == 1 && context->tls_ctx == NULL) { -#ifdef HAVE_LIBTLS1_2 +#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()); if(context->tls_ctx == NULL) return GETDNS_RETURN_BAD_CONTEXT; + /* Be strict and only use the cipher suites recommended in RFC7525 */ + 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 ((tls_only_is_in_transports_list(context) == 1) && context->tls_auth_req) + context->tls_auth_fallback_ok = 0; + /* TODO: If no auth data provided for any upstream, fail here */ + else + context->tls_auth_fallback_ok = 1; + /* By default cert chain will be verified, but note that per + connection management of the result and hostname verification is done.*/ SSL_CTX_set_verify(context->tls_ctx, SSL_VERIFY_PEER, _getdns_tls_verify_callback); if (!SSL_CTX_set_default_verify_paths(context->tls_ctx)) return GETDNS_RETURN_BAD_CONTEXT; diff --git a/src/context.h b/src/context.h index 4e762843..67a4725c 100644 --- a/src/context.h +++ b/src/context.h @@ -145,6 +145,9 @@ struct getdns_context { getdns_upstreams *upstreams; uint16_t limit_outstanding_queries; uint32_t dnssec_allowed_skew; + /*Make this a list*/ + size_t tls_auth_req; + size_t tls_auth_fallback_ok; /*Redundant but convinient*/ getdns_transport_list_t *dns_transports; size_t dns_transport_count; diff --git a/src/request-internal.c b/src/request-internal.c index ed4722ab..42dce648 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -104,6 +104,8 @@ 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_req = owner->context->tls_auth_req; + net_req->tls_auth_fallback_ok = owner->context->tls_auth_fallback_ok; memset(&net_req->event, 0, sizeof(net_req->event)); memset(&net_req->tcp, 0, sizeof(net_req->tcp)); net_req->query_id = 0; diff --git a/src/stub.c b/src/stub.c index 6cb5ce57..ada93bf6 100644 --- a/src/stub.c +++ b/src/stub.c @@ -32,6 +32,7 @@ */ #include +#include #include #include "config.h" #include @@ -78,7 +79,6 @@ static void stub_timeout_cb(void *userarg); /* General utility functions */ /*****************************/ - static void rollover_secret() { @@ -822,20 +822,39 @@ tls_failed(getdns_upstream *upstream) upstream->tls_hs_state == GETDNS_HS_FAILED) ? 1: 0; } +int +_getdns_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, ERROR: %s\n", __FUNCTION__, err_str); + /*Always proceed without changing result*/ + return preverify_ok; +} + +int +_getdns_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, ERROR: (%d) \"%s\"\n", __FUNCTION__, err, err_str); + /*Proceed if error is hostname mismatch*/ + if (err == X509_V_ERR_HOSTNAME_MISMATCH) + 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 */ + getdns_context *context = dnsreq->context; if (context->tls_ctx == NULL) return NULL; - - // if (auth_name[0] == '\0') { - // DEBUG_STUB("--- %s, ERROR: No host name provided for authentication\n", __FUNCTION__); - // return NULL; - // } SSL* ssl = SSL_new(context->tls_ctx); - X509_VERIFY_PARAM *param; if(!ssl) return NULL; @@ -844,26 +863,47 @@ 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 is + an interim simplification. */ + + /* Lack of host name is OK unless only authenticated TLS is specified*/ + if (upstream->tls_auth_name[0] == '\0') { + if (!dnsreq->netreqs[0]->tls_auth_fallback_ok) { + DEBUG_STUB("--- %s, ERROR: No host name provided for authentication\n", __FUNCTION__); + upstream->tls_hs_state = GETDNS_HS_FAILED; + return NULL; + } else { + SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); + } + } else { + /*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); +#else + /* TODO: Trigger post-handshake custom validation*/ + if (!dnsreq->netreqs[0]->tls_auth_fallback_ok) { + 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 from authenticated TLS if settings permit it (use NONE here?)*/ + if (dnsreq->netreqs[0]->tls_auth_fallback_ok) + SSL_set_verify(ssl, SSL_VERIFY_NONE, _getdns_tls_verify_callback_with_fallback); + } + SSL_set_connect_state(ssl); (void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); return ssl; -#else - return NULL; -#endif -} - -int -_getdns_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, ERROR: %s\n", __FUNCTION__, err_str); - return 1; } static int @@ -920,6 +960,17 @@ tls_do_handshake(getdns_upstream *upstream) } } upstream->tls_hs_state = GETDNS_HS_DONE; + /* TODO: Can we detect the authentication state of the connection here?*/ +//#ifndef HAVE_SSL_HN_AUTH + /*TODO: When OpenSSL 1.0.2 not available, use custom function to validate + the hostname.*/ + // X509* cert = SSL_get_peer_certificate(upstream->tls_obj); + // if(cert) { X509_free(cert); } /* Free immediately */ + // if(NULL == cert) return 0; + // if (!verify_cert_hostname(cert, upstream->tls_auth_name)) + // DEBUG_STUB("--- %s %s\n", __FUNCTION__, "Hostname verification failed: "); + // X509_free(cert); +//#endif /* Reset timeout on success*/ GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); upstream->event.read_cb = NULL; @@ -1328,9 +1379,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; @@ -1570,7 +1621,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; @@ -1633,7 +1684,7 @@ find_upstream_for_netreq(getdns_network_req *netreq) netreq->transports[i], &fd); if (fd == -1 || !upstream) - continue; + continue; netreq->transport_current = i; netreq->upstream = upstream; return fd; diff --git a/src/test/Makefile.in b/src/test/Makefile.in index cb07b954..fb420392 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -157,6 +157,9 @@ nolibldns: @false test: $(NOLIBCHECK) $(NOLIBLDNS) all + +test_code: $(NOLIBCHECK) all + (cd $(srcdir)/../.. && find . -type f -executable -and \( -name "*.[ch]" -or -name "*.html" -or -name "*.in" -or -name "*.good" -or -name "*.ac" \) | awk 'BEGIN{e=0}{print("ERROR! Executable bit found on", $$0);e=1}END{exit(e)}') ./$(CHECK_GETDNS) if test $(have_libevent) = 1 ; then ./$(CHECK_EVENT_PROG) ; fi diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index bc9d4043..94942e94 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -862,6 +862,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: diff --git a/src/types-internal.h b/src/types-internal.h index 5750fdc5..9f0458eb 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -196,8 +196,10 @@ 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; + size_t tls_auth_req; + size_t tls_auth_fallback_ok; getdns_eventloop_event event; getdns_tcp_state tcp; uint16_t query_id; From 6b4ee4ed312c5619bff193135a84a40207892555 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Tue, 29 Sep 2015 12:09:39 +0100 Subject: [PATCH 3/7] Block authenticated requests on unauthenticated connection --- src/context.c | 5 ++++- src/context.h | 1 + src/stub.c | 48 ++++++++++++++++++++++++++++-------------------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/context.c b/src/context.c index dcae9dcb..b5aca374 100644 --- a/src/context.c +++ b/src/context.c @@ -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; diff --git a/src/context.h b/src/context.h index 67a4725c..5c16a6ff 100644 --- a/src/context.h +++ b/src/context.h @@ -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; diff --git a/src/stub.c b/src/stub.c index ada93bf6..a3c94d83 100644 --- a/src/stub.c +++ b/src/stub.c @@ -819,7 +819,14 @@ 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_req && + !netreq->tls_auth_fallback_ok && + upstream->tls_auth_failed) ? 0 : 1; } int @@ -828,21 +835,23 @@ _getdns_tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) { err = X509_STORE_CTX_get_error(ctx); const char * err_str; err_str = X509_verify_cert_error_string(err); - DEBUG_STUB("--- %s, ERROR: %s\n", __FUNCTION__, err_str); + DEBUG_STUB("--- %s, VERIFY RESULT: %s\n", __FUNCTION__, err_str); /*Always proceed without changing result*/ return preverify_ok; } int -_getdns_tls_verify_callback_with_fallback(int preverify_ok, X509_STORE_CTX *ctx) { +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, ERROR: (%d) \"%s\"\n", __FUNCTION__, err, err_str); + 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) + if (err == X509_V_ERR_HOSTNAME_MISMATCH) { + DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__); return 1; + } else return preverify_ok; } @@ -875,6 +884,8 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) upstream->tls_hs_state = GETDNS_HS_FAILED; return NULL; } else { + DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__); + upstream->tls_auth_failed = 1; SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } } else { @@ -898,7 +909,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) #endif /* Allow fallback from authenticated TLS if settings permit it (use NONE here?)*/ if (dnsreq->netreqs[0]->tls_auth_fallback_ok) - SSL_set_verify(ssl, SSL_VERIFY_NONE, _getdns_tls_verify_callback_with_fallback); + SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback); } SSL_set_connect_state(ssl); @@ -960,17 +971,13 @@ tls_do_handshake(getdns_upstream *upstream) } } upstream->tls_hs_state = GETDNS_HS_DONE; - /* TODO: Can we detect the authentication state of the connection here?*/ + r = SSL_get_verify_result(upstream->tls_obj); + if (r == X509_V_ERR_HOSTNAME_MISMATCH) + upstream->tls_auth_failed = 1; //#ifndef HAVE_SSL_HN_AUTH /*TODO: When OpenSSL 1.0.2 not available, use custom function to validate - the hostname.*/ - // X509* cert = SSL_get_peer_certificate(upstream->tls_obj); - // if(cert) { X509_free(cert); } /* Free immediately */ - // if(NULL == cert) return 0; - // if (!verify_cert_hostname(cert, upstream->tls_auth_name)) - // DEBUG_STUB("--- %s %s\n", __FUNCTION__, "Hostname verification failed: "); - // X509_free(cert); -//#endif + the hostname e.g. see libcurl:openssl.c:verifyhost() */ +//#endif /* Reset timeout on success*/ GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); upstream->event.read_cb = NULL; @@ -1517,7 +1524,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) @@ -1538,7 +1546,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; } @@ -1566,7 +1574,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]; @@ -1578,11 +1586,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; } From 28ffb2fdf61956973aa0a8b3a82691b1f5712d85 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Wed, 30 Sep 2015 14:03:15 +0100 Subject: [PATCH 4/7] Add ls_authentication to API --- src/const-info.c | 2 ++ src/context.c | 60 ++++++++++++++++++++++++++++------------- src/context.h | 5 ++-- src/getdns/getdns.h.in | 26 +++++++++++++++++- src/libgetdns.symbols | 1 + src/request-internal.c | 3 +-- src/stub.c | 19 ++++++++----- src/test/getdns_query.c | 21 ++++++++++++--- src/types-internal.h | 3 +-- 9 files changed, 103 insertions(+), 37 deletions(-) diff --git a/src/const-info.c b/src/const-info.c index 900989de..7555c156 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -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) diff --git a/src/context.c b/src/context.c index b5aca374..0d881be2 100644 --- a/src/context.c +++ b/src/context.c @@ -900,8 +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_req = 1; - result->tls_auth_fallback_ok = 1; + result->tls_auth = GETDNS_AUTHENTICATION_HOSTNAME; + result->tls_auth_min = GETDNS_AUTHENTICATION_HOSTNAME; result->limit_outstanding_queries = 0; result->return_dnssec_status = GETDNS_EXTENSION_FALSE; @@ -1262,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) @@ -1274,7 +1273,7 @@ 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); + dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_TRANSPORT); return GETDNS_RETURN_GOOD; } @@ -1423,6 +1422,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 */ @@ -2178,23 +2197,18 @@ _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) { + 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()); if(context->tls_ctx == NULL) return GETDNS_RETURN_BAD_CONTEXT; - /* Be strict and only use the cipher suites recommended in RFC7525 */ - 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 ((tls_only_is_in_transports_list(context) == 1) && context->tls_auth_req) - context->tls_auth_fallback_ok = 0; - /* TODO: If no auth data provided for any upstream, fail here */ - else - context->tls_auth_fallback_ok = 1; + // /* Be strict and only use the cipher suites recommended in RFC7525 */ + // 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; /* By default cert chain will be verified, but note that per connection management of the result and hostname verification is done.*/ SSL_CTX_set_verify(context->tls_ctx, SSL_VERIFY_PEER, _getdns_tls_verify_callback); @@ -2206,9 +2220,19 @@ _getdns_context_prepare_for_resolution(struct getdns_context *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) { + fprintf(stdout, "Setting auth min to HOSTNAME\n"); + 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; + fprintf(stdout, "Setting auth min to NONE\n"); } } + /* 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. */ diff --git a/src/context.h b/src/context.h index 5c16a6ff..8a205e4e 100644 --- a/src/context.h +++ b/src/context.h @@ -146,9 +146,8 @@ struct getdns_context { getdns_upstreams *upstreams; uint16_t limit_outstanding_queries; uint32_t dnssec_allowed_skew; - /*Make this a list*/ - size_t tls_auth_req; - size_t tls_auth_fallback_ok; /*Redundant but convinient*/ + 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; diff --git a/src/getdns/getdns.h.in b/src/getdns/getdns.h.in index 3f24250e..d75fb00a 100644 --- a/src/getdns/getdns.h.in +++ b/src/getdns/getdns.h.in @@ -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); diff --git a/src/libgetdns.symbols b/src/libgetdns.symbols index 3eb60c4a..c0241c31 100644 --- a/src/libgetdns.symbols +++ b/src/libgetdns.symbols @@ -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 diff --git a/src/request-internal.c b/src/request-internal.c index 42dce648..30156724 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -104,8 +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_req = owner->context->tls_auth_req; - net_req->tls_auth_fallback_ok = owner->context->tls_auth_fallback_ok; + 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; diff --git a/src/stub.c b/src/stub.c index a3c94d83..996cdc88 100644 --- a/src/stub.c +++ b/src/stub.c @@ -824,9 +824,9 @@ tls_failed(getdns_upstream *upstream) static int tls_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) { - return (netreq->tls_auth_req && - !netreq->tls_auth_fallback_ok && - upstream->tls_auth_failed) ? 0 : 1; + DEBUG_STUB("--- %s %d %d\n", __FUNCTION__, (int)netreq->tls_auth_min, (int)upstream->tls_auth_failed); + return (netreq->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME && + upstream->tls_auth_failed) ? 0 : 1; } int @@ -879,13 +879,15 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) /* Lack of host name is OK unless only authenticated TLS is specified*/ if (upstream->tls_auth_name[0] == '\0') { - if (!dnsreq->netreqs[0]->tls_auth_fallback_ok) { + 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; + /* TODO: Should we always enforce validation of the cert at least??*/ SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } } else { @@ -900,15 +902,15 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) X509_VERIFY_PARAM_set1_host(param, upstream->tls_auth_name, 0); #else /* TODO: Trigger post-handshake custom validation*/ - if (!dnsreq->netreqs[0]->tls_auth_fallback_ok) { + if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME) { 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 from authenticated TLS if settings permit it (use NONE here?)*/ - if (dnsreq->netreqs[0]->tls_auth_fallback_ok) + /* Allow fallback from authenticated TLS if settings permit it*/ + if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_NONE) SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback); } @@ -1118,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) { @@ -1672,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; diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 94942e94..8c1b2e5e 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -193,8 +193,10 @@ void my_eventloop_run_once(getdns_eventloop *loop, int blocking) tv.tv_sec = 0; tv.tv_usec = 0; } else { - tv.tv_sec = (timeout - now) / 1000000; + //tv.tv_sec = (timeout - now) / 1000000; + tv.tv_sec = 21474836; tv.tv_usec = (timeout - now) % 1000000; + //fprintf(stdout, "Using BIG tv: %" PRIu64 " %" PRIu64 ", %lu %d \n", timeout, now, tv.tv_sec, tv.tv_usec); } if (select(max_fd + 1, &readfds, &writefds, NULL, &tv) < 0) { perror("select() failed"); @@ -371,9 +373,11 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-a\tPerform asynchronous resolution " "(default = synchronous)\n"); fprintf(out, "\t-A\taddress lookup ( is ignored)\n"); + fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n"); fprintf(out, "\t-b \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 \tSet idle timeout in miliseconds\n"); fprintf(out, "\t-F \tread the queries from the specified file\n"); fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-H\thostname lookup. ( must be an IP address; is ignored)\n"); @@ -382,13 +386,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 is to verify hostname)\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 ( is ignored)\n"); fprintf(out, "\t-t \tSet timeout in miliseconds\n"); - fprintf(out, "\t-e \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 +404,7 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-U\tSet transport to UDP only\n"); fprintf(out, "\t-l \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 +700,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': diff --git a/src/types-internal.h b/src/types-internal.h index 9f0458eb..08b3acc2 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -198,8 +198,7 @@ typedef struct getdns_network_req getdns_transport_list_t transports[GETDNS_TRANSPORTS_MAX]; size_t transport_count; size_t transport_current; - size_t tls_auth_req; - size_t tls_auth_fallback_ok; + getdns_tls_authentication_t tls_auth_min; getdns_eventloop_event event; getdns_tcp_state tcp; uint16_t query_id; From 689447509a6e526f191a0d2ca25a56819d1f8220 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 16 Oct 2015 16:56:39 +0100 Subject: [PATCH 5/7] Change port used for TLS to 853 --- src/context.c | 18 +++++-------- src/stub.c | 74 +++++++++++++++++++++++++-------------------------- src/stub.h | 2 -- 3 files changed, 44 insertions(+), 50 deletions(-) diff --git a/src/context.c b/src/context.c index 0d881be2..dd21e304 100644 --- a/src/context.c +++ b/src/context.c @@ -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; @@ -2205,13 +2205,11 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); if(context->tls_ctx == NULL) return GETDNS_RETURN_BAD_CONTEXT; - // /* Be strict and only use the cipher suites recommended in RFC7525 */ - // 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; - /* By default cert chain will be verified, but note that per - connection management of the result and hostname verification is done.*/ - SSL_CTX_set_verify(context->tls_ctx, SSL_VERIFY_PEER, _getdns_tls_verify_callback); + /* 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 @@ -2223,13 +2221,11 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, } if (tls_only_is_in_transports_list(context) == 1 && context->tls_auth == GETDNS_AUTHENTICATION_HOSTNAME) { - fprintf(stdout, "Setting auth min to HOSTNAME\n"); 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; - fprintf(stdout, "Setting auth min to NONE\n"); } } diff --git a/src/stub.c b/src/stub.c index 996cdc88..6b85ccf8 100644 --- a/src/stub.c +++ b/src/stub.c @@ -563,7 +563,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 +590,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; @@ -830,13 +830,13 @@ tls_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) { } int -_getdns_tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) { +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*/ + /*Always proceed without changing result*/ return preverify_ok; } @@ -864,7 +864,6 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) if (context->tls_ctx == NULL) return NULL; SSL* ssl = SSL_new(context->tls_ctx); - if(!ssl) return NULL; /* Connect the SSL object with a file descriptor */ @@ -874,11 +873,38 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) } /* NOTE: this code will fallback on a given upstream, without trying - authentication on other upstreams first. This is non-optimal and is - an interim simplification. */ + authentication on other upstreams first. This is non-optimal and but avoids + multiple TLS handshakes before getting a usable connection. */ - /* Lack of host name is OK unless only authenticated TLS is specified*/ - if (upstream->tls_auth_name[0] == '\0') { + /* 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; @@ -887,31 +913,9 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) } else { DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__); upstream->tls_auth_failed = 1; - /* TODO: Should we always enforce validation of the cert at least??*/ - SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); - } - } else { - /*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); -#else - /* TODO: Trigger post-handshake custom validation*/ - if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME) { - 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 from authenticated TLS if settings permit it*/ - if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_NONE) 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); @@ -976,10 +980,6 @@ tls_do_handshake(getdns_upstream *upstream) r = SSL_get_verify_result(upstream->tls_obj); if (r == X509_V_ERR_HOSTNAME_MISMATCH) upstream->tls_auth_failed = 1; -//#ifndef HAVE_SSL_HN_AUTH - /*TODO: When OpenSSL 1.0.2 not available, use custom function to validate - the hostname e.g. see libcurl:openssl.c:verifyhost() */ -//#endif /* Reset timeout on success*/ GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); upstream->event.read_cb = NULL; diff --git a/src/stub.h b/src/stub.h index e10c39be..41aa629a 100644 --- a/src/stub.h +++ b/src/stub.h @@ -41,8 +41,6 @@ getdns_return_t _getdns_submit_stub_request(getdns_network_req *netreq); void _getdns_cancel_stub_request(getdns_network_req *netreq); -int _getdns_tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx); - #endif /* stub.h */ From b74c62066c5dead0cdf976232053250fdc407906 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 16 Oct 2015 18:31:57 +0100 Subject: [PATCH 6/7] Cleanup --- ChangeLog | 6 ++++++ Makefile.in | 3 --- README.md | 5 +++-- m4/acx_openssl.m4 | 2 +- src/Makefile.in | 3 --- src/context.c | 5 ++--- src/stub.c | 4 ++-- src/test/Makefile.in | 2 -- src/test/getdns_query.c | 6 ++---- src/test/tests_transports.sh | 12 +++++++----- 10 files changed, 23 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index f31cb691..c4569813 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/Makefile.in b/Makefile.in index 01e04555..93ef6946 100644 --- a/Makefile.in +++ b/Makefile.in @@ -91,9 +91,6 @@ doc: FORCE example: cd spec/example && $(MAKE) $@ -test_code: - cd src && $(MAKE) $@ - test: cd src && $(MAKE) $@ diff --git a/README.md b/README.md index 175f8aaf..0353a6d0 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,8 @@ 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 +227,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 ============ diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 index 4a567fd2..135131fb 100644 --- a/m4/acx_openssl.m4 +++ b/m4/acx_openssl.m4 @@ -112,7 +112,7 @@ AC_CHECK_LIB(ssl, TLSv1_2_client_method,AC_DEFINE([HAVE_TLS_v1_2], [1], 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. Native TLS hostname verification will not be available, custom code will be used.])]) + [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 diff --git a/src/Makefile.in b/src/Makefile.in index b7f81f60..d5b8badd 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -147,9 +147,6 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo libgetdns.la: $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols -test_code: FORCE - cd test && $(MAKE) $@ - test: FORCE cd test && $(MAKE) $@ diff --git a/src/context.c b/src/context.c index dd21e304..defe18e6 100644 --- a/src/context.c +++ b/src/context.c @@ -900,8 +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_HOSTNAME; - result->tls_auth_min = GETDNS_AUTHENTICATION_HOSTNAME; + 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; @@ -1273,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_DNS_TRANSPORT); return GETDNS_RETURN_GOOD; } diff --git a/src/stub.c b/src/stub.c index 6b85ccf8..c26d3b95 100644 --- a/src/stub.c +++ b/src/stub.c @@ -79,6 +79,7 @@ static void stub_timeout_cb(void *userarg); /* General utility functions */ /*****************************/ + static void rollover_secret() { @@ -824,7 +825,6 @@ tls_failed(getdns_upstream *upstream) static int tls_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) { - DEBUG_STUB("--- %s %d %d\n", __FUNCTION__, (int)netreq->tls_auth_min, (int)upstream->tls_auth_failed); return (netreq->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME && upstream->tls_auth_failed) ? 0 : 1; } @@ -1697,7 +1697,7 @@ find_upstream_for_netreq(getdns_network_req *netreq) netreq->transports[i], &fd); if (fd == -1 || !upstream) - continue; + continue; netreq->transport_current = i; netreq->upstream = upstream; return fd; diff --git a/src/test/Makefile.in b/src/test/Makefile.in index fb420392..d3fdc2c6 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -158,8 +158,6 @@ nolibldns: test: $(NOLIBCHECK) $(NOLIBLDNS) all -test_code: $(NOLIBCHECK) all - (cd $(srcdir)/../.. && find . -type f -executable -and \( -name "*.[ch]" -or -name "*.html" -or -name "*.in" -or -name "*.good" -or -name "*.ac" \) | awk 'BEGIN{e=0}{print("ERROR! Executable bit found on", $$0);e=1}END{exit(e)}') ./$(CHECK_GETDNS) if test $(have_libevent) = 1 ; then ./$(CHECK_EVENT_PROG) ; fi diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 8c1b2e5e..e131b271 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -193,10 +193,8 @@ void my_eventloop_run_once(getdns_eventloop *loop, int blocking) tv.tv_sec = 0; tv.tv_usec = 0; } else { - //tv.tv_sec = (timeout - now) / 1000000; - tv.tv_sec = 21474836; + tv.tv_sec = (timeout - now) / 1000000; tv.tv_usec = (timeout - now) % 1000000; - //fprintf(stdout, "Using BIG tv: %" PRIu64 " %" PRIu64 ", %lu %d \n", timeout, now, tv.tv_sec, tv.tv_usec); } if (select(max_fd + 1, &readfds, &writefds, NULL, &tv) < 0) { perror("select() failed"); @@ -386,7 +384,7 @@ 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 is to verify hostname)\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"); diff --git a/src/test/tests_transports.sh b/src/test/tests_transports.sh index ec75e7ab..15d31341 100755 --- a/src/test/tests_transports.sh +++ b/src/test/tests_transports.sh @@ -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" From 3be47edbb328c355cb2d458df3e104d468ddf67a Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 16 Oct 2015 18:40:33 +0100 Subject: [PATCH 7/7] More cleanup --- README.md | 3 +-- src/Makefile.in | 1 + src/test/Makefile.in | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0353a6d0..90a91ef3 100644 --- a/README.md +++ b/README.md @@ -87,8 +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.1 or later is required for TLS support, version 1.0.2 -or later is required for TLS hostname authentication) +* [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 diff --git a/src/Makefile.in b/src/Makefile.in index d5b8badd..470f6ff2 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -147,6 +147,7 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo libgetdns.la: $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols + test: FORCE cd test && $(MAKE) $@ diff --git a/src/test/Makefile.in b/src/test/Makefile.in index d3fdc2c6..cb07b954 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -157,7 +157,6 @@ nolibldns: @false test: $(NOLIBCHECK) $(NOLIBLDNS) all - (cd $(srcdir)/../.. && find . -type f -executable -and \( -name "*.[ch]" -or -name "*.html" -or -name "*.in" -or -name "*.good" -or -name "*.ac" \) | awk 'BEGIN{e=0}{print("ERROR! Executable bit found on", $$0);e=1}END{exit(e)}') ./$(CHECK_GETDNS) if test $(have_libevent) = 1 ; then ./$(CHECK_EVENT_PROG) ; fi