Add ls_authentication to API

This commit is contained in:
Sara Dickinson 2015-09-30 14:03:15 +01:00
parent 6b4ee4ed31
commit 28ffb2fdf6
9 changed files with 103 additions and 37 deletions

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

@ -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. */

View File

@ -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;

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,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;

View File

@ -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;

View File

@ -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 (<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 +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 (<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 +404,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 +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':

View File

@ -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;