Merge branch 'features/canonical_dnssec_chain' into upstream/develop

This commit is contained in:
Willem Toorop 2016-04-29 16:24:58 +02:00
commit 066c0b3837
13 changed files with 368 additions and 119 deletions

View File

@ -232,7 +232,7 @@ context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/g
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
@ -247,13 +247,14 @@ dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h \ $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \
$(srcdir)/util/val_secalgo.h
general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ getdns/getdns_extra.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
@ -285,7 +286,7 @@ sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h ge
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/debug.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/debug.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/debug.h $(srcdir)/debug.h
@ -293,7 +294,8 @@ util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getd
$(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \
$(srcdir)/gldns/rrdef.h
version.lo version.o: version.c version.lo version.o: version.c
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h
keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h

View File

@ -601,6 +601,24 @@ getdns_dict_set_list(
/*---------------------------------------- getdns_dict_set_bindata */ /*---------------------------------------- getdns_dict_set_bindata */
getdns_return_t
_getdns_dict_set_this_bindata(
getdns_dict *dict, const char *name, getdns_bindata *bindata)
{
getdns_item *item;
getdns_return_t r;
if (!dict || !name || !bindata)
return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = _getdns_dict_find_and_add(dict, name, &item)))
return r;
item->dtype = t_bindata;
item->data.bindata = bindata;
return GETDNS_RETURN_GOOD;
}
getdns_return_t getdns_return_t
_getdns_dict_set_const_bindata( _getdns_dict_set_const_bindata(
getdns_dict *dict, const char *name, size_t size, const void *data) getdns_dict *dict, const char *name, size_t size, const void *data)

View File

