mirror of https://github.com/getdnsapi/getdns.git
Merge pull request #351 from getdnsapi/devel/dnssec_maintenance
Devel/dnssec maintenance
This commit is contained in:
commit
e078f3c51a
|
@ -1,4 +1,10 @@
|
||||||
* 2017-1?-??: Version 1.2.1
|
* 2017-1?-??: Version 1.2.1
|
||||||
|
* Bugfix: Tolerate unsigned and unused RRsets in the authority section.
|
||||||
|
Fixes DNSSEC with BIND upstream.
|
||||||
|
* Bugfix: DNSSEC validation without support records
|
||||||
|
* Bugfix: Validation of full recursive DNSKEY lookups
|
||||||
|
* Bugfix: Retry to validate full recursion BOGUS replies with zero
|
||||||
|
configuration DNSSEC only when DNSSEC was actually requested
|
||||||
* Bugfix #348: Fix a linking issue in stubby when libbsd is present
|
* Bugfix #348: Fix a linking issue in stubby when libbsd is present
|
||||||
Thanks Remi Gacogne
|
Thanks Remi Gacogne
|
||||||
* More robust scheduling; Eliminating a segfault with long running
|
* More robust scheduling; Eliminating a segfault with long running
|
||||||
|
|
82
src/dnssec.c
82
src/dnssec.c
|
@ -802,11 +802,14 @@ static void add_pkt2val_chain(struct mem_funcs *mf,
|
||||||
if (is_synthesized_cname(rrset))
|
if (is_synthesized_cname(rrset))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!(rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset))
|
||||||
|
&& _getdns_rr_iter_section(&i->rr_i) != SECTION_ANSWER)
|
||||||
|
continue; /* No sigs in authority section is okayish */
|
||||||
|
|
||||||
if (!(head = add_rrset2val_chain(mf, chain_p, rrset, netreq)))
|
if (!(head = add_rrset2val_chain(mf, chain_p, rrset, netreq)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset), n_rrsigs = 0
|
for ( n_rrsigs = 0; rrsig
|
||||||
; rrsig
|
|
||||||
; rrsig = _getdns_rrsig_iter_next(rrsig), n_rrsigs++) {
|
; rrsig = _getdns_rrsig_iter_next(rrsig), n_rrsigs++) {
|
||||||
|
|
||||||
/* Signature, so lookup DS/DNSKEY at signer's name */
|
/* Signature, so lookup DS/DNSKEY at signer's name */
|
||||||
|
@ -934,6 +937,17 @@ static void val_chain_sched_soa(chain_head *head, const uint8_t *dname)
|
||||||
val_chain_sched_soa_node(node);
|
val_chain_sched_soa_node(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static chain_head *_dnskey_query(const chain_node *node)
|
||||||
|
{
|
||||||
|
chain_head *head;
|
||||||
|
|
||||||
|
for (head = node->chains; head; head = head->next)
|
||||||
|
if (head->rrset.rr_type == GETDNS_RRTYPE_DNSKEY &&
|
||||||
|
head->parent == node)
|
||||||
|
return head;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void val_chain_node_cb(getdns_dns_req *dnsreq);
|
static void val_chain_node_cb(getdns_dns_req *dnsreq);
|
||||||
static void val_chain_sched_node(chain_node *node)
|
static void val_chain_sched_node(chain_node *node)
|
||||||
{
|
{
|
||||||
|
@ -951,13 +965,27 @@ static void val_chain_sched_node(chain_node *node)
|
||||||
DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name);
|
DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name);
|
||||||
|
|
||||||
node->lock++;
|
node->lock++;
|
||||||
if (! node->dnskey_req /* not scheduled */ &&
|
if (! node->dnskey_req) {
|
||||||
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY,
|
chain_head *head;
|
||||||
CD_extension(node->chains->netreq->owner),
|
|
||||||
node, &node->dnskey_req, NULL, val_chain_node_cb))
|
|
||||||
|
|
||||||
node->dnskey_req = NULL;
|
/* Reuse the DNSKEY query if this node is scheduled in the
|
||||||
|
* context of validating a DNSKEY query, because libunbound
|
||||||
|
* does not callback from a callback for the same query.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((head = _dnskey_query(node))) {
|
||||||
|
DEBUG_SEC("Found DNSKEY head: %p\n", (void *)head);
|
||||||
|
node->dnskey_req = head->netreq;
|
||||||
|
node->dnskey.pkt = head->netreq->response;
|
||||||
|
node->dnskey.pkt_len = head->netreq->response_len;
|
||||||
|
|
||||||
|
} else if (_getdns_general_loop(
|
||||||
|
context, loop, name, GETDNS_RRTYPE_DNSKEY,
|
||||||
|
CD_extension(node->chains->netreq->owner),
|
||||||
|
node, &node->dnskey_req, NULL, val_chain_node_cb))
|
||||||
|
|
||||||
|
node->dnskey_req = NULL;
|
||||||
|
}
|
||||||
if (! node->ds_req && node->parent /* not root */ &&
|
if (! node->ds_req && node->parent /* not root */ &&
|
||||||
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS,
|
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS,
|
||||||
CD_extension(node->chains->netreq->owner),
|
CD_extension(node->chains->netreq->owner),
|
||||||
|
@ -2523,6 +2551,11 @@ static int chain_node_get_trusted_keys(
|
||||||
node->dnskey_signer = keytag;
|
node->dnskey_signer = keytag;
|
||||||
return GETDNS_DNSSEC_SECURE;
|
return GETDNS_DNSSEC_SECURE;
|
||||||
}
|
}
|
||||||
|
/* ta is the DNSKEY for this name? */
|
||||||
|
if (_dname_equal(ta->name, node->dnskey.name)) {
|
||||||
|
*keys = ta;
|
||||||
|
return GETDNS_DNSSEC_SECURE;
|
||||||
|
}
|
||||||
/* ta is parent's ZSK */
|
/* ta is parent's ZSK */
|
||||||
if ((keytag = key_proves_nonexistance(
|
if ((keytag = key_proves_nonexistance(
|
||||||
mf, now, skew, ta, &node->ds, NULL))) {
|
mf, now, skew, ta, &node->ds, NULL))) {
|
||||||
|
@ -2938,6 +2971,26 @@ static void append_rrset2val_chain_list(
|
||||||
_getdns_list_append_this_dict(val_chain_list, rr_dict))
|
_getdns_list_append_this_dict(val_chain_list, rr_dict))
|
||||||
getdns_dict_destroy(rr_dict);
|
getdns_dict_destroy(rr_dict);
|
||||||
|
|
||||||
|
/* Append the other RRSIGs, which were not used for validation too,
|
||||||
|
* because other validators might not have the same algorithm support.
|
||||||
|
*/
|
||||||
|
for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
|
||||||
|
; rrsig
|
||||||
|
; rrsig = _getdns_rrsig_iter_next(rrsig)) {
|
||||||
|
|
||||||
|
if (rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (gldns_read_uint16(rrsig->rr_i.rr_type + 26)
|
||||||
|
== (signer & 0xFFFF))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
|
||||||
|
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)
|
if (val_rrset != val_rrset_spc)
|
||||||
GETDNS_FREE(val_chain_list->mf, val_rrset);
|
GETDNS_FREE(val_chain_list->mf, val_rrset);
|
||||||
}
|
}
|
||||||
|
@ -3341,7 +3394,7 @@ void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq)
|
||||||
|
|
||||||
void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
|
void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
|
||||||
{
|
{
|
||||||
chain_head *head = dnsreq->chain, *next;
|
chain_head *head = dnsreq->chain, *next, *dnskey_head;
|
||||||
chain_node *node;
|
chain_node *node;
|
||||||
size_t node_count;
|
size_t node_count;
|
||||||
|
|
||||||
|
@ -3353,7 +3406,10 @@ void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
|
||||||
; node_count
|
; node_count
|
||||||
; node_count--, node = node->parent ) {
|
; node_count--, node = node->parent ) {
|
||||||
|
|
||||||
if (node->dnskey_req)
|
if (node->dnskey_req &&
|
||||||
|
!( (dnskey_head = _dnskey_query(node))
|
||||||
|
&& dnskey_head->netreq == node->dnskey_req))
|
||||||
|
|
||||||
_getdns_context_cancel_request(
|
_getdns_context_cancel_request(
|
||||||
node->dnskey_req->owner);
|
node->dnskey_req->owner);
|
||||||
|
|
||||||
|
@ -3537,13 +3593,17 @@ getdns_validate_dnssec2(getdns_list *records_to_validate,
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!records_to_validate || !support_records || !trust_anchors)
|
if (!records_to_validate || !trust_anchors)
|
||||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
mf = &records_to_validate->mf;
|
mf = &records_to_validate->mf;
|
||||||
|
|
||||||
/* First convert everything to wire format
|
/* First convert everything to wire format
|
||||||
*/
|
*/
|
||||||
if (!(support = _getdns_list2wire(support_records,
|
|
||||||
|
if (!support_records)
|
||||||
|
(void) memset((support = support_buf), 0, GLDNS_HEADER_SIZE);
|
||||||
|
|
||||||
|
else if (!(support = _getdns_list2wire(support_records,
|
||||||
support_buf, &support_len, mf)))
|
support_buf, &support_len, mf)))
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,10 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
||||||
dns_req->dnssec_return_all_statuses
|
dns_req->dnssec_return_all_statuses
|
||||||
))
|
))
|
||||||
#endif
|
#endif
|
||||||
|| ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
|| ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
||||||
|
&& (dns_req->dnssec_return_status ||
|
||||||
|
dns_req->dnssec_return_only_secure ||
|
||||||
|
dns_req->dnssec_return_all_statuses)
|
||||||
&& _getdns_bogus(dns_req))
|
&& _getdns_bogus(dns_req))
|
||||||
)) {
|
)) {
|
||||||
/* Reschedule timeout for this DNS request
|
/* Reschedule timeout for this DNS request
|
||||||
|
@ -446,14 +449,12 @@ _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms)
|
||||||
if (_getdns_ub_loop_enabled(&context->ub_loop))
|
if (_getdns_ub_loop_enabled(&context->ub_loop))
|
||||||
ub_resolve_r = ub_resolve_event(context->unbound_ctx,
|
ub_resolve_r = ub_resolve_event(context->unbound_ctx,
|
||||||
name, netreq->request_type, dns_req->request_class,
|
name, netreq->request_type, dns_req->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;
|
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
ub_resolve_r = ub_resolve_async(context->unbound_ctx,
|
ub_resolve_r = ub_resolve_async(context->unbound_ctx,
|
||||||
name, netreq->request_type, dns_req->request_class,
|
name, netreq->request_type, dns_req->request_class,
|
||||||
netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
|
netreq, ub_resolve_callback, &(netreq->unbound_id));
|
||||||
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
|
||||||
if (dnsreq_freed)
|
if (dnsreq_freed)
|
||||||
return DNS_REQ_FINISHED;
|
return DNS_REQ_FINISHED;
|
||||||
dns_req->freed = NULL;
|
dns_req->freed = NULL;
|
||||||
|
|
Loading…
Reference in New Issue