mirror of https://github.com/getdnsapi/getdns.git
DANE records can be passed along each upstream with "dane_records" key
Needs to be printed as well
This commit is contained in:
parent
544746094c
commit
03bddb40e1
|
@ -611,6 +611,8 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
|||
; upstreams->count--, upstream++ ) {
|
||||
|
||||
sha256_pin_t *pin = upstream->tls_pubkey_pinset;
|
||||
dane_record_t *dane_record = upstream->tls_dane_records;
|
||||
|
||||
if (upstream->loop && ( upstream->event.read_cb
|
||||
|| upstream->event.write_cb
|
||||
|| upstream->event.timeout_cb) ) {
|
||||
|
@ -652,6 +654,12 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
|||
pin = nextpin;
|
||||
}
|
||||
upstream->tls_pubkey_pinset = NULL;
|
||||
while (dane_record) {
|
||||
dane_record_t *next_dane_record = dane_record->next;
|
||||
GETDNS_FREE(upstreams->mf, dane_record);
|
||||
dane_record = next_dane_record;
|
||||
}
|
||||
upstream->tls_dane_records = NULL;
|
||||
if (upstream->tls_cipher_list)
|
||||
GETDNS_FREE(upstreams->mf, upstream->tls_cipher_list);
|
||||
if (upstream->tls_ciphersuites)
|
||||
|
@ -966,6 +974,7 @@ upstream_init(getdns_upstream *upstream,
|
|||
upstream->last_tls_auth_state = GETDNS_AUTH_NONE;
|
||||
upstream->best_tls_auth_state = GETDNS_AUTH_NONE;
|
||||
upstream->tls_pubkey_pinset = NULL;
|
||||
upstream->tls_dane_records = NULL;
|
||||
upstream->loop = NULL;
|
||||
(void) getdns_eventloop_event_init(
|
||||
&upstream->event, upstream, NULL, NULL, NULL);
|
||||
|
@ -2786,6 +2795,52 @@ getdns_context_set_dnssec_allowed_skew(struct getdns_context *context,
|
|||
return GETDNS_RETURN_GOOD;
|
||||
} /* getdns_context_set_dnssec_allowed_skew */
|
||||
|
||||
static getdns_return_t
|
||||
_getdns_list2dane_records(struct mem_funcs *mf, const getdns_list *dr_list,
|
||||
dane_record_t **tls_dane_records)
|
||||
{
|
||||
size_t i;
|
||||
getdns_return_t r;
|
||||
getdns_dict *dr_dict;
|
||||
|
||||
assert(tls_dane_records);
|
||||
|
||||
for (i = 0; !(r = getdns_list_get_dict(dr_list, i, &dr_dict)); i++) {
|
||||
uint32_t usage;
|
||||
uint32_t selector;
|
||||
uint32_t type;
|
||||
getdns_bindata *data;
|
||||
getdns_dict *rdata;
|
||||
dane_record_t *dane_record;
|
||||
|
||||
if (!getdns_dict_get_dict(dr_dict, "rdata", &rdata)) {
|
||||
/* only scan TLSA RRs */
|
||||
if (!getdns_dict_get_int(dr_dict, "type", &type)
|
||||
&& type != GETDNS_RRTYPE_TLSA)
|
||||
continue;
|
||||
dr_dict = rdata;
|
||||
}
|
||||
if ((r = getdns_dict_get_int(dr_dict, "certificate_usage", &usage))
|
||||
|| (r = getdns_dict_get_int(dr_dict, "selector", &selector))
|
||||
|| (r = getdns_dict_get_int(dr_dict, "matching_type", &type))
|
||||
|| (r = getdns_dict_get_bindata(dr_dict,
|
||||
"certificate_association_data", &data)))
|
||||
return r;
|
||||
|
||||
if (!(dane_record = (dane_record_t *)GETDNS_XMALLOC(
|
||||
*mf, uint8_t, sizeof(dane_record_t) + data->size)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
dane_record->next = *tls_dane_records;
|
||||
dane_record->usage = (uint8_t)usage;
|
||||
dane_record->selector = (uint8_t)selector;
|
||||
dane_record->type = (uint8_t)type;
|
||||
dane_record->size = data->size;
|
||||
memcpy(dane_record->data, data->data, data->size);
|
||||
*tls_dane_records = dane_record;
|
||||
}
|
||||
return r == GETDNS_RETURN_NO_SUCH_LIST_ITEM ? GETDNS_RETURN_GOOD : r;
|
||||
}
|
||||
|
||||
/*
|
||||
* getdns_context_set_upstream_recursive_servers
|
||||
*
|
||||
|
@ -2992,6 +3047,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
upstream->transport = getdns_upstream_transports[j];
|
||||
if (dict && getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) {
|
||||
getdns_list *pubkey_pinset = NULL;
|
||||
getdns_list *dane_records = NULL;
|
||||
getdns_bindata *tls_cipher_list = NULL;
|
||||
getdns_bindata *tls_ciphersuites = NULL;
|
||||
getdns_bindata *tls_curves_list = NULL;
|
||||
|
@ -3031,6 +3087,30 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
goto invalid_parameter;
|
||||
}
|
||||
}
|
||||
if (!(r = getdns_dict_get_list(
|
||||
dict, "dane_records", &dane_records))) {
|
||||
if ((r = _getdns_list2dane_records(
|
||||
&(upstreams->mf), dane_records,
|
||||
&(upstream->tls_dane_records)))) {
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAMS,
|
||||
GETDNS_LOG_ERR,
|
||||
"%-40s : Upstream : could"
|
||||
" not parse dane_records: "
|
||||
"%s\n", upstream->addr_str,
|
||||
getdns_get_errorstr_by_id(r));
|
||||
freeaddrinfo(ai);
|
||||
goto invalid_parameter;
|
||||
}
|
||||
} else if (r != GETDNS_RETURN_NO_SUCH_DICT_NAME)
|
||||
_getdns_upstream_log(upstream,
|
||||
GETDNS_LOG_UPSTREAMS,
|
||||
GETDNS_LOG_ERR,
|
||||
"%-40s : Upstream : could not "
|
||||
"get dane_records: %s\n",
|
||||
upstream->addr_str,
|
||||
getdns_get_errorstr_by_id(r));
|
||||
|
||||
(void) getdns_dict_get_bindata(
|
||||
dict, "tls_cipher_list", &tls_cipher_list);
|
||||
upstream->tls_cipher_list = tls_cipher_list
|
||||
|
|
|
@ -132,6 +132,16 @@ typedef struct sha256_pin {
|
|||
struct sha256_pin *next;
|
||||
} sha256_pin_t;
|
||||
|
||||
/* for doing DANE authentication of TLS-capable upstreams: */
|
||||
typedef struct dane_record {
|
||||
struct dane_record *next;
|
||||
uint8_t usage;
|
||||
uint8_t selector;
|
||||
uint8_t type;
|
||||
size_t size;
|
||||
uint8_t data[];
|
||||
} dane_record_t;
|
||||
|
||||
typedef struct getdns_upstream {
|
||||
/* backpointer to containing upstreams structure */
|
||||
struct getdns_upstreams *upstreams;
|
||||
|
@ -223,6 +233,7 @@ typedef struct getdns_upstream {
|
|||
/* Auth credentials */
|
||||
char tls_auth_name[256];
|
||||
sha256_pin_t *tls_pubkey_pinset;
|
||||
dane_record_t *tls_dane_records;
|
||||
|
||||
/* When requests have been scheduled asynchronously on an upstream
|
||||
* that is kept open, and a synchronous call is then done with the
|
||||
|
|
|
@ -584,6 +584,8 @@ typedef enum getdns_loglevel_type {
|
|||
#define GETDNS_LOG_INFO_TEXT "Informational message"
|
||||
#define GETDNS_LOG_DEBUG_TEXT "Debug-level message"
|
||||
|
||||
#define GETDNS_LOG_UPSTREAMS 0x1000
|
||||
#define GETDNS_LOG_UPSTREAMS_TEXT "Log messages about upstreams"
|
||||
#define GETDNS_LOG_UPSTREAM_STATS 0x3000
|
||||
#define GETDNS_LOG_UPSTREAM_STATS_TEXT "Log messages about upstream statistics"
|
||||
#define GETDNS_LOG_SYS_STUB 0x2000
|
||||
|
|
|
@ -995,6 +995,70 @@ getdns_return_t _getdns_tls_connection_set_host_pinset(_getdns_tls_connection* c
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t _getdns_tls_connection_set_dane_records(_getdns_tls_connection* conn, const char* auth_name, const dane_record_t* dane_records)
|
||||
{
|
||||
if (!conn || !conn->ssl || !auth_name)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
#if 0 && defined(USE_DANESSL)
|
||||
/* Stash auth name and pinset away for use in cert verification. */
|
||||
conn->auth_name = auth_name;
|
||||
conn->dane_records = dane_records;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SSL_DANE_ENABLE)
|
||||
int osr = SSL_dane_enable(conn->ssl, *auth_name ? auth_name : NULL);
|
||||
(void) osr; /* unused parameter */
|
||||
DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_enable(\"%s\") -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, auth_name, osr);
|
||||
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok);
|
||||
const dane_record_t *dane_p;
|
||||
size_t n_records= 0;
|
||||
for (dane_p = dane_records; dane_p; dane_p = dane_p->next) {
|
||||
osr = SSL_dane_tlsa_add(conn->ssl, dane_p->usage,
|
||||
dane_p->selector, dane_p->type, dane_p->data, dane_p->size);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: SSL_dane_tlsa_add() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
if (osr > 0)
|
||||
++n_records;
|
||||
}
|
||||
#elif 0 && defined(USE_DANESSL)
|
||||
conn->pinset = pinset;
|
||||
if (pinset) {
|
||||
const char *auth_names[2] = { auth_name, NULL };
|
||||
int osr = DANESSL_init(conn->ssl,
|
||||
*auth_name ? auth_name : NULL,
|
||||
*auth_name ? auth_names : NULL);
|
||||
(void) osr; /* unused parameter */
|
||||
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_init(\"%s\") -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, auth_name, osr);
|
||||
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok);
|
||||
const sha256_pin_t *pin_p;
|
||||
size_t n_pins = 0;
|
||||
for (pin_p = pinset; pin_p; pin_p = pin_p->next) {
|
||||
osr = DANESSL_add_tlsa(conn->ssl, 3, 1, "sha256",
|
||||
(unsigned char *)pin_p->pin, SHA256_DIGEST_LENGTH);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_add_tlsa() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
if (osr > 0)
|
||||
++n_pins;
|
||||
osr = DANESSL_add_tlsa(conn->ssl, 2, 1, "sha256",
|
||||
(unsigned char *)pin_p->pin, SHA256_DIGEST_LENGTH);
|
||||
DEBUG_STUB("%s %-35s: DEBUG: DANESSL_add_tlsa() -> %d\n"
|
||||
, STUB_DEBUG_SETUP_TLS, __FUNC__, osr);
|
||||
if (osr > 0)
|
||||
++n_pins;
|
||||
}
|
||||
} else {
|
||||
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, _getdns_tls_verify_always_ok);
|
||||
}
|
||||
#else
|
||||
#error Must have either DANE SSL or OpenSSL v1.1.
|
||||
#endif
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
|
||||
getdns_return_t _getdns_tls_connection_certificate_verify(_getdns_tls_connection* conn, long* errnum, const char** errmsg)
|
||||
{
|
||||
if (!conn || !conn->ssl)
|
||||
|
|
|
@ -1049,8 +1049,9 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
/* Lack of host name is OK unless only authenticated
|
||||
* TLS is specified and we have no pubkey_pinset */
|
||||
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) {
|
||||
if (upstream->tls_pubkey_pinset) {
|
||||
DEBUG_STUB("%s %-35s: Proceeding with only pubkey pinning authentication\n",
|
||||
if (upstream->tls_pubkey_pinset
|
||||
|| upstream->tls_dane_records) {
|
||||
DEBUG_STUB("%s %-35s: Proceeding with only pubkey pinning and/or DANE authentication\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
} else {
|
||||
DEBUG_STUB("%s %-35s: ERROR:No auth name or pinset provided for this upstream for Strict TLS authentication\n",
|
||||
|
@ -1075,6 +1076,10 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
_getdns_tls_connection_set_host_pinset(
|
||||
tls, upstream->tls_auth_name, upstream->tls_pubkey_pinset);
|
||||
|
||||
if (upstream->tls_dane_records)
|
||||
_getdns_tls_connection_set_dane_records(
|
||||
tls, upstream->tls_auth_name, upstream->tls_dane_records);
|
||||
|
||||
/* Session resumption. There are trade-offs here. Want to do it when
|
||||
possible only if we have the right type of connection. Note a change
|
||||
to the upstream auth info creates a new upstream so never re-uses.*/
|
||||
|
|
12
src/tls.h
12
src/tls.h
|
@ -43,6 +43,7 @@
|
|||
/* Forward declare type. */
|
||||
struct sha256_pin;
|
||||
struct getdns_log_config;
|
||||
struct dane_record;
|
||||
|
||||
/* Additional return codes required by TLS abstraction. Internal use only. */
|
||||
#define GETDNS_RETURN_TLS_WANT_READ ((getdns_return_t) 420)
|
||||
|
@ -332,6 +333,17 @@ getdns_return_t _getdns_tls_connection_setup_hostname_auth(_getdns_tls_connectio
|
|||
*/
|
||||
getdns_return_t _getdns_tls_connection_set_host_pinset(_getdns_tls_connection* conn, const char* auth_name, const struct sha256_pin* pinset);
|
||||
|
||||
/**
|
||||
* Set host pinset.
|
||||
*
|
||||
* @param conn the connection.
|
||||
* @param auth_name the hostname.
|
||||
* @param dane_records the DANE records that must match.
|
||||
* @return GETDNS_RETURN_GOOD if all OK.
|
||||
* @return GETDNS_RETURN_INVALID_PARAMETER if conn is null or has no SSL.
|
||||
*/
|
||||
getdns_return_t _getdns_tls_connection_set_dane_records(_getdns_tls_connection* conn, const char* auth_name, const struct dane_record* dane_records);
|
||||
|
||||
/**
|
||||
* Get result of certificate verification.
|
||||
*
|
||||
|
|
2
stubby
2
stubby
|
@ -1 +1 @@
|
|||
Subproject commit 3d5632852826736b14a5b86b6f19117f7bce97da
|
||||
Subproject commit a550394f874817bd5fda022c34c0c96e7f819bc2
|
Loading…
Reference in New Issue