@ -268,23 +268,6 @@ static uint8_t *_dname_label_copy(uint8_t *dst, const uint8_t *src, size_t dst_l
return r; return r;
} }
inline static void _dname_canonicalize(const uint8_t *src, uint8_t *dst)
{
const uint8_t *next_label;
while (*src) {
next_label = src + *src + 1;
*dst++ = *src++;
while (src < next_label)
*dst++ = (uint8_t)tolower((unsigned char)*src++);
}
}
inline static void _dname_canonicalize2(uint8_t *dname)
{
_dname_canonicalize(dname, dname);
}
/* Fills the array pointed to by labels (of at least 128 uint8_t * pointers) /* Fills the array pointed to by labels (of at least 128 uint8_t * pointers)
* with pointers to labels in given dname in reversed order. So that * with pointers to labels in given dname in reversed order. So that
@ -736,6 +719,8 @@ typedef struct chain_node chain_node;
struct chain_head { struct chain_head {
struct mem_funcs my_mf; struct mem_funcs my_mf;
size_t lock;
chain_head *next; chain_head *next;
chain_node *parent; chain_node *parent;
size_t node_count; /* Number of nodes attached directly size_t node_count; /* Number of nodes attached directly
@ -857,6 +842,7 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
head = *chain_p = (chain_head *)region; head = *chain_p = (chain_head *)region;
head->my_mf = *mf; head->my_mf = *mf;
head->lock = 1;
head->next = NULL; head->next = NULL;
head->rrset.name = head->name_spc; head->rrset.name = head->name_spc;
memcpy(head->name_spc, rrset->name, dname_len); memcpy(head->name_spc, rrset->name, dname_len);
@ -865,7 +851,7 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
head->rrset.pkt = rrset->pkt; head->rrset.pkt = rrset->pkt;
head->rrset.pkt_len = rrset->pkt_len; head->rrset.pkt_len = rrset->pkt_len;
head->netreq = netreq; head->netreq = netreq;
head->signer = 0; head->signer = -1;
head->node_count = node_count; head->node_count = node_count;
if (!node_count) { if (!node_count) {
@ -894,8 +880,8 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
node->ds_req = NULL; node->ds_req = NULL;
node->dnskey_req = NULL; node->dnskey_req = NULL;
node->soa_req = NULL; node->soa_req = NULL;
node->ds_signer = 0; node->ds_signer = -1;
node->dnskey_signer = 0; node->dnskey_signer = -1;
node->chains = *chain_p; node->chains = *chain_p;
} }
@ -1319,6 +1305,7 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq)
default : check_chain_complete(node->chains); default : check_chain_complete(node->chains);
return; return;
} }
node->lock++;
n_signers = 0; n_signers = 0;
for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len) for ( i = rrset_iter_init(&i_spc,netreq->response,netreq->response_len)
; i ; i
@ -1344,6 +1331,7 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq)
*/ */
val_chain_sched_soa_node(node->parent); val_chain_sched_soa_node(node->parent);
node->lock--;
check_chain_complete(node->chains); check_chain_complete(node->chains);
} }
@ -1363,17 +1351,21 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq)
! _dname_equal(node->ds.name, rrset->name)) ! _dname_equal(node->ds.name, rrset->name))
node = node->parent; node = node->parent;
if (node) if (node) {
node->lock++;
val_chain_sched_ds_node(node); val_chain_sched_ds_node(node);
else { } else {
/* SOA for a different name */ /* SOA for a different name */
node = (chain_node *)dnsreq->user_pointer; node = (chain_node *)dnsreq->user_pointer;
node->lock++;
val_chain_sched_soa_node(node->parent); val_chain_sched_soa_node(node->parent);
} }
} else if (node->parent) } else if (node->parent) {
node->lock++;
val_chain_sched_soa_node(node->parent); val_chain_sched_soa_node(node->parent);
}
node->lock--;
check_chain_complete(node->chains); check_chain_complete(node->chains);
} }
@ -1528,21 +1520,6 @@ inline static void canon_rdata_iter_next(canon_rdata_iter *i)
i->pos++; i->pos++;
} }
inline static int _dnssec_rdata_to_canonicalize(uint16_t rr_type)
{
return rr_type == GLDNS_RR_TYPE_NS || rr_type == GLDNS_RR_TYPE_MD
|| rr_type == GLDNS_RR_TYPE_MF || rr_type == GLDNS_RR_TYPE_CNAME
|| rr_type == GLDNS_RR_TYPE_SOA || rr_type == GLDNS_RR_TYPE_MB
|| rr_type == GLDNS_RR_TYPE_MG || rr_type == GLDNS_RR_TYPE_MR
|| rr_type == GLDNS_RR_TYPE_PTR || rr_type == GLDNS_RR_TYPE_MINFO
|| rr_type == GLDNS_RR_TYPE_MX || rr_type == GLDNS_RR_TYPE_RP
|| rr_type == GLDNS_RR_TYPE_AFSDB || rr_type == GLDNS_RR_TYPE_RT
|| rr_type == GLDNS_RR_TYPE_SIG || rr_type == GLDNS_RR_TYPE_PX
|| rr_type == GLDNS_RR_TYPE_NXT || rr_type == GLDNS_RR_TYPE_NAPTR
|| rr_type == GLDNS_RR_TYPE_KX || rr_type == GLDNS_RR_TYPE_SRV
|| rr_type == GLDNS_RR_TYPE_DNAME || rr_type == GLDNS_RR_TYPE_RRSIG;
}
static int _rr_iter_rdata_cmp(const void *a, const void *b) static int _rr_iter_rdata_cmp(const void *a, const void *b)
{ {
_getdns_rr_iter *x = (_getdns_rr_iter *)a; _getdns_rr_iter *x = (_getdns_rr_iter *)a;
@ -1656,6 +1633,7 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf,
if (!_dnssec_rdata_to_canonicalize(rrset->rr_type)) if (!_dnssec_rdata_to_canonicalize(rrset->rr_type))
for (i = 0; i < n_rrs; i++) { for (i = 0; i < n_rrs; i++) {
/* Get rid of doubles */
if (i && !_rr_iter_rdata_cmp( if (i && !_rr_iter_rdata_cmp(
&val_rrset[i], &val_rrset[i-1])) &val_rrset[i], &val_rrset[i-1]))
continue; continue;
@ -3003,7 +2981,7 @@ static size_t count_outstanding_requests(chain_head *head)
if (!head) if (!head)
return 0; return 0;
for ( node = head->parent, count = 0 for ( node = head->parent, count = head->lock
; node ; node
; node = node->parent) { ; node = node->parent) {
@ -3047,6 +3025,77 @@ static int rrset_in_list(getdns_rrset *rrset, getdns_list *list)
return 0; return 0;
} }
static void append_rrset2val_chain_list(
getdns_list *val_chain_list, getdns_rrset *rrset, int signer)
{
_getdns_rr_iter val_rrset_spc[VAL_RRSET_SPC_SZ];
_getdns_rr_iter *val_rrset = val_rrset_spc;
rrtype_iter rr_spc, *rr;
size_t n_rrs, i;
uint32_t orig_ttl;
getdns_dict *rr_dict;
rrsig_iter *rrsig, rrsig_spc;
assert(val_chain_list && rrset);
if (signer < 0)
return;
for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset)
; rrsig &&
( rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28
|| gldns_read_uint16(rrsig->rr_i.rr_type + 26)
!= (signer & 0xFFFF))
; rrsig = rrsig_iter_next(rrsig))
; /* pass */
if (!rrsig)
return;
/* keytag was already read, so orig_ttl should cause no problem */
assert(rrsig->rr_i.nxt >= rrsig->rr_i.rr_type + 18);
orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
for (;;) {
for ( rr = rrtype_iter_init(&rr_spc, rrset), n_rrs = 0
; rr
; rr = rrtype_iter_next(rr), n_rrs++) {
if (n_rrs < VAL_RRSET_SPC_SZ ||
val_rrset != val_rrset_spc)
val_rrset[n_rrs] = rr->rr_i;
}
/* Did everything fit? Then break */
if (val_rrset != val_rrset_spc || n_rrs <= VAL_RRSET_SPC_SZ)
break;
/* More space needed for val_rrset */
val_rrset = GETDNS_XMALLOC(
val_chain_list->mf, _getdns_rr_iter, n_rrs);
}
qsort(val_rrset, n_rrs, sizeof(_getdns_rr_iter), _rr_iter_rdata_cmp);
for (i = 0; i < n_rrs; i++) {
/* Get rid of doubles */
if (i && !_rr_iter_rdata_cmp(&val_rrset[i], &val_rrset[i-1]))
continue;
if (!(rr_dict = _getdns_rr_iter2rr_dict_canonical(
&val_chain_list->mf, &val_rrset[i], &orig_ttl)))
continue;
if (_getdns_list_append_this_dict(val_chain_list, rr_dict))
getdns_dict_destroy(rr_dict);
}
if ((rr_dict = _getdns_rr_iter2rr_dict_canonical(
&val_chain_list->mf, &rrsig->rr_i, &orig_ttl)) &&
_getdns_list_append_this_dict(val_chain_list, rr_dict))
getdns_dict_destroy(rr_dict);
if (val_rrset != val_rrset_spc)
GETDNS_FREE(val_chain_list->mf, val_rrset);
}
static void append_rrs2val_chain_list(getdns_context *ctxt, static void append_rrs2val_chain_list(getdns_context *ctxt,
getdns_list *val_chain_list, getdns_network_req *netreq, int signer) getdns_list *val_chain_list, getdns_network_req *netreq, int signer)
{ {
@ -3072,6 +3121,15 @@ static void append_rrs2val_chain_list(getdns_context *ctxt,
rrset->rr_type != GETDNS_RRTYPE_DS) rrset->rr_type != GETDNS_RRTYPE_DS)
continue; continue;
if (signer > 0) {
/* We have a signer! Return RRset in canonical
* form and order with only the RRSIG that signed
* the RRset.
*/
append_rrset2val_chain_list(
val_chain_list, rrset, signer);
continue;
}
for ( rr = rrtype_iter_init(&rr_spc, rrset) for ( rr = rrtype_iter_init(&rr_spc, rrset)
; rr; rr = rrtype_iter_next(rr)) { ; rr; rr = rrtype_iter_next(rr)) {
@ -3085,16 +3143,7 @@ static void append_rrs2val_chain_list(getdns_context *ctxt,
for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset) for ( rrsig = rrsig_iter_init(&rrsig_spc, rrset)
; rrsig; rrsig = rrsig_iter_next(rrsig)) { ; rrsig; rrsig = rrsig_iter_next(rrsig)) {
if (/* No space for keytag & signer in rrsig rdata? */ if (!(rr_dict = _getdns_rr_iter2rr_dict(
rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28
/* We have a signer and it doesn't match? */
|| ((signer & 0xFFFF) &&
gldns_read_uint16(rrsig->rr_i.rr_type + 26)
!= (signer & 0xFFFF))
/* Could not convert to rr_dict */
|| !(rr_dict = _getdns_rr_iter2rr_dict(
&ctxt->mf, &rrsig->rr_i))) &ctxt->mf, &rrsig->rr_i)))
continue; continue;
@ -3139,7 +3188,7 @@ static void check_chain_complete(chain_head *chain)
getdns_dns_req *dnsreq; getdns_dns_req *dnsreq;
getdns_context *context; getdns_context *context;
size_t o, node_count; size_t o, node_count;
chain_head *head, *next; chain_head *head, *next, *same_chain;
chain_node *node; chain_node *node;
getdns_list *val_chain_list; getdns_list *val_chain_list;
getdns_dict *response_dict; getdns_dict *response_dict;
@ -3181,7 +3230,7 @@ static void check_chain_complete(chain_head *chain)
&& !dnsreq->avoid_dnssec_roadblocks && !dnsreq->avoid_dnssec_roadblocks
&& dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) { && dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) {
getdns_return_t r = GETDNS_RETURN_GOOD; int r = GETDNS_RETURN_GOOD;
getdns_network_req **netreq_p, *netreq; getdns_network_req **netreq_p, *netreq;
dnsreq->avoid_dnssec_roadblocks = 1; dnsreq->avoid_dnssec_roadblocks = 1;
@ -3203,22 +3252,39 @@ static void check_chain_complete(chain_head *chain)
/* Walk chain to add values to val_chain_list and to cleanup */ /* Walk chain to add values to val_chain_list and to cleanup */
for ( head = chain; head ; head = next ) { for ( head = chain; head ; head = next ) {
next = head->next; next = head->next;
if (dnsreq->dnssec_return_full_validation_chain &&
head->node_count && head->signer > 0) {
append_rrset2val_chain_list(
val_chain_list, &head->rrset, head->signer);
for ( same_chain = next
; same_chain && same_chain->signer == head->signer
; same_chain = same_chain->next) {
append_rrset2val_chain_list(val_chain_list,
&same_chain->rrset, same_chain->signer);
same_chain->signer = -1;
}
}
for ( node_count = head->node_count, node = head->parent for ( node_count = head->node_count, node = head->parent
; node_count ; node_count
; node_count--, node = node->parent ) { ; node_count--, node = node->parent ) {
if (node->dnskey_req) { if (node->dnskey_req) {
append_rrs2val_chain_list( if (val_chain_list)
context, val_chain_list, append_rrs2val_chain_list(
node->dnskey_req, node->dnskey_signer); context, val_chain_list,
node->dnskey_req,
node->dnskey_signer);
_getdns_dns_req_free(node->dnskey_req->owner); _getdns_dns_req_free(node->dnskey_req->owner);
} }
if (node->ds_req) { if (node->ds_req) {
append_rrs2val_chain_list( if (val_chain_list)
context, val_chain_list, append_rrs2val_chain_list(
node->ds_req, node->ds_signer); context, val_chain_list,
node->ds_req, node->ds_signer);
if (!node->ds_signer && if (val_chain_list && node->ds_signer == -1 &&
!rrset_has_rrs(&node->ds)) { !rrset_has_rrs(&node->ds)) {
/* Add empty DS, to prevent less /* Add empty DS, to prevent less
* specific to be able to authenticate * specific to be able to authenticate
@ -3245,6 +3311,7 @@ static void check_chain_complete(chain_head *chain)
} }
/* Final user callback */ /* Final user callback */
dnsreq->validating = 0;
_getdns_call_user_callback(dnsreq, response_dict); _getdns_call_user_callback(dnsreq, response_dict);
} }
@ -3252,7 +3319,11 @@ static void check_chain_complete(chain_head *chain)
void _getdns_get_validation_chain(getdns_dns_req *dnsreq) void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
{ {
getdns_network_req *netreq, **netreq_p; getdns_network_req *netreq, **netreq_p;
chain_head *chain = NULL; chain_head *chain = NULL, *chain_p;
if (dnsreq->validating)
return;
dnsreq->validating = 1;
for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) { for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) {
if (! netreq->response if (! netreq->response
@ -3277,11 +3348,15 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
, netreq , netreq
); );
} }
if (chain) if (chain) {
for (chain_p = chain; chain_p; chain_p = chain_p->next)
chain_p->lock--;
check_chain_complete(chain); check_chain_complete(chain);
else } else {
dnsreq->validating = 0;
_getdns_call_user_callback(dnsreq, _getdns_call_user_callback(dnsreq,
_getdns_create_getdns_response(dnsreq)); _getdns_create_getdns_response(dnsreq));
}
} }

View File

@ -41,6 +41,7 @@
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "config.h" #include "config.h"
#include "gldns/gbuffer.h" #include "gldns/gbuffer.h"
#include "gldns/rrdef.h"
#include "types-internal.h" #include "types-internal.h"
/* Do some additional requests to fetch the complete validation chain */ /* Do some additional requests to fetch the complete validation chain */
@ -48,6 +49,21 @@ void _getdns_get_validation_chain(getdns_dns_req *dns_req);
uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf); uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf);
inline static int _dnssec_rdata_to_canonicalize(uint16_t rr_type)
{
return rr_type == GLDNS_RR_TYPE_NS || rr_type == GLDNS_RR_TYPE_MD
|| rr_type == GLDNS_RR_TYPE_MF || rr_type == GLDNS_RR_TYPE_CNAME
|| rr_type == GLDNS_RR_TYPE_SOA || rr_type == GLDNS_RR_TYPE_MB
|| rr_type == GLDNS_RR_TYPE_MG || rr_type == GLDNS_RR_TYPE_MR
|| rr_type == GLDNS_RR_TYPE_PTR || rr_type == GLDNS_RR_TYPE_MINFO
|| rr_type == GLDNS_RR_TYPE_MX || rr_type == GLDNS_RR_TYPE_RP
|| rr_type == GLDNS_RR_TYPE_AFSDB || rr_type == GLDNS_RR_TYPE_RT
|| rr_type == GLDNS_RR_TYPE_SIG || rr_type == GLDNS_RR_TYPE_PX
|| rr_type == GLDNS_RR_TYPE_NXT || rr_type == GLDNS_RR_TYPE_NAPTR
|| rr_type == GLDNS_RR_TYPE_KX || rr_type == GLDNS_RR_TYPE_SRV
|| rr_type == GLDNS_RR_TYPE_DNAME || rr_type == GLDNS_RR_TYPE_RRSIG;
}
#endif #endif
/* dnssec.h */ /* dnssec.h */

View File

@ -161,7 +161,7 @@ void
_getdns_check_dns_req_complete(getdns_dns_req *dns_req) _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
{ {
getdns_network_req **netreq_p, *netreq; getdns_network_req **netreq_p, *netreq;
int results_found = 0; int results_found = 0, r;
for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++) for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++)
if (netreq->state != NET_REQ_FINISHED && if (netreq->state != NET_REQ_FINISHED &&
@ -198,8 +198,11 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
; (netreq = *netreq_p) ; (netreq = *netreq_p)
; netreq_p++ ) { ; netreq_p++ ) {
_getdns_netreq_reinit(netreq); _getdns_netreq_reinit(netreq);
if (_getdns_submit_netreq(netreq)) if ((r = _getdns_submit_netreq(netreq))) {
if (r == DNS_REQ_FINISHED)
return;
netreq->state = NET_REQ_FINISHED; netreq->state = NET_REQ_FINISHED;
}
} }
_getdns_check_dns_req_complete(dns_req); _getdns_check_dns_req_complete(dns_req);
return; return;
@ -233,8 +236,11 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
; (netreq = *netreq_p) ; (netreq = *netreq_p)
; netreq_p++ ) { ; netreq_p++ ) {
_getdns_netreq_reinit(netreq); _getdns_netreq_reinit(netreq);
if (_getdns_submit_netreq(netreq)) if ((r = _getdns_submit_netreq(netreq))) {
if (r == DNS_REQ_FINISHED)
return;
netreq->state = NET_REQ_FINISHED; netreq->state = NET_REQ_FINISHED;
}
} }
_getdns_check_dns_req_complete(dns_req); _getdns_check_dns_req_complete(dns_req);
return; return;
@ -312,13 +318,16 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
#endif #endif
getdns_return_t int
_getdns_submit_netreq(getdns_network_req *netreq) _getdns_submit_netreq(getdns_network_req *netreq)
{ {
getdns_return_t r; getdns_return_t r;
getdns_dns_req *dns_req = netreq->owner; getdns_dns_req *dns_req = netreq->owner;
char name[1024]; char name[1024];
int dnsreq_freed = 0;
#ifdef HAVE_LIBUNBOUND
int ub_resolve_r;
#endif
#ifdef STUB_NATIVE_DNSSEC #ifdef STUB_NATIVE_DNSSEC
# ifdef DNSSEC_ROADBLOCK_AVOIDANCE # ifdef DNSSEC_ROADBLOCK_AVOIDANCE
@ -351,24 +360,34 @@ _getdns_submit_netreq(getdns_network_req *netreq)
dns_req->name_len, name, sizeof(name)); dns_req->name_len, name, sizeof(name));
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
dns_req->freed = &dnsreq_freed;
#ifdef HAVE_UNBOUND_EVENT_API #ifdef HAVE_UNBOUND_EVENT_API
if (_getdns_ub_loop_enabled(&dns_req->context->ub_loop)) if (_getdns_ub_loop_enabled(&dns_req->context->ub_loop))
return ub_resolve_event(dns_req->context->unbound_ctx, ub_resolve_r = ub_resolve_event(dns_req->context->unbound_ctx,
name, netreq->request_type, netreq->owner->request_class, name, netreq->request_type, netreq->owner->request_class,
netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ? netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ?
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
else else
#endif #endif
return ub_resolve_async(dns_req->context->unbound_ctx, ub_resolve_r = ub_resolve_async(dns_req->context->unbound_ctx,
name, netreq->request_type, netreq->owner->request_class, name, netreq->request_type, netreq->owner->request_class,
netreq, ub_resolve_callback, &(netreq->unbound_id)) ? netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
if (dnsreq_freed)
return DNS_REQ_FINISHED;
dns_req->freed = NULL;
return ub_resolve_r ? GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
#else #else
return GETDNS_RETURN_NOT_IMPLEMENTED; return GETDNS_RETURN_NOT_IMPLEMENTED;
#endif #endif
} }
/* Submit with stub resolver */ /* Submit with stub resolver */
return _getdns_submit_stub_request(netreq); dns_req->freed = &dnsreq_freed;
r = _getdns_submit_stub_request(netreq);
if (dnsreq_freed)
return DNS_REQ_FINISHED;
dns_req->freed = NULL;
return r;
} }
@ -403,6 +422,7 @@ validate_extensions(struct getdns_dict * extensions)
{"add_opt_parameters" , t_dict, 1}, {"add_opt_parameters" , t_dict, 1},
{"add_warning_for_bad_dns" , t_int , 1}, {"add_warning_for_bad_dns" , t_int , 1},
{"dnssec_return_all_statuses" , t_int , 1}, {"dnssec_return_all_statuses" , t_int , 1},
{"dnssec_return_full_validation_chain", t_int , 1},
{"dnssec_return_only_secure" , t_int , 1}, {"dnssec_return_only_secure" , t_int , 1},
{"dnssec_return_status" , t_int , 1}, {"dnssec_return_status" , t_int , 1},
{"dnssec_return_validation_chain", t_int , 1}, {"dnssec_return_validation_chain", t_int , 1},
@ -457,7 +477,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
void *userarg, getdns_network_req **return_netreq_p, void *userarg, getdns_network_req **return_netreq_p,
getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces) getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces)
{ {
getdns_return_t r = GETDNS_RETURN_GOOD; int r = GETDNS_RETURN_GOOD;
getdns_network_req *netreq, **netreq_p; getdns_network_req *netreq, **netreq_p;
getdns_dns_req *req; getdns_dns_req *req;
getdns_dict *localnames_response; getdns_dict *localnames_response;
@ -496,8 +516,16 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
/* issue all network requests */ /* issue all network requests */
for ( netreq_p = req->netreqs for ( netreq_p = req->netreqs
; !r && (netreq = *netreq_p) ; !r && (netreq = *netreq_p)
; netreq_p++) ; netreq_p++) {
r = _getdns_submit_netreq(netreq); if ((r = _getdns_submit_netreq(netreq))) {
if (r == DNS_REQ_FINISHED) {
if (return_netreq_p)
*return_netreq_p = NULL;
return GETDNS_RETURN_GOOD;
}
netreq->state = NET_REQ_FINISHED;
}
}
else for (i = 0; i < context->namespace_count; i++) { else for (i = 0; i < context->namespace_count; i++) {
if (context->namespaces[i] == GETDNS_NAMESPACE_LOCALNAMES) { if (context->namespaces[i] == GETDNS_NAMESPACE_LOCALNAMES) {
@ -518,14 +546,21 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
r = GETDNS_RETURN_GOOD; r = GETDNS_RETURN_GOOD;
for ( netreq_p = req->netreqs for ( netreq_p = req->netreqs
; !r && (netreq = *netreq_p) ; !r && (netreq = *netreq_p)
; netreq_p++) ; netreq_p++) {
r = _getdns_submit_netreq(netreq); if ((r = _getdns_submit_netreq(netreq))) {
if (r == DNS_REQ_FINISHED) {
if (return_netreq_p)
*return_netreq_p = NULL;
return GETDNS_RETURN_GOOD;
}
netreq->state = NET_REQ_FINISHED;
}
}
break; break;
} else } else
r = GETDNS_RETURN_BAD_CONTEXT; r = GETDNS_RETURN_BAD_CONTEXT;
} }
if (r > 0) { /* i.e. r != GETDNS_RETURN_GOOD && r != DNS_REQ_FINISHED */
if (r != 0) {
/* clean up the request */ /* clean up the request */
_getdns_context_clear_outbound_request(req); _getdns_context_clear_outbound_request(req);
_getdns_dns_req_free(req); _getdns_dns_req_free(req);

View File

@ -42,9 +42,11 @@
/* private inner helper used by sync and async */ /* private inner helper used by sync and async */
#define DNS_REQ_FINISHED -1
void _getdns_call_user_callback(getdns_dns_req *, getdns_dict *); void _getdns_call_user_callback(getdns_dns_req *, getdns_dict *);
void _getdns_check_dns_req_complete(getdns_dns_req *dns_req); void _getdns_check_dns_req_complete(getdns_dns_req *dns_req);
getdns_return_t _getdns_submit_netreq(getdns_network_req *netreq); int _getdns_submit_netreq(getdns_network_req *netreq);
getdns_return_t getdns_return_t

View File

@ -646,7 +646,8 @@ _getdns_dns_req_free(getdns_dns_req * req)
req->loop->vmt->clear(req->loop, &req->timeout); req->loop->vmt->clear(req->loop, &req->timeout);
req->timeout.timeout_cb = NULL; req->timeout.timeout_cb = NULL;
} }
if (req->freed)
*req->freed = 1;
GETDNS_FREE(req->my_mf, req); GETDNS_FREE(req->my_mf, req);
} }
@ -664,6 +665,8 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
= is_extension_set(extensions, "dnssec_return_only_secure"); = is_extension_set(extensions, "dnssec_return_only_secure");
int dnssec_return_all_statuses int dnssec_return_all_statuses
= is_extension_set(extensions, "dnssec_return_all_statuses"); = is_extension_set(extensions, "dnssec_return_all_statuses");
int dnssec_return_full_validation_chain
= is_extension_set(extensions, "dnssec_return_full_validation_chain");
int dnssec_return_validation_chain int dnssec_return_validation_chain
= is_extension_set(extensions, "dnssec_return_validation_chain"); = is_extension_set(extensions, "dnssec_return_validation_chain");
int edns_cookies int edns_cookies
@ -680,6 +683,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
int dnssec_extension_set = dnssec_return_status int dnssec_extension_set = dnssec_return_status
|| dnssec_return_only_secure || dnssec_return_all_statuses || dnssec_return_only_secure || dnssec_return_all_statuses
|| dnssec_return_validation_chain || dnssec_return_validation_chain
|| dnssec_return_full_validation_chain
|| (extensions == dnssec_ok_checking_disabled) || (extensions == dnssec_ok_checking_disabled)
|| (extensions == dnssec_ok_checking_disabled_roadblock_avoidance) || (extensions == dnssec_ok_checking_disabled_roadblock_avoidance)
|| (extensions == dnssec_ok_checking_disabled_avoid_roadblocks) || (extensions == dnssec_ok_checking_disabled_avoid_roadblocks)
@ -880,7 +884,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->dnssec_return_status = dnssec_return_status; result->dnssec_return_status = dnssec_return_status;
result->dnssec_return_only_secure = dnssec_return_only_secure; result->dnssec_return_only_secure = dnssec_return_only_secure;
result->dnssec_return_all_statuses = dnssec_return_all_statuses; result->dnssec_return_all_statuses = dnssec_return_all_statuses;
result->dnssec_return_validation_chain = dnssec_return_validation_chain; result->dnssec_return_full_validation_chain =
dnssec_return_full_validation_chain;
result->dnssec_return_validation_chain = dnssec_return_validation_chain
|| dnssec_return_full_validation_chain;
result->edns_cookies = edns_cookies; result->edns_cookies = edns_cookies;
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance; result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance;
@ -907,6 +914,8 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->upstreams->referenced++; result->upstreams->referenced++;
result->finished_next = NULL; result->finished_next = NULL;
result->freed = NULL;
result->validating = 0;
network_req_init(result->netreqs[0], result, network_req_init(result->netreqs[0], result,
request_type, dnssec_extension_set, with_opt, request_type, dnssec_extension_set, with_opt,

View File

@ -474,6 +474,7 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t+dnssec_return_only_secure\n"); fprintf(out, "\t+dnssec_return_only_secure\n");
fprintf(out, "\t+dnssec_return_all_statuses\n"); fprintf(out, "\t+dnssec_return_all_statuses\n");
fprintf(out, "\t+dnssec_return_validation_chain\n"); fprintf(out, "\t+dnssec_return_validation_chain\n");
fprintf(out, "\t+dnssec_return_full_validation_chain\n");
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
fprintf(out, "\t+dnssec_roadblock_avoidance\n"); fprintf(out, "\t+dnssec_roadblock_avoidance\n");
#endif #endif

View File

@ -6,8 +6,12 @@
cat >queries <<EOT cat >queries <<EOT
NS . NS .
localhost
localhost.
A localhost.
-A getdnsapi.net -A getdnsapi.net
qwerlkjhasdfpuiqwyerm.1234kjhrqwersv.com qwerlkjhasdfpuiqwyerm.1234kjhrqwersv.com
localhost.
-G TXT bogus.nlnetlabs.nl -G TXT bogus.nlnetlabs.nl
-H 8.8.8.8 -H 8.8.8.8
-H 2a04:b900:0:100::37 -H 2a04:b900:0:100::37

View File

@ -4,13 +4,11 @@
# use .tpkg.var.test for in test variable passing # use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test [ -f .tpkg.var.test ] && source .tpkg.var.test
( cd "${BUILDDIR}/build-event-loops"
cd "${BUILDDIR}/build-event-loops" if make test
make test
) && if grep 'ERROR:' result.330-event-loops-unit-tests
then then
exit 1 if grep ERROR "${BUILDDIR}/build-event-loops/src/test/*.log"
else then
echo 'No ERROR:s found in result.330-event-loops-unit-tests' exit 1
ls -l result.330-event-loops-unit-tests fi
fi fi

View File

@ -272,37 +272,50 @@ typedef struct getdns_dns_req {
uint8_t name[256]; uint8_t name[256];
size_t name_len; size_t name_len;
getdns_append_name_t append_name;
const uint8_t *suffix;
size_t suffix_len;
int suffix_appended;
uint16_t request_class; uint16_t request_class;
/* canceled flag */
int canceled;
/* context that owns the request */ /* context that owns the request */
struct getdns_context *context; struct getdns_context *context;
getdns_append_name_t append_name;
const uint8_t *suffix;
size_t suffix_len;
int suffix_appended : 1;
/* canceled flag */
int canceled : 1;
/* request extensions */ /* request extensions */
int dnssec_return_status; int dnssec_return_status : 1;
int dnssec_return_only_secure; int dnssec_return_only_secure : 1;
int dnssec_return_all_statuses; int dnssec_return_all_statuses : 1;
int dnssec_return_validation_chain; int dnssec_return_validation_chain : 1;
int dnssec_return_full_validation_chain : 1;
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
int dnssec_roadblock_avoidance; int dnssec_roadblock_avoidance : 1;
int avoid_dnssec_roadblocks; int avoid_dnssec_roadblocks : 1;
#endif #endif
int edns_cookies; int edns_cookies : 1;
int edns_client_subnet_private; int edns_client_subnet_private : 1;
uint16_t tls_query_padding_blocksize; int return_call_reporting : 1;
int return_call_reporting; int add_warning_for_bad_dns : 1;
int add_warning_for_bad_dns;
/* Internally used by return_validation_chain */ /* Internally used by return_validation_chain */
int dnssec_ok_checking_disabled; int dnssec_ok_checking_disabled : 1;
int is_sync_request; int is_sync_request : 1;
/* The validating and freed variables are used to make sure a single
* code path is followed while processing a DNS request, even when
* callbacks are already fired whilst the registering/scheduling call
* (i.e. ub_resolve_event) has not returned yet.
*
* validating is touched by _getdns_get_validation_chain only and
* freed is touched by _getdns_submit_netreq only
*/
int validating : 1;
int *freed;
uint16_t tls_query_padding_blocksize;
/* internally scheduled request */ /* internally scheduled request */
internal_cb_t internal_cb; internal_cb_t internal_cb;

View File

@ -51,6 +51,7 @@
#include "gldns/str2wire.h" #include "gldns/str2wire.h"
#include "gldns/gbuffer.h" #include "gldns/gbuffer.h"
#include "gldns/pkthdr.h" #include "gldns/pkthdr.h"
#include "dnssec.h"
getdns_return_t getdns_return_t
@ -145,11 +146,12 @@ _getdns_sockaddr_to_dict(struct getdns_context *context, struct sockaddr_storage
} }
getdns_dict * getdns_dict *
_getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i) _getdns_rr_iter2rr_dict_canonical(
struct mem_funcs *mf, _getdns_rr_iter *i, uint32_t *orig_ttl)
{ {
getdns_dict *rr_dict, *rdata_dict; getdns_dict *rr_dict, *rdata_dict;
const uint8_t *bin_data; const uint8_t *bin_data;
size_t bin_size; size_t bin_size, owner_len = 0, rdata_sz;
uint32_t int_val = 0; uint32_t int_val = 0;
enum wf_data_type { wf_int, wf_bindata, wf_special } val_type; enum wf_data_type { wf_int, wf_bindata, wf_special } val_type;
_getdns_rdf_iter rdf_storage, *rdf; _getdns_rdf_iter rdf_storage, *rdf;
@ -157,6 +159,10 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
getdns_dict *repeat_dict = NULL; getdns_dict *repeat_dict = NULL;
uint8_t ff_bytes[256]; uint8_t ff_bytes[256];
uint16_t rr_type; uint16_t rr_type;
int canonicalize;
gldns_buffer gbuf;
getdns_bindata *bindata;
uint8_t *data;
assert(i); assert(i);
if (!(rr_dict = _getdns_dict_create_with_mf(mf))) if (!(rr_dict = _getdns_dict_create_with_mf(mf)))
@ -165,6 +171,12 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
bin_data = _getdns_owner_if_or_as_decompressed( bin_data = _getdns_owner_if_or_as_decompressed(
i, ff_bytes, &bin_size); i, ff_bytes, &bin_size);
if (orig_ttl) {
if (bin_data != ff_bytes)
bin_data = memcpy(ff_bytes, bin_data, bin_size);
_dname_canonicalize2(ff_bytes);
owner_len = bin_size;
}
/* question */ /* question */
if (_getdns_rr_iter_section(i) == GLDNS_SECTION_QUESTION) { if (_getdns_rr_iter_section(i) == GLDNS_SECTION_QUESTION) {
@ -186,6 +198,9 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
goto error; goto error;
} }
canonicalize = orig_ttl && _dnssec_rdata_to_canonicalize(rr_type)
&& (i->rr_type + 12 <= i->nxt) /* To estimate rdata size */;
if (rr_type == GETDNS_RRTYPE_OPT) { if (rr_type == GETDNS_RRTYPE_OPT) {
int_val = gldns_read_uint16(i->rr_type + 6); int_val = gldns_read_uint16(i->rr_type + 6);
@ -210,7 +225,8 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
(uint32_t) gldns_read_uint16(i->rr_type + 2)) || (uint32_t) gldns_read_uint16(i->rr_type + 2)) ||
getdns_dict_set_int(rr_dict, "ttl", getdns_dict_set_int(rr_dict, "ttl",
(uint32_t) gldns_read_uint32(i->rr_type + 4)) || ( orig_ttl && rr_type != GETDNS_RRTYPE_RRSIG
? *orig_ttl : (uint32_t) gldns_read_uint32(i->rr_type + 4))) ||
_getdns_dict_set_const_bindata( _getdns_dict_set_const_bindata(
rr_dict, "name", bin_size, bin_data)) { rr_dict, "name", bin_size, bin_data)) {
@ -220,15 +236,21 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
if (!(rdata_dict = _getdns_dict_create_with_mf(mf))) if (!(rdata_dict = _getdns_dict_create_with_mf(mf)))
return NULL; return NULL;
if (i->rr_type + 10 <= i->nxt) { if (i->rr_type + 10 <= i->nxt && !canonicalize) {
bin_size = i->nxt - (i->rr_type + 10); bin_size = i->nxt - (i->rr_type + 10);
bin_data = i->rr_type + 10; bin_data = i->rr_type + 10;
if (_getdns_dict_set_const_bindata( if (_getdns_dict_set_const_bindata(
rdata_dict, "rdata_raw", bin_size, bin_data)) rdata_dict, "rdata_raw", bin_size, bin_data))
goto rdata_error; goto rdata_error;
} }
if (canonicalize)
rdata_sz = 0;
for ( rdf = _getdns_rdf_iter_init(&rdf_storage, i) for ( rdf = _getdns_rdf_iter_init(&rdf_storage, i)
; rdf; rdf = _getdns_rdf_iter_next(rdf)) { ; rdf; rdf = _getdns_rdf_iter_next(rdf)) {
if (canonicalize && !(rdf->rdd_pos->type & GETDNS_RDF_DNAME)) {
rdata_sz += rdf->nxt - rdf->pos;
}
if (rdf->rdd_pos->type & GETDNS_RDF_INTEGER) { if (rdf->rdd_pos->type & GETDNS_RDF_INTEGER) {
val_type = wf_int; val_type = wf_int;
switch (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) { switch (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) {
@ -247,6 +269,12 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
bin_data = _getdns_rdf_if_or_as_decompressed( bin_data = _getdns_rdf_if_or_as_decompressed(
rdf, ff_bytes, &bin_size); rdf, ff_bytes, &bin_size);
if (canonicalize) {
if (bin_data != ff_bytes)
bin_data = memcpy(ff_bytes, bin_data, bin_size);
_dname_canonicalize2(ff_bytes);
rdata_sz += bin_size;
}
} else if (rdf->rdd_pos->type & GETDNS_RDF_BINDATA) { } else if (rdf->rdd_pos->type & GETDNS_RDF_BINDATA) {
val_type = wf_bindata; val_type = wf_bindata;
if (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) { if (rdf->rdd_pos->type & GETDNS_RDF_FIXEDSZ) {
@ -376,6 +404,23 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
if (_getdns_dict_set_this_dict(rr_dict, "rdata", rdata_dict)) if (_getdns_dict_set_this_dict(rr_dict, "rdata", rdata_dict))
goto rdata_error; goto rdata_error;
if (canonicalize && rdata_sz) {
if (!(data = GETDNS_XMALLOC(
*mf, uint8_t, owner_len + 10 + rdata_sz)))
return rr_dict;
gldns_buffer_init_frm_data(&gbuf, data, owner_len+10+rdata_sz);
if (_getdns_rr_dict2wire(rr_dict, &gbuf) ||
gldns_buffer_position(&gbuf) != owner_len + 10 + rdata_sz ||
!(bindata = GETDNS_MALLOC(*mf, struct getdns_bindata))) {
GETDNS_FREE(*mf, data);
return rr_dict;
}
bindata->size = rdata_sz;
bindata->data = memmove(data, data + owner_len + 10, rdata_sz);
(void) _getdns_dict_set_this_bindata(rr_dict,
"/rdata/rdata_raw", bindata);
}
return rr_dict; return rr_dict;
rdata_error: rdata_error:
@ -387,6 +432,12 @@ error:
return NULL; return NULL;
} }
getdns_dict *
_getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i)
{
return _getdns_rr_iter2rr_dict_canonical(mf, i, NULL);
}
int int
_getdns_dname_equal(const uint8_t *s1, const uint8_t *s2) _getdns_dname_equal(const uint8_t *s1, const uint8_t *s2)
{ {

View File

@ -41,6 +41,7 @@
#include "config.h" #include "config.h"
#include "context.h" #include "context.h"
#include "rr-iter.h" #include "rr-iter.h"
#include <ctype.h>
#define UNCONST_UINT8_p uint8_t * #define UNCONST_UINT8_p uint8_t *
@ -95,6 +96,9 @@ getdns_return_t _getdns_dict_set_this_list(getdns_dict *dict,
getdns_return_t _getdns_dict_set_const_bindata(getdns_dict *dict, getdns_return_t _getdns_dict_set_const_bindata(getdns_dict *dict,
const char *name, size_t size, const void *data); const char *name, size_t size, const void *data);
getdns_return_t _getdns_dict_set_this_bindata(getdns_dict *dict,
const char *name, getdns_bindata *child_bindata);
/** /**
* private function (API users should not be calling this), this uses library * private function (API users should not be calling this), this uses library
* routines to make a copy of the list - would be faster to make the copy directly * routines to make a copy of the list - would be faster to make the copy directly
@ -138,6 +142,10 @@ getdns_return_t _getdns_sockaddr_to_dict(struct getdns_context *context,
getdns_dict * getdns_dict *
_getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i); _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i);
getdns_dict *
_getdns_rr_iter2rr_dict_canonical(
struct mem_funcs *mf, _getdns_rr_iter *i, uint32_t *orig_ttl);
struct getdns_dns_req; struct getdns_dns_req;
struct getdns_dict *_getdns_create_getdns_response(struct getdns_dns_req *completed_request); struct getdns_dict *_getdns_create_getdns_response(struct getdns_dns_req *completed_request);
@ -178,5 +186,22 @@ INLINE getdns_eventloop_event *getdns_eventloop_event_init(
#define GETDNS_SCHEDULE_EVENT(loop, fd, timeout, event) \ #define GETDNS_SCHEDULE_EVENT(loop, fd, timeout, event) \
do { (loop)->vmt->schedule((loop),(fd),(timeout),(event)); } while(0) do { (loop)->vmt->schedule((loop),(fd),(timeout),(event)); } while(0)
INLINE void _dname_canonicalize(const uint8_t *src, uint8_t *dst)
{
const uint8_t *next_label;
while (*src) {
next_label = src + *src + 1;
*dst++ = *src++;
while (src < next_label)
*dst++ = (uint8_t)tolower((unsigned char)*src++);
}
}
INLINE void _dname_canonicalize2(uint8_t *dname)
{
_dname_canonicalize(dname, dname);
}
#endif #endif
/* util-internal.h */ /* util-internal.h */