mirror of https://github.com/getdnsapi/getdns.git
Merge pull request #367 from getdnsapi/features/set_cipher_list
Features/set cipher list
This commit is contained in:
commit
f173f4667f
|
@ -1,4 +1,9 @@
|
|||
* 2017-12-??: Version 1.3.0
|
||||
* Specify default available cipher suites for authenticated TLS
|
||||
upstreams with getdns_context_set_tls_ciphers_list()
|
||||
An upstream specific available cipher suite may also be given
|
||||
with the tls_cipher_list setting in the upstream dict with
|
||||
getdns_context_set_upstream_recursive_servers()
|
||||
* PR #366: Add support for TLS 1.3 and Chacha20-Poly1305
|
||||
Thanks Pascal Ernster
|
||||
* Bugfix #356: Do Zero configuration DNSSEC meta queries over on the
|
||||
|
|
|
@ -91,6 +91,7 @@ static struct const_info consts_info[] = {
|
|||
{ 630, "GETDNS_CONTEXT_CODE_HOSTS", GETDNS_CONTEXT_CODE_HOSTS_TEXT },
|
||||
{ 631, "GETDNS_CONTEXT_CODE_CAPATH", GETDNS_CONTEXT_CODE_CAPATH_TEXT },
|
||||
{ 632, "GETDNS_CONTEXT_CODE_CAFILE", GETDNS_CONTEXT_CODE_CAFILE_TEXT },
|
||||
{ 633, "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT },
|
||||
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
|
||||
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
|
||||
{ 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
|
||||
|
@ -186,6 +187,7 @@ static struct const_name_info consts_name_info[] = {
|
|||
{ "GETDNS_CONTEXT_CODE_TIMEOUT", 616 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", 633 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 },
|
||||
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
|
||||
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", 625 },
|
||||
|
|
|
@ -165,6 +165,17 @@ static void set_ub_dnssec_allowed_skew(struct getdns_context*, uint32_t);
|
|||
/* Stuff to make it compile pedantically */
|
||||
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
|
||||
|
||||
static char *
|
||||
_getdns_strdup2(const struct mem_funcs *mfs, const getdns_bindata *s)
|
||||
{
|
||||
char *r;
|
||||
if (!s || !(r = GETDNS_XMALLOC(*mfs, char, s->size + 1)))
|
||||
return NULL;
|
||||
else {
|
||||
r[s->size] = '\0';
|
||||
return memcpy(r, s, s->size);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
/* For windows, the CA trust store is not read by openssl.
|
||||
|
@ -723,6 +734,8 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
|||
pin = nextpin;
|
||||
}
|
||||
upstream->tls_pubkey_pinset = NULL;
|
||||
if (upstream->tls_cipher_list)
|
||||
GETDNS_FREE(upstreams->mf, upstream->tls_cipher_list);
|
||||
}
|
||||
GETDNS_FREE(upstreams->mf, upstreams);
|
||||
}
|
||||
|
@ -1006,6 +1019,7 @@ upstream_init(getdns_upstream *upstream,
|
|||
upstream->fd = -1;
|
||||
upstream->tls_obj = NULL;
|
||||
upstream->tls_session = NULL;
|
||||
upstream->tls_cipher_list = NULL;
|
||||
upstream->transport = GETDNS_TRANSPORT_TCP;
|
||||
upstream->tls_hs_state = GETDNS_HS_NONE;
|
||||
upstream->tls_auth_name[0] = '\0';
|
||||
|
@ -1377,11 +1391,11 @@ static void _getdns_check_expired_pending_netreqs_cb(void *arg)
|
|||
_getdns_check_expired_pending_netreqs((getdns_context *)arg, &now_ms);
|
||||
}
|
||||
|
||||
static const char *_getdns_default_trust_anchors_url =
|
||||
static char const * const _getdns_default_trust_anchors_url =
|
||||
"http://data.iana.org/root-anchors/root-anchors.xml";
|
||||
|
||||
/* The ICANN CA fetched at 24 Sep 2010. Valid to 2028 */
|
||||
static const char *_getdns_default_trust_anchors_verify_CA =
|
||||
static char const * const _getdns_default_trust_anchors_verify_CA =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
|
||||
"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
|
||||
|
@ -1404,9 +1418,12 @@ static const char *_getdns_default_trust_anchors_verify_CA =
|
|||
"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
static const char *_getdns_default_trust_anchors_verify_email =
|
||||
static char const * const _getdns_default_trust_anchors_verify_email =
|
||||
"dnssec@iana.org";
|
||||
|
||||
static char const * const _getdns_default_tls_cipher_list =
|
||||
"TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:"
|
||||
"TLS13-CHACHA20-POLY1305-SHA256:EECDH+AESGCM:EECDH+CHACHA20";
|
||||
|
||||
/*
|
||||
* getdns_context_create
|
||||
|
@ -1515,6 +1532,7 @@ getdns_context_create_with_extended_memory_functions(
|
|||
result->appdata_dir = NULL;
|
||||
result->CApath = NULL;
|
||||
result->CAfile = NULL;
|
||||
result->tls_cipher_list = NULL;
|
||||
|
||||
(void) memset(&result->root_ksk, 0, sizeof(result->root_ksk));
|
||||
|
||||
|
@ -1783,7 +1801,8 @@ getdns_context_destroy(struct getdns_context *context)
|
|||
GETDNS_FREE(context->mf, context->CApath);
|
||||
if (context->CAfile)
|
||||
GETDNS_FREE(context->mf, context->CAfile);
|
||||
|
||||
if (context->tls_cipher_list)
|
||||
GETDNS_FREE(context->mf, context->tls_cipher_list);
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
|
@ -2972,16 +2991,19 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
upstream->addr.ss_family = addr.ss_family;
|
||||
upstream_init(upstream, upstreams, ai);
|
||||
upstream->transport = getdns_upstream_transports[j];
|
||||
if (getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) {
|
||||
if (dict && getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) {
|
||||
getdns_list *pubkey_pinset = NULL;
|
||||
if (dict && (r = getdns_dict_get_bindata(
|
||||
getdns_bindata *tls_cipher_list = NULL;
|
||||
|
||||
if ((r = getdns_dict_get_bindata(
|
||||
dict, "tls_auth_name", &tls_auth_name)) == GETDNS_RETURN_GOOD) {
|
||||
|
||||
if (tls_auth_name->size >= sizeof(upstream->tls_auth_name)) {
|
||||
/* tls_auth_name's are just
|
||||
* domain names and should
|
||||
* thus not be larger than 256
|
||||
* bytes.
|
||||
/* tls_auth_name's are
|
||||
* domain names in presentation
|
||||
* format and, taking escaping
|
||||
* into account, should not
|
||||
* be larger than 1024 bytes.
|
||||
*/
|
||||
goto invalid_parameter;
|
||||
}
|
||||
|
@ -2991,7 +3013,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
upstream->tls_auth_name
|
||||
[tls_auth_name->size] = '\0';
|
||||
}
|
||||
if (dict && (r = getdns_dict_get_list(dict, "tls_pubkey_pinset",
|
||||
if ((r = getdns_dict_get_list(dict, "tls_pubkey_pinset",
|
||||
&pubkey_pinset)) == GETDNS_RETURN_GOOD) {
|
||||
/* TODO: what if the user supplies tls_pubkey_pinset with
|
||||
* something other than a list? */
|
||||
|
@ -3001,6 +3023,12 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
if (r != GETDNS_RETURN_GOOD)
|
||||
goto invalid_parameter;
|
||||
}
|
||||
(void) getdns_dict_get_bindata(
|
||||
dict, "tls_cipher_list", &tls_cipher_list);
|
||||
upstream->tls_cipher_list = tls_cipher_list
|
||||
? _getdns_strdup2(&upstreams->mf
|
||||
, tls_cipher_list)
|
||||
: NULL;
|
||||
}
|
||||
if ((upstream->tsig_alg = tsig_alg)) {
|
||||
if (tsig_name) {
|
||||
|
@ -3574,8 +3602,9 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
|
|||
# endif
|
||||
/* Be strict and only use the cipher suites recommended in RFC7525
|
||||
Unless we later fallback to opportunistic. */
|
||||
const char* const PREFERRED_CIPHERS = "TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:EECDH+AESGCM:EECDH+CHACHA20";
|
||||
if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS))
|
||||
if (!SSL_CTX_set_cipher_list(context->tls_ctx,
|
||||
context->tls_cipher_list ? context->tls_cipher_list
|
||||
: _getdns_default_tls_cipher_list))
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
/* For strict authentication, we must have local root certs available
|
||||
Set up is done only when the tls_ctx is created (per getdns_context)*/
|
||||
|
@ -3625,7 +3654,7 @@ _getdns_context_prepare_for_resolution(getdns_context *context)
|
|||
return r;
|
||||
} /* _getdns_context_prepare_for_resolution */
|
||||
|
||||
char *
|
||||
static char *
|
||||
_getdns_strdup(const struct mem_funcs *mfs, const char *s)
|
||||
{
|
||||
size_t sz;
|
||||
|
@ -3891,6 +3920,8 @@ _get_context_settings(getdns_context* context)
|
|||
(void) getdns_dict_util_set_string(result, "CApath", str_value);
|
||||
if (!getdns_context_get_CAfile(context, &str_value) && str_value)
|
||||
(void) getdns_dict_util_set_string(result, "CAfile", str_value);
|
||||
if (!getdns_context_get_tls_cipher_list(context, &str_value) && str_value)
|
||||
(void) getdns_dict_util_set_string(result, "tls_cipher_list", str_value);
|
||||
|
||||
/* Default settings for extensions */
|
||||
(void)getdns_dict_set_int(
|
||||
|
@ -4475,6 +4506,11 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context,
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (upstream->tls_cipher_list) {
|
||||
(void) getdns_dict_util_set_string(
|
||||
d, "tls_cipher_list",
|
||||
upstream->tls_cipher_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!r)
|
||||
|
@ -4683,6 +4719,7 @@ _getdns_context_config_setting(getdns_context *context,
|
|||
CONTEXT_SETTING_STRING(hosts)
|
||||
CONTEXT_SETTING_STRING(CApath)
|
||||
CONTEXT_SETTING_STRING(CAfile)
|
||||
CONTEXT_SETTING_STRING(tls_cipher_list)
|
||||
|
||||
/**************************************/
|
||||
/**** ****/
|
||||
|
@ -5233,4 +5270,34 @@ getdns_context_get_CAfile(getdns_context *context, const char **CAfile)
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_cipher_list(
|
||||
getdns_context *context, const char *tls_cipher_list)
|
||||
{
|
||||
if (!context)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
if (context->tls_cipher_list)
|
||||
GETDNS_FREE(context->mf, context->tls_cipher_list);
|
||||
context->tls_cipher_list = tls_cipher_list
|
||||
? _getdns_strdup(&context->mf, tls_cipher_list)
|
||||
: NULL;
|
||||
|
||||
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_cipher_list(
|
||||
getdns_context *context, const char **tls_cipher_list)
|
||||
{
|
||||
if (!context || !tls_cipher_list)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
*tls_cipher_list = context->tls_cipher_list
|
||||
? context->tls_cipher_list
|
||||
: _getdns_default_tls_cipher_list;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/* context.c */
|
||||
|
|
|
@ -205,6 +205,7 @@ typedef struct getdns_upstream {
|
|||
getdns_tls_hs_state_t tls_hs_state;
|
||||
getdns_auth_state_t tls_auth_state;
|
||||
unsigned tls_fallback_ok : 1;
|
||||
char *tls_cipher_list;
|
||||
/* Auth credentials*/
|
||||
char tls_auth_name[256];
|
||||
sha256_pin_t *tls_pubkey_pinset;
|
||||
|
@ -345,6 +346,7 @@ struct getdns_context {
|
|||
|
||||
char *CApath;
|
||||
char *CAfile;
|
||||
char *tls_cipher_list;
|
||||
|
||||
getdns_upstreams *upstreams;
|
||||
uint16_t limit_outstanding_queries;
|
||||
|
@ -527,8 +529,6 @@ void _getdns_context_cancel_request(getdns_dns_req *dnsreq);
|
|||
*/
|
||||
void _getdns_context_request_timed_out(getdns_dns_req *dnsreq);
|
||||
|
||||
char *_getdns_strdup(const struct mem_funcs *mfs, const char *str);
|
||||
|
||||
struct getdns_bindata *_getdns_bindata_copy(
|
||||
struct mem_funcs *mfs, size_t size, const uint8_t *data);
|
||||
|
||||
|
|
|
@ -1687,6 +1687,8 @@ getdns_context_set_dnssec_allowed_skew(getdns_context *context,
|
|||
* - `value` A SHA256 hash of the `SubjectPublicKeyInfo`
|
||||
* of the upstream, which will be used to authenticate
|
||||
* it.
|
||||
* - `tls_cipher_list` (a bindata) that is the string
|
||||
* of available ciphers specific for this upstream.
|
||||
* @return GETDNS_RETURN_GOOD when successful.
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when `context` or `upstream_list` was `NULL`
|
||||
* @return GETDNS_RETURN_CONTEXT_UPDATE_FAIL when there were problems parsing
|
||||
|
|
|
@ -98,6 +98,8 @@ extern "C" {
|
|||
#define GETDNS_CONTEXT_CODE_CAPATH_TEXT "Change related to getdns_context_set_CApath"
|
||||
#define GETDNS_CONTEXT_CODE_CAFILE 632
|
||||
#define GETDNS_CONTEXT_CODE_CAFILE_TEXT "Change related to getdns_context_set_CAfile"
|
||||
#define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST 633
|
||||
#define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT "Change related to getdns_context_set_tls_cipher_list"
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
@ -739,6 +741,18 @@ getdns_context_set_CApath(getdns_context *context, const char *CApath);
|
|||
getdns_return_t
|
||||
getdns_context_set_CAfile(getdns_context *context, const char *CAfile);
|
||||
|
||||
/**
|
||||
* Sets the list of available ciphers for authenticated TLS upstreams.
|
||||
* @see getdns_context_get_tls_cipher_list
|
||||
* @param[in] context The context to configure
|
||||
* @param[in] cipher_list The cipher list
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_set_tls_cipher_list(
|
||||
getdns_context *context, const char *cipher_list);
|
||||
|
||||
/**
|
||||
* Get the current resolution type setting from this context.
|
||||
* @see getdns_context_set_resolution_type
|
||||
|
@ -1246,6 +1260,19 @@ getdns_context_get_CApath(getdns_context *context, const char **CApath);
|
|||
getdns_return_t
|
||||
getdns_context_get_CAfile(getdns_context *context, const char **CAfile);
|
||||
|
||||
/**
|
||||
* Get the list of available ciphers for authenticated TLS upstreams.
|
||||
* @see getdns_context_set_tls_cipher_list
|
||||
* @param[in] context The context configure
|
||||
* @param[out] cipher_list The cipher list
|
||||
* @return GETDNS_RETURN_GOOD when successful
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_context_get_tls_cipher_list(
|
||||
getdns_context *context, const char **cipher_list);
|
||||
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ getdns_context_get_suffix
|
|||
getdns_context_get_timeout
|
||||
getdns_context_get_tls_authentication
|
||||
getdns_context_get_tls_backoff_time
|
||||
getdns_context_get_tls_cipher_list
|
||||
getdns_context_get_tls_connection_retries
|
||||
getdns_context_get_tls_query_padding_blocksize
|
||||
getdns_context_get_trust_anchors_url
|
||||
|
@ -77,6 +78,7 @@ getdns_context_set_suffix
|
|||
getdns_context_set_timeout
|
||||
getdns_context_set_tls_authentication
|
||||
getdns_context_set_tls_backoff_time
|
||||
getdns_context_set_tls_cipher_list
|
||||
getdns_context_set_tls_connection_retries
|
||||
getdns_context_set_tls_query_padding_blocksize
|
||||
getdns_context_set_trust_anchors_url
|
||||
|
|
|
@ -986,9 +986,12 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
SSL_set_cipher_list(ssl, "DEFAULT");
|
||||
DEBUG_STUB("%s %-35s: WARNING: Using Oppotunistic TLS (fallback allowed)!\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
} else
|
||||
} else {
|
||||
if (upstream->tls_cipher_list)
|
||||
SSL_set_cipher_list(ssl, upstream->tls_cipher_list);
|
||||
DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS,
|
||||
__FUNC__);
|
||||
}
|
||||
SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
|
||||
|
||||
SSL_set_connect_state(ssl);
|
||||
|
|
Loading…
Reference in New Issue