mirror of https://github.com/getdnsapi/getdns.git
Add ls_authentication to API
This commit is contained in:
parent
6b4ee4ed31
commit
28ffb2fdf6
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
19
src/stub.c
19
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;
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue