mirror of https://github.com/getdnsapi/getdns.git
--enable-broken-native-stub-dnssec
Still needs a little more work for wildcards and NODATA answers...
This commit is contained in:
parent
59c92b884c
commit
fa782d1043
|
@ -754,6 +754,7 @@ with_sysroot
|
|||
enable_libtool_lock
|
||||
enable_rpath
|
||||
enable_tcp_fastopen
|
||||
enable_broken_native_stub_dnssec
|
||||
with_libidn
|
||||
with_libldns
|
||||
with_libunbound
|
||||
|
@ -1396,6 +1397,9 @@ Optional Features:
|
|||
--disable-libtool-lock avoid locking (might break parallel builds)
|
||||
--disable-rpath disable hardcoded rpath (default=enabled)
|
||||
--enable-tcp-fastopen Enable TCP Fast Open
|
||||
--enable-broken-native-stub-dnssec
|
||||
Enable very experimental and broken native stub
|
||||
DNSSEC support
|
||||
|
||||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
|
@ -11186,6 +11190,24 @@ _ACEOF
|
|||
;;
|
||||
esac
|
||||
|
||||
# Check whether --enable-broken-native-stub-dnssec was given.
|
||||
if test "${enable_broken_native_stub_dnssec+set}" = set; then :
|
||||
enableval=$enable_broken_native_stub_dnssec;
|
||||
fi
|
||||
|
||||
case "$enable_broken_native_stub_dnssec" in
|
||||
yes)
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define STUB_NATIVE_DNSSEC 1
|
||||
_ACEOF
|
||||
|
||||
;;
|
||||
no|*)
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# search to set include and library paths right
|
||||
# find libidn
|
||||
|
||||
|
|
10
configure.ac
10
configure.ac
|
@ -131,6 +131,16 @@ case "$enable_tcp_fastopen" in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(broken-native-stub-dnssec, AC_HELP_STRING([--enable-broken-native-stub-dnssec], [Enable very experimental and broken native stub DNSSEC support]))
|
||||
case "$enable_broken_native_stub_dnssec" in
|
||||
yes)
|
||||
AC_DEFINE_UNQUOTED([STUB_NATIVE_DNSSEC], [1], [Define this to enable the very experimental and broken native stub DNSSEC support.])
|
||||
;;
|
||||
no|*)
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# search to set include and library paths right
|
||||
# find libidn
|
||||
AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
|
||||
|
|
|
@ -130,6 +130,10 @@
|
|||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define this to enable the very experimental and broken native stub DNSSEC
|
||||
support. */
|
||||
#undef STUB_NATIVE_DNSSEC
|
||||
|
||||
/* System configuration dir */
|
||||
#undef SYSCONFDIR
|
||||
|
||||
|
|
208
src/dnssec.c
208
src/dnssec.c
|
@ -79,6 +79,57 @@ static void launch_chain_link_lookup(struct validation_chain *chain,
|
|||
priv_getdns_rdf_iter *rdf_dname);
|
||||
static void destroy_chain(struct validation_chain *chain);
|
||||
|
||||
#ifdef STUB_NATIVE_DNSSEC
|
||||
static void
|
||||
native_stub_validate_dnssec(getdns_dns_req *dns_req, getdns_list *support)
|
||||
{
|
||||
getdns_network_req *netreq, **netreq_p;
|
||||
getdns_list *trust_anchors;
|
||||
getdns_dict *reply = NULL;
|
||||
getdns_dict *header;
|
||||
getdns_list *to_validate;
|
||||
uint32_t rcode;
|
||||
|
||||
if (!(trust_anchors = getdns_root_trust_anchor(NULL)))
|
||||
return;
|
||||
|
||||
for (netreq_p = dns_req->netreqs; (netreq = *netreq_p) ; netreq_p++) {
|
||||
if (!(reply = priv_getdns_create_reply_dict(dns_req->context,
|
||||
netreq, NULL, NULL)))
|
||||
continue;
|
||||
if (getdns_dict_get_dict(reply, "header", &header))
|
||||
break;
|
||||
if (getdns_dict_get_int(header, "rcode", &rcode))
|
||||
break;
|
||||
if (rcode == GETDNS_RCODE_NXDOMAIN) {
|
||||
if (getdns_dict_get_list(
|
||||
reply, "authority", &to_validate))
|
||||
break;
|
||||
} else if (getdns_dict_get_list(reply, "answer", &to_validate))
|
||||
break;
|
||||
switch ((int)getdns_validate_dnssec(
|
||||
to_validate, support, trust_anchors)) {
|
||||
case GETDNS_DNSSEC_SECURE:
|
||||
netreq->secure = 1;
|
||||
netreq->bogus = 0;
|
||||
break;
|
||||
case GETDNS_DNSSEC_BOGUS:
|
||||
netreq->secure = 0;
|
||||
netreq->bogus = 1;
|
||||
break;
|
||||
default:
|
||||
/* GETDNS_DNSSEC_INSECURE */
|
||||
netreq->secure = 0;
|
||||
netreq->bogus = 0;
|
||||
break;
|
||||
}
|
||||
getdns_dict_destroy(reply);
|
||||
reply = NULL;
|
||||
}
|
||||
getdns_dict_destroy(reply);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void callback_on_complete_chain(struct validation_chain *chain)
|
||||
{
|
||||
getdns_context *context = chain->dns_req->context;
|
||||
|
@ -101,10 +152,9 @@ static void callback_on_complete_chain(struct validation_chain *chain)
|
|||
if (ongoing > 0)
|
||||
return;
|
||||
|
||||
if (!(response = create_getdns_response(chain->dns_req)) ||
|
||||
!(keys = getdns_list_create_with_context(context))) {
|
||||
|
||||
priv_getdns_call_user_callback(chain->dns_req, response);
|
||||
if (!(keys = getdns_list_create_with_context(context))) {
|
||||
priv_getdns_call_user_callback(chain->dns_req,
|
||||
create_getdns_response(chain->dns_req));
|
||||
destroy_chain(chain);
|
||||
return;
|
||||
}
|
||||
|
@ -117,7 +167,13 @@ static void callback_on_complete_chain(struct validation_chain *chain)
|
|||
, i, &rr_dict); i++)
|
||||
(void) getdns_list_append_dict(keys, rr_dict);
|
||||
}
|
||||
(void) getdns_dict_set_list(response, "validation_chain", keys);
|
||||
#ifdef STUB_NATIVE_DNSSEC
|
||||
native_stub_validate_dnssec(chain->dns_req, keys);
|
||||
#endif
|
||||
if ((response = create_getdns_response(chain->dns_req)) &&
|
||||
chain->dns_req->dnssec_return_validation_chain) {
|
||||
(void)getdns_dict_set_list(response, "validation_chain", keys);
|
||||
}
|
||||
getdns_list_destroy(keys);
|
||||
priv_getdns_call_user_callback(chain->dns_req, response);
|
||||
destroy_chain(chain);
|
||||
|
@ -385,6 +441,82 @@ priv_getdns_rr_list_from_list(struct getdns_list *list, ldns_rr_list **rr_list)
|
|||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
priv_getdns_rr_dict_with_compressed_names(getdns_dict *rr_dict)
|
||||
{
|
||||
uint32_t rr_type;
|
||||
getdns_dict *rdata;
|
||||
|
||||
if (getdns_dict_get_int(rr_dict, "type", &rr_type))
|
||||
return 0;
|
||||
if (rr_type == GETDNS_RRTYPE_RRSIG) {
|
||||
if (getdns_dict_get_dict(rr_dict, "rdata", &rdata))
|
||||
return 0;
|
||||
if (getdns_dict_get_int(rdata, "type_covered", &rr_type))
|
||||
return 0;
|
||||
}
|
||||
switch (rr_type) {
|
||||
case GETDNS_RRTYPE_NS:
|
||||
case GETDNS_RRTYPE_MD:
|
||||
case GETDNS_RRTYPE_CNAME:
|
||||
case GETDNS_RRTYPE_SOA:
|
||||
case GETDNS_RRTYPE_MG:
|
||||
case GETDNS_RRTYPE_MR:
|
||||
case GETDNS_RRTYPE_PTR:
|
||||
case GETDNS_RRTYPE_MINFO:
|
||||
case GETDNS_RRTYPE_MX:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ldns_dname_compare_v(const void *a, const void *b) {
|
||||
return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
|
||||
}
|
||||
|
||||
ldns_status
|
||||
priv_getdns_ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
|
||||
{
|
||||
ldns_dnssec_name *new_name;
|
||||
ldns_rbnode_t *new_node;
|
||||
|
||||
if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC3)
|
||||
return ldns_dnssec_zone_add_rr(zone, rr);
|
||||
|
||||
if (!(new_name = ldns_dnssec_name_new()))
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
|
||||
new_name->name = ldns_rdf_clone(ldns_rr_owner(rr));
|
||||
new_name->hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
|
||||
new_name->name_alloced = true;
|
||||
|
||||
if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
|
||||
ldns_dnssec_name_free(new_name);
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
}
|
||||
new_node->key = new_name->name;
|
||||
new_node->data = new_name;
|
||||
if (!zone->names)
|
||||
zone->names = ldns_rbtree_create(ldns_dname_compare_v);
|
||||
(void)ldns_rbtree_insert(zone->names, new_node);
|
||||
|
||||
if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
|
||||
ldns_dnssec_name_free(new_name);
|
||||
return LDNS_STATUS_MEM_ERR;
|
||||
}
|
||||
new_node->key = new_name->hashed_name;
|
||||
new_node->data = new_name;
|
||||
if (!zone->hashed_names) {
|
||||
zone->_nsec3params = rr;
|
||||
zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
|
||||
}
|
||||
(void)ldns_rbtree_insert(zone->hashed_names, new_node);
|
||||
|
||||
return ldns_dnssec_zone_add_rr(zone, rr);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
priv_getdns_dnssec_zone_from_list(struct getdns_list *list,
|
||||
ldns_dnssec_zone **zone)
|
||||
|
@ -405,10 +537,13 @@ priv_getdns_dnssec_zone_from_list(struct getdns_list *list,
|
|||
if ((r = getdns_list_get_dict(list, i, &rr_dict)))
|
||||
break;
|
||||
|
||||
if (priv_getdns_rr_dict_with_compressed_names(rr_dict))
|
||||
continue;
|
||||
|
||||
if ((r = priv_getdns_create_rr_from_dict(rr_dict, &rr)))
|
||||
break;
|
||||
|
||||
if ((s = ldns_dnssec_zone_add_rr(*zone, rr))) {
|
||||
if ((s = priv_getdns_ldns_dnssec_zone_add_rr(*zone, rr))) {
|
||||
ldns_rr_free(rr);
|
||||
r = GETDNS_RETURN_GENERIC_ERROR;
|
||||
break;
|
||||
|
@ -423,19 +558,41 @@ typedef struct zone_iter {
|
|||
ldns_dnssec_zone *zone;
|
||||
ldns_rbnode_t *cur_node;
|
||||
ldns_dnssec_rrsets *cur_rrset;
|
||||
|
||||
ldns_dnssec_rrsets nsec_rrset;
|
||||
ldns_dnssec_rrs nsec_rrs;
|
||||
} zone_iter;
|
||||
|
||||
static void
|
||||
rrset_iter_init_zone(zone_iter *i, ldns_dnssec_zone *zone)
|
||||
{
|
||||
ldns_dnssec_name *name;
|
||||
assert(i);
|
||||
|
||||
i->zone = zone;
|
||||
i->cur_node = zone->names ? ldns_rbtree_first(zone->names)
|
||||
: LDNS_RBTREE_NULL;
|
||||
i->cur_rrset = i->cur_node != LDNS_RBTREE_NULL
|
||||
? ((ldns_dnssec_name *)i->cur_node->data)->rrsets
|
||||
: NULL;
|
||||
if ((i->cur_node = zone->names
|
||||
? ldns_rbtree_first(zone->names)
|
||||
: LDNS_RBTREE_NULL) == LDNS_RBTREE_NULL) {
|
||||
|
||||
i->cur_rrset = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
i->cur_rrset = ((ldns_dnssec_name *)i->cur_node->data)->rrsets;
|
||||
if (!i->cur_rrset) {
|
||||
name = ((ldns_dnssec_name *)i->cur_node->data);
|
||||
if (name->nsec && name->nsec_signatures) {
|
||||
i->cur_rrset = &i->nsec_rrset;
|
||||
i->nsec_rrset.rrs = &i->nsec_rrs;
|
||||
i->nsec_rrs.rr = name->nsec;
|
||||
i->nsec_rrs.next = NULL;
|
||||
i->nsec_rrset.type = ldns_rr_get_type(name->nsec);
|
||||
i->nsec_rrset.signatures =
|
||||
name->nsec_signatures;
|
||||
i->nsec_rrset.next = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ldns_dnssec_rrsets *
|
||||
|
@ -449,12 +606,30 @@ rrset_iter_value(zone_iter *i)
|
|||
static void
|
||||
rrset_iter_next(zone_iter *i)
|
||||
{
|
||||
int was_nsec_rrset;
|
||||
ldns_dnssec_name *name;
|
||||
assert(i);
|
||||
|
||||
if (! i->cur_rrset)
|
||||
return;
|
||||
|
||||
was_nsec_rrset = (i->cur_rrset == &i->nsec_rrset);
|
||||
if (! (i->cur_rrset = i->cur_rrset->next)) {
|
||||
|
||||
if (!was_nsec_rrset) {
|
||||
name = ((ldns_dnssec_name *)i->cur_node->data);
|
||||
if (name->nsec && name->nsec_signatures) {
|
||||
i->cur_rrset = &i->nsec_rrset;
|
||||
i->nsec_rrset.rrs = &i->nsec_rrs;
|
||||
i->nsec_rrs.rr = name->nsec;
|
||||
i->nsec_rrs.next = NULL;
|
||||
i->nsec_rrset.type = ldns_rr_get_type(name->nsec);
|
||||
i->nsec_rrset.signatures =
|
||||
name->nsec_signatures;
|
||||
i->nsec_rrset.next = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
i->cur_node = ldns_rbtree_next(i->cur_node);
|
||||
i->cur_rrset = i->cur_node != LDNS_RBTREE_NULL
|
||||
? ((ldns_dnssec_name *)i->cur_node->data)->rrsets
|
||||
|
@ -572,9 +747,9 @@ done_free_verifying_keys:
|
|||
*
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_validate_dnssec(struct getdns_list *records_to_validate,
|
||||
struct getdns_list *support_records,
|
||||
struct getdns_list *trust_anchors)
|
||||
getdns_validate_dnssec(getdns_list *records_to_validate,
|
||||
getdns_list *support_records,
|
||||
getdns_list *trust_anchors)
|
||||
{
|
||||
getdns_return_t r;
|
||||
ldns_rr_list *trusted;
|
||||
|
@ -584,7 +759,7 @@ getdns_validate_dnssec(struct getdns_list *records_to_validate,
|
|||
zone_iter i;
|
||||
ldns_dnssec_rrsets *rrset;
|
||||
ldns_dnssec_rrs *rrs;
|
||||
ldns_status s = LDNS_STATUS_OK;
|
||||
ldns_status s = LDNS_STATUS_ERR;
|
||||
|
||||
if ((r = priv_getdns_rr_list_from_list(trust_anchors, &trusted)))
|
||||
return r;
|
||||
|
@ -616,8 +791,7 @@ getdns_validate_dnssec(struct getdns_list *records_to_validate,
|
|||
for (rrset_iter_init_zone(&i, to_validate);
|
||||
(rrset = rrset_iter_value(&i)); rrset_iter_next(&i)) {
|
||||
|
||||
s |= chase(rrset, support, support_keys, trusted);
|
||||
if (s != 0)
|
||||
if ((s = chase(rrset, support, support_keys, trusted)))
|
||||
break;
|
||||
}
|
||||
if (s == LDNS_STATUS_CRYPTO_BOGUS)
|
||||
|
|
|
@ -93,7 +93,13 @@ priv_getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
|||
|
||||
if (! results_found)
|
||||
priv_getdns_call_user_callback(dns_req, NULL);
|
||||
else if (dns_req->dnssec_return_validation_chain)
|
||||
else if (dns_req->dnssec_return_validation_chain
|
||||
#ifdef STUB_NATIVE_DNSSEC
|
||||
|| (dns_req->context->resolution_type == GETDNS_RESOLUTION_STUB
|
||||
&& (dns_req->dnssec_return_status ||
|
||||
dns_req->dnssec_return_only_secure))
|
||||
#endif
|
||||
)
|
||||
priv_getdns_get_validation_chain(dns_req);
|
||||
else
|
||||
priv_getdns_call_user_callback(
|
||||
|
@ -130,13 +136,16 @@ submit_network_request(getdns_network_req *netreq)
|
|||
getdns_return_t r;
|
||||
getdns_dns_req *dns_req = netreq->owner;
|
||||
|
||||
if (dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING ||
|
||||
if (dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
||||
/* TODO: Until DNSSEC with the new async stub resolver is finished,
|
||||
* use unbound when we need DNSSEC.
|
||||
*/
|
||||
dns_req->dnssec_return_status ||
|
||||
dns_req->dnssec_return_only_secure ||
|
||||
dns_req->dnssec_return_validation_chain) {
|
||||
#ifndef STUB_NATIVE_DNSSEC
|
||||
|| dns_req->dnssec_return_status
|
||||
|| dns_req->dnssec_return_only_secure
|
||||
|| dns_req->dnssec_return_validation_chain
|
||||
#endif
|
||||
) {
|
||||
|
||||
/* schedule the timeout */
|
||||
if (! dns_req->timeout.timeout_cb) {
|
||||
|
|
|
@ -477,8 +477,8 @@ set_dict(getdns_dict **var, getdns_dict *value)
|
|||
#define SET_WIRE_CNT(X,Y) if (getdns_dict_set_int(header, #X , (int) \
|
||||
GLDNS_ ## Y (req->response))) goto error
|
||||
|
||||
static getdns_dict *
|
||||
create_reply_dict(getdns_context *context, getdns_network_req *req,
|
||||
getdns_dict *
|
||||
priv_getdns_create_reply_dict(getdns_context *context, getdns_network_req *req,
|
||||
getdns_list *just_addrs, int *rrsigs_in_answer)
|
||||
{
|
||||
/* turn a packet into this glorious structure
|
||||
|
@ -595,7 +595,7 @@ create_reply_dict(getdns_context *context, getdns_network_req *req,
|
|||
|
||||
rr_type = gldns_read_uint16(rr_iter->rr_type);
|
||||
if (section > GLDNS_SECTION_QUESTION &&
|
||||
rr_type == GETDNS_RRTYPE_RRSIG)
|
||||
rr_type == GETDNS_RRTYPE_RRSIG && rrsigs_in_answer)
|
||||
*rrsigs_in_answer = 1;
|
||||
|
||||
if (section != GLDNS_SECTION_ANSWER)
|
||||
|
@ -635,7 +635,7 @@ create_reply_dict(getdns_context *context, getdns_network_req *req,
|
|||
|
||||
getdns_dict_set_bindata(rr_dict,"address_data",&bindata) ||
|
||||
|
||||
getdns_list_append_dict(just_addrs, rr_dict)) {
|
||||
(just_addrs && getdns_list_append_dict(just_addrs, rr_dict))) {
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
@ -775,7 +775,7 @@ create_getdns_response(getdns_dns_req *completed_request)
|
|||
&& ! netreq->secure)
|
||||
continue;
|
||||
}
|
||||
if (!(reply = create_reply_dict(context,
|
||||
if (!(reply = priv_getdns_create_reply_dict(context,
|
||||
netreq, just_addrs, &rrsigs_in_answer)))
|
||||
goto error;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "rr-iter.h"
|
||||
|
||||
#define SCHED_DEBUG 0
|
||||
#define WIRE_DEBUG 1
|
||||
#define WIRE_DEBUG 0
|
||||
|
||||
#ifdef S_SPLINT_S
|
||||
# define INLINE
|
||||
|
@ -127,6 +127,9 @@ priv_getdns_rr_iter2rr_dict(getdns_context *context, priv_getdns_rr_iter *i);
|
|||
struct getdns_dns_req;
|
||||
struct getdns_dict *create_getdns_response(struct getdns_dns_req *completed_request);
|
||||
|
||||
getdns_dict *priv_getdns_create_reply_dict(getdns_context *context,
|
||||
getdns_network_req *req, getdns_list *just_addrs, int *rrsigs_in_answer);
|
||||
|
||||
getdns_return_t validate_dname(const char* dname);
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue