From 36943a438090a5229de06599a1950d495507a38e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 20 Sep 2017 14:42:35 +0200 Subject: [PATCH] A dnsreq is bogus if any of its netreqs is --- src/dnssec.c | 37 ++++++++++++++++++++++--------------- src/dnssec.h | 2 ++ src/general.c | 33 ++++++++++++++++++++------------- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/dnssec.c b/src/dnssec.c index da0f92b1..3a2fc866 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -3036,6 +3036,17 @@ static inline chain_node *_to_the_root(chain_node *node) return node; } +int _getdns_bogus(getdns_dns_req *dnsreq) +{ + getdns_network_req **netreq_p, *netreq; + + for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) { + if (netreq->dnssec_status == GETDNS_DNSSEC_BOGUS) + return 1; + } + return 0; +} + static void check_chain_complete(chain_head *chain) { getdns_dns_req *dnsreq; @@ -3075,22 +3086,13 @@ static void check_chain_complete(chain_head *chain) } } #ifdef STUB_NATIVE_DNSSEC - /* Perform validation only on GETDNS_RESOLUTION_STUB (unbound_id == -1) - * Or when asked for the validation chain (to identify the RRSIGs that - * signed the RRSETs, so that only those will be included in the - * validation chain) - * In any case we must have a trust anchor. - */ - if (( chain->netreq->unbound_id == -1 - || dnsreq->dnssec_return_validation_chain) - && context->trust_anchors) + if (context->trust_anchors) chain_set_netreq_dnssec_status(chain,_getdns_rrset_iter_init(&tas_iter, context->trust_anchors, context->trust_anchors_len, SECTION_ANSWER)); #else - if (dnsreq->dnssec_return_validation_chain - && context->trust_anchors) + if (context->trust_anchors) (void) chain_validate_dnssec(priv_getdns_context_mf(context), time(NULL), context->dnssec_allowed_skew, @@ -3104,13 +3106,14 @@ static void check_chain_complete(chain_head *chain) node->dnskey.name && *node->dnskey.name == 0) _getdns_context_update_root_ksk(context,&node->dnskey); - } else if (dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) { + } else if (_getdns_bogus(dnsreq)) { DEBUG_ANCHOR("Request was bogus!\n"); + if ((head = chain) && (node = _to_the_root(head->parent)) && node->dnskey.name && *node->dnskey.name == 0 && node->dnskey_req->dnssec_status == GETDNS_DNSSEC_BOGUS){ - DEBUG_ANCHOR("ROOT DNSKEY set was bogus!\n"); + DEBUG_ANCHOR("root DNSKEY set was bogus!\n"); if (!dnsreq->waiting_for_ta) { uint64_t now = 0; @@ -3143,7 +3146,7 @@ static void check_chain_complete(chain_head *chain) #ifdef DNSSEC_ROADBLOCK_AVOIDANCE if ( dnsreq->dnssec_roadblock_avoidance && !dnsreq->avoid_dnssec_roadblocks - && dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) { + && _getdns_bogus(dnsreq)) { getdns_network_req **netreq_p, *netreq; uint64_t now_ms = 0; @@ -3381,6 +3384,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq) if (dnsreq->avoid_dnssec_roadblocks && chain->lock == 0) ; /* pass */ + else for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) { if (! netreq->response || netreq->response_len < GLDNS_HEADER_SIZE @@ -3391,7 +3395,10 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq) netreq->dnssec_status = GETDNS_DNSSEC_INSECURE; continue; - } + + } else if (netreq->unbound_id != -1) + netreq->dnssec_status = GETDNS_DNSSEC_INDETERMINATE; + add_pkt2val_chain( &dnsreq->my_mf, &chain , netreq->response, netreq->response_len , netreq diff --git a/src/dnssec.h b/src/dnssec.h index 3ffa96ee..ef1b4747 100644 --- a/src/dnssec.h +++ b/src/dnssec.h @@ -67,6 +67,8 @@ static inline int _dnssec_rdata_to_canonicalize(uint16_t rr_type) || rr_type == GLDNS_RR_TYPE_DNAME || rr_type == GLDNS_RR_TYPE_RRSIG; } +int _getdns_bogus(getdns_dns_req *dns_req); + #endif /* dnssec.h */ diff --git a/src/general.c b/src/general.c index 72e7840a..d8a2bdf8 100644 --- a/src/general.c +++ b/src/general.c @@ -214,13 +214,15 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) #endif #ifdef STUB_NATIVE_DNSSEC - || (dns_req->context->resolution_type == GETDNS_RESOLUTION_STUB + || ( dns_req->context->resolution_type == GETDNS_RESOLUTION_STUB && !dns_req->avoid_dnssec_roadblocks && (dns_req->dnssec_return_status || dns_req->dnssec_return_only_secure || dns_req->dnssec_return_all_statuses )) #endif + || ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING + && _getdns_bogus(dns_req)) )) { /* Reschedule timeout for this DNS request */ @@ -236,6 +238,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) #if defined(REQ_DEBUG) && REQ_DEBUG debug_req("getting validation chain for ", *dns_req->netreqs); #endif + DEBUG_ANCHOR("Valchain lookup\n"); _getdns_get_validation_chain(dns_req); } else _getdns_call_user_callback( @@ -594,22 +597,18 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, _getdns_context_equip_with_anchor(context, &now_ms); if (context->trust_anchors_source == GETDNS_TASRC_NONE) { _getdns_start_fetching_ta(context, loop); - if (context->trust_anchors_source - == GETDNS_TASRC_FETCHING - && context->resolution_type - == GETDNS_RESOLUTION_RECURSING - && context->resolution_type - != context->resolution_type_set) { - - req->waiting_for_ta = 1; - req->ta_notify = context->ta_notify; - context->ta_notify = req; - return GETDNS_RETURN_GOOD; - } } } } if (!usenamespaces) { + if (context->trust_anchors_source == GETDNS_TASRC_FETCHING + && context->resolution_type == GETDNS_RESOLUTION_RECURSING + && context->resolution_type != context->resolution_type_set) { + req->waiting_for_ta = 1; + req->ta_notify = context->ta_notify; + context->ta_notify = req; + return GETDNS_RETURN_GOOD; + } (void) _getdns_context_prepare_for_resolution(context, 0); /* issue all network requests */ @@ -660,6 +659,14 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, } #endif /* HAVE_MDNS_SUPPORT */ } else if (context->namespaces[i] == GETDNS_NAMESPACE_DNS) { + if (context->trust_anchors_source == GETDNS_TASRC_FETCHING + && context->resolution_type == GETDNS_RESOLUTION_RECURSING + && context->resolution_type != context->resolution_type_set) { + req->waiting_for_ta = 1; + req->ta_notify = context->ta_notify; + context->ta_notify = req; + return GETDNS_RETURN_GOOD; + } (void) _getdns_context_prepare_for_resolution(context, 0); /* TODO: We will get a good return code here even if