diff --git a/configure.ac b/configure.ac index 8c161bbf..9ce45a81 100644 --- a/configure.ac +++ b/configure.ac @@ -418,7 +418,7 @@ AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_min_proto_version OpenSSL_version_num OpenSSL_version SSL_CTX_dane_enable SSL_dane_enable SSL_dane_tlsa_add X509_check_host X509_get_notAfter X509_get0_notAfter]) -AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set1_curves_list,SSL_set1_curves_list], [], [], [ +AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set1_curves_list,SSL_set1_curves_list,SSL_CTX_set_ciphersuites,SSL_set_ciphersuites], [], [], [ AC_INCLUDES_DEFAULT #ifdef HAVE_OPENSSL_ERR_H #include diff --git a/src/const-info.c b/src/const-info.c index 644676e6..b4dde28d 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -93,6 +93,7 @@ static struct const_info consts_info[] = { { 632, "GETDNS_CONTEXT_CODE_TLS_CA_FILE", GETDNS_CONTEXT_CODE_TLS_CA_FILE_TEXT }, { 633, "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT }, { 634, "GETDNS_CONTEXT_CODE_TLS_CURVES_LIST", GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT }, + { 635, "GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES", GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES_TEXT }, { 699, "GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE", GETDNS_CONTEXT_CODE_MAX_BACKOFF_VALUE_TEXT }, { 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT }, { 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT }, @@ -190,6 +191,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 }, { "GETDNS_CONTEXT_CODE_TLS_CA_FILE", 632 }, { "GETDNS_CONTEXT_CODE_TLS_CA_PATH", 631 }, + { "GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES", 635 }, { "GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST", 633 }, { "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 }, { "GETDNS_CONTEXT_CODE_TLS_CURVES_LIST", 634 }, diff --git a/src/context.c b/src/context.c index 56d827ee..322bfb5b 100644 --- a/src/context.c +++ b/src/context.c @@ -178,7 +178,7 @@ _getdns_strdup2(const struct mem_funcs *mfs, const getdns_bindata *s) return NULL; else { r[s->size] = '\0'; - return memcpy(r, s, s->size); + return memcpy(r, s->data, s->size); } } @@ -781,6 +781,8 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams) upstream->tls_pubkey_pinset = NULL; if (upstream->tls_cipher_list) GETDNS_FREE(upstreams->mf, upstream->tls_cipher_list); + if (upstream->tls_ciphersuites) + GETDNS_FREE(upstreams->mf, upstream->tls_ciphersuites); if (upstream->tls_curves_list) GETDNS_FREE(upstreams->mf, upstream->tls_curves_list); } @@ -1075,6 +1077,7 @@ upstream_init(getdns_upstream *upstream, upstream->tls_obj = NULL; upstream->tls_session = NULL; upstream->tls_cipher_list = NULL; + upstream->tls_ciphersuites = NULL; upstream->tls_curves_list = NULL; upstream->transport = GETDNS_TRANSPORT_TCP; upstream->tls_hs_state = GETDNS_HS_NONE; @@ -1478,8 +1481,11 @@ 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"; + "TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:" + "TLS13-CHACHA20-POLY1305-SHA256:EECDH+AESGCM:EECDH+CHACHA20"; + +static char const * const _getdns_default_tls_ciphersuites = + "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"; /* * getdns_context_create @@ -1589,6 +1595,7 @@ getdns_context_create_with_extended_memory_functions( result->tls_ca_path = NULL; result->tls_ca_file = NULL; result->tls_cipher_list = NULL; + result->tls_ciphersuites = NULL; result->tls_curves_list = NULL; (void) memset(&result->root_ksk, 0, sizeof(result->root_ksk)); @@ -1864,6 +1871,8 @@ getdns_context_destroy(struct getdns_context *context) GETDNS_FREE(context->mf, context->tls_ca_file); if (context->tls_cipher_list) GETDNS_FREE(context->mf, context->tls_cipher_list); + if (context->tls_ciphersuites) + GETDNS_FREE(context->mf, context->tls_ciphersuites); if (context->tls_curves_list) GETDNS_FREE(context->mf, context->tls_curves_list); @@ -3079,6 +3088,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context, if (dict && getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) { getdns_list *pubkey_pinset = NULL; getdns_bindata *tls_cipher_list = NULL; + getdns_bindata *tls_ciphersuites = NULL; getdns_bindata *tls_curves_list = NULL; if ((r = getdns_dict_get_bindata( @@ -3118,6 +3128,12 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context, ? _getdns_strdup2(&upstreams->mf , tls_cipher_list) : NULL; + (void) getdns_dict_get_bindata( + dict, "tls_ciphersuites", &tls_ciphersuites); + upstream->tls_ciphersuites = tls_ciphersuites + ? _getdns_strdup2(&upstreams->mf + , tls_ciphersuites) + : NULL; (void) getdns_dict_get_bindata( dict, "tls_curves_list", &tls_curves_list); if (tls_curves_list) { @@ -3713,7 +3729,12 @@ _getdns_context_prepare_for_resolution(getdns_context *context) context->tls_cipher_list ? context->tls_cipher_list : _getdns_default_tls_cipher_list)) return GETDNS_RETURN_BAD_CONTEXT; - +# if defined(HAVE_DECL_SSL_CTX_SET_CIPHERSUITES) && HAVE_DECL_SSL_CTX_SET_CIPHERSUITES + if (!SSL_CTX_set_ciphersuites(context->tls_ctx, + context->tls_ciphersuites ? context->tls_ciphersuites + : _getdns_default_tls_ciphersuites)) + return GETDNS_RETURN_BAD_CONTEXT; +# endif # if defined(HAVE_DECL_SSL_CTX_SET1_CURVES_LIST) && HAVE_DECL_SSL_CTX_SET1_CURVES_LIST if (context->tls_curves_list && !SSL_CTX_set1_curves_list(context->tls_ctx, context->tls_curves_list)) @@ -4058,6 +4079,8 @@ _get_context_settings(getdns_context* context) (void) getdns_dict_util_set_string(result, "tls_ca_file", 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); + if (!getdns_context_get_tls_ciphersuites(context, &str_value) && str_value) + (void) getdns_dict_util_set_string(result, "tls_ciphersuites", str_value); if (!getdns_context_get_tls_curves_list(context, &str_value) && str_value) (void) getdns_dict_util_set_string(result, "tls_curves_list", str_value); @@ -4668,6 +4691,11 @@ getdns_context_get_upstream_recursive_servers(getdns_context *context, d, "tls_cipher_list", upstream->tls_cipher_list); } + if (upstream->tls_ciphersuites) { + (void) getdns_dict_util_set_string( + d, "tls_ciphersuites", + upstream->tls_ciphersuites); + } if (upstream->tls_curves_list) { (void) getdns_dict_util_set_string( d, "tls_curves_list", @@ -4893,6 +4921,7 @@ _getdns_context_config_setting(getdns_context *context, CONTEXT_SETTING_STRING(tls_ca_path) CONTEXT_SETTING_STRING(tls_ca_file) CONTEXT_SETTING_STRING(tls_cipher_list) + CONTEXT_SETTING_STRING(tls_ciphersuites) CONTEXT_SETTING_STRING(tls_curves_list) /**************************************/ @@ -5491,6 +5520,35 @@ getdns_context_get_tls_cipher_list( return GETDNS_RETURN_GOOD; } +getdns_return_t +getdns_context_set_tls_ciphersuites( + getdns_context *context, const char *tls_ciphersuites) +{ + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; + if (context->tls_ciphersuites) + GETDNS_FREE(context->mf, context->tls_ciphersuites); + context->tls_ciphersuites = tls_ciphersuites + ? _getdns_strdup(&context->mf, tls_ciphersuites) + : NULL; + + dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES); + return GETDNS_RETURN_GOOD; +} + +getdns_return_t +getdns_context_get_tls_ciphersuites( + getdns_context *context, const char **tls_ciphersuites) +{ + if (!context || !tls_ciphersuites) + return GETDNS_RETURN_INVALID_PARAMETER; + + *tls_ciphersuites = context->tls_ciphersuites + ? context->tls_ciphersuites + : _getdns_default_tls_ciphersuites; + return GETDNS_RETURN_GOOD; +} + getdns_return_t getdns_context_set_tls_curves_list( getdns_context *context, const char *tls_curves_list) diff --git a/src/context.h b/src/context.h index 27dd2bee..5d453c7d 100644 --- a/src/context.h +++ b/src/context.h @@ -207,6 +207,7 @@ typedef struct getdns_upstream { getdns_auth_state_t tls_auth_state; unsigned tls_fallback_ok : 1; char *tls_cipher_list; + char *tls_ciphersuites; char *tls_curves_list; /* Auth credentials*/ char tls_auth_name[256]; @@ -350,6 +351,7 @@ struct getdns_context { char *tls_ca_path; char *tls_ca_file; char *tls_cipher_list; + char *tls_ciphersuites; char *tls_curves_list; getdns_upstreams *upstreams; diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 34282643..83db831f 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -102,6 +102,9 @@ extern "C" { #define GETDNS_CONTEXT_CODE_TLS_CIPHER_LIST_TEXT "Change related to getdns_context_set_tls_cipher_list" #define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST 634 #define GETDNS_CONTEXT_CODE_TLS_CURVES_LIST_TEXT "Change related to getdns_context_set_tls_curves_list" +#define GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES 635 +#define GETDNS_CONTEXT_CODE_TLS_CIPHERSUITES_TEXT "Change related to getdns_context_set_tls_ciphersuites" + /** @} */ @@ -755,6 +758,18 @@ getdns_return_t getdns_context_set_tls_cipher_list( getdns_context *context, const char *cipher_list); +/** + * Configure the available TLS1.3 ciphersuites for authenticated TLS upstreams. + * @see getdns_context_get_tls_ciphersuites + * @param[in] context The context to configure + * @param[in] ciphersuites 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_ciphersuites( + getdns_context *context, const char *ciphersuites); + /** * Sets the supported curves TLS upstreams. * @see getdns_context_get_tls_curves_list @@ -1287,6 +1302,19 @@ getdns_return_t getdns_context_get_tls_cipher_list( getdns_context *context, const char **cipher_list); +/** + * Get the configured available TLS1.3 ciphersuited for authenticated TLS + * upstreams. + * @see getdns_context_set_tls_ciphersuites + * @param[in] context The context configure + * @param[out] ciphersuites 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_ciphersuites( + getdns_context *context, const char **ciphersuites); + /** * Get the supported curves list if one has been set earlier. * @see getdns_context_set_tls_curves_list diff --git a/src/stub.c b/src/stub.c index 785d9f1f..d4861a53 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1006,11 +1006,24 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream) DEBUG_STUB("%s %-35s: WARNING: Using Oppotunistic TLS (fallback allowed)!\n", STUB_DEBUG_SETUP_TLS, __FUNC__); } else { - if (upstream->tls_cipher_list) - SSL_set_cipher_list(ssl, upstream->tls_cipher_list); + if (upstream->tls_cipher_list && + !SSL_set_cipher_list(ssl, upstream->tls_cipher_list)) + _getdns_upstream_log(upstream, + GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR, + "%-40s : Error configuring cipher_list\"%s\"\n", + upstream->addr_str, upstream->tls_cipher_list); + DEBUG_STUB("%s %-35s: Using Strict TLS \n", STUB_DEBUG_SETUP_TLS, __FUNC__); } +#if defined(HAVE_DECL_SSL_SET_CIPHERSUITES) && HAVE_DECL_SSL_SET_CIPHERSUITES + if (upstream->tls_ciphersuites && + !SSL_set_ciphersuites(ssl, upstream->tls_ciphersuites)) { + _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, + GETDNS_LOG_ERR, "%-40s : Error configuring ciphersuites " + "\"%s\"\n", upstream->addr_str, upstream->tls_ciphersuites); + } +#endif #if defined(HAVE_SSL_DANE_ENABLE) int osr; # if defined(STUB_DEBUG) && STUB_DEBUG