From e29cfb6b6a0afb21600a655a5ba6bbc0daf52ad9 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 2 Mar 2018 14:14:28 +0100 Subject: [PATCH] Query for DS i.s.o. SOA to find zonecuts Because of broken setups that have zonecuts without SOA: ``` $ drill -T www.gslb.kpn.com A . 518400 IN NS i.root-servers.net. com. 172800 IN NS a.gtld-servers.net. kpn.com. 172800 IN NS ns1.kpn.net. kpn.com. 172800 IN NS ns2.kpn.net. gslb.kpn.com. 3600 IN NS gss1.kpn.com. gslb.kpn.com. 3600 IN NS gss2.kpn.com. www.gslb.kpn.com. 10 IN A 145.7.170.135 ``` but ``` $ drill gslb.kpn.com SOA ;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 48303 ;; flags: qr rd ra ; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;; gslb.kpn.com. IN SOA ;; ANSWER SECTION: ;; AUTHORITY SECTION: ;; ADDITIONAL SECTION: ;; Query time: 8 msec ;; SERVER: 185.49.140.100 ;; WHEN: Fri Mar 2 14:13:21 2018 ;; MSG SIZE rcvd: 30 ``` --- src/dnssec.c | 137 ++++++--------------------------------------------- 1 file changed, 14 insertions(+), 123 deletions(-) diff --git a/src/dnssec.c b/src/dnssec.c index 8ebafc5a..6a434f08 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -506,8 +506,6 @@ struct chain_node { getdns_network_req *ds_req; int ds_signer; - getdns_network_req *soa_req; - chain_head *chains; }; @@ -521,7 +519,6 @@ struct chain_node { static void val_chain_sched(chain_head *head, const uint8_t *dname); static void val_chain_sched_ds(chain_head *head, const uint8_t *dname); static void val_chain_sched_signer(chain_head *head, _getdns_rrsig_iter *rrsig); -static void val_chain_sched_soa(chain_head *head, const uint8_t *dname); static chain_head *add_rrset2val_chain(struct mem_funcs *mf, chain_head **chain_p, _getdns_rrset *rrset, getdns_network_req *netreq) @@ -663,7 +660,6 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf, node->dnskey.sections = head->rrset.sections; node->ds_req = NULL; node->dnskey_req = NULL; - node->soa_req = NULL; node->ds_signer = -1; node->dnskey_signer = -1; @@ -822,9 +818,9 @@ static void add_pkt2val_chain(struct mem_funcs *mf, if (rrset->rr_type == GETDNS_RRTYPE_SOA) val_chain_sched_ds(head, rrset->name); else if (rrset->rr_type == GETDNS_RRTYPE_CNAME) - val_chain_sched_soa(head, rrset->name + *rrset->name + 1); + val_chain_sched_ds(head, rrset->name + *rrset->name + 1); else - val_chain_sched_soa(head, rrset->name); + val_chain_sched_ds(head, rrset->name); } } @@ -841,6 +837,7 @@ static void add_question2val_chain(struct mem_funcs *mf, _getdns_rrset_iter *i, i_spc; _getdns_rrset *rrset; _getdns_rrsig_iter rrsig_spc; + size_t n_soas; _getdns_rrset_spc q_rrset; chain_head *head; @@ -867,26 +864,29 @@ static void add_question2val_chain(struct mem_funcs *mf, debug_sec_print_rrset("Adding NX rrset: ", &q_rrset.rrset); head = add_rrset2val_chain(mf, chain_p, &q_rrset.rrset, netreq); - /* On empty packet, find SOA (zonecut) for the qname */ - if (head && GLDNS_ANCOUNT(pkt) == 0 && GLDNS_NSCOUNT(pkt) == 0) { - val_chain_sched_soa(head, q_rrset.rrset.name); - return; - } /* Insecure SOA indicating a zonecut in the authority section? * Then schedule a DS query at the zonecut for insecure proof. */ + n_soas = 0; for ( i = _getdns_rrset_iter_init(&i_spc, pkt, pkt_len , SECTION_AUTHORITY) ; i ; i = _getdns_rrset_iter_next(i)) { rrset = _getdns_rrset_iter_value(i); debug_sec_print_rrset("rrset: ", rrset); - if (rrset->rr_type != GETDNS_RRTYPE_SOA || - _getdns_rrsig_iter_init(&rrsig_spc, rrset)) + if (rrset->rr_type != GETDNS_RRTYPE_SOA) + continue; + + n_soas += 1; + + if (_getdns_rrsig_iter_init(&rrsig_spc, rrset)) continue; val_chain_sched_ds(head, rrset->name); } + /* No answer and no SOA indicating a zonecut? Find zonecut */ + if (n_soas == 0) + val_chain_sched_ds(head, q_rrset.rrset.name); } @@ -908,55 +908,6 @@ static getdns_dict *CD_extension(getdns_dns_req *dnsreq) } static void check_chain_complete(chain_head *chain); -static void val_chain_node_soa_cb(getdns_dns_req *dnsreq); -static void val_chain_sched_soa_node(chain_node *node) -{ - getdns_context *context; - getdns_eventloop *loop; - char name[1024]; - - context = node->chains->netreq->owner->context; - loop = node->chains->netreq->owner->loop; - - if (!gldns_wire2str_dname_buf( - (UNCONST_UINT8_p)node->ds.name, 256, name, sizeof(name))) - return; - - DEBUG_SEC("schedule SOA lookup for %s\n", name); - - node->lock++; - if (! node->soa_req && - _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_SOA, - CD_extension(node->chains->netreq->owner), node, &node->soa_req, - NULL, val_chain_node_soa_cb)) - - node->soa_req = NULL; - - if (node->lock) node->lock--; -} - -/* A SOA lookup is scheduled as a last resort. No signatures were found and - * no SOA in the authority section. If a SOA query returns an actual SOA - * answer, then a DS/DNSKEY lookup will follow the acquire the link of the - * authentication chain. - */ -static void val_chain_sched_soa(chain_head *head, const uint8_t *dname) -{ - chain_node *node; - - if (!head->netreq) - return; - - if (!*dname) - return; - - for ( node = head->parent - ; node && !_dname_equal(dname, node->ds.name) - ; node = node->parent); - - if (node) - val_chain_sched_soa_node(node); -} static chain_head *_dnskey_query(const chain_node *node) { @@ -1145,60 +1096,13 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq) /* No signed DS and no signed proof of non-existance. * Search further up the tree... */ - val_chain_sched_soa_node(node->parent); + val_chain_sched_ds_node(node->parent); if (node->lock) node->lock--; check_chain_complete(node->chains); } -static void val_chain_node_soa_cb(getdns_dns_req *dnsreq) -{ - chain_node *node = (chain_node *)dnsreq->user_pointer; - getdns_network_req *netreq = dnsreq->netreqs[0]; - _getdns_rrset_iter i_spc, *i; - _getdns_rrset *rrset; - - /* A SOA query is always scheduled with a node as the user argument. - */ - assert(node != NULL); - - for ( i = _getdns_rrset_iter_init(&i_spc, netreq->response - , netreq->response_len - , SECTION_ANSWER) - ; i - ; i = _getdns_rrset_iter_next(i)) { - - rrset = _getdns_rrset_iter_value(i); - if (rrset->rr_type != GETDNS_RRTYPE_SOA) - continue; - - while (node && - ! _dname_equal(node->ds.name, rrset->name)) - node = node->parent; - - if (node) { - node->lock++; - val_chain_sched_ds_node(node); - } else { - /* SOA for a different name */ - node = (chain_node *)dnsreq->user_pointer; - if (node->parent) { - node->lock++; - val_chain_sched_soa_node(node->parent); - } - } - break; - } - if (!i && node->parent) { - node->lock++; - val_chain_sched_soa_node(node->parent); - } - if (node->lock) node->lock--; - check_chain_complete(node->chains); -} - - /*************************** DNSSEC Validation ***************************** *****************************************************************************/ @@ -2923,9 +2827,6 @@ static size_t count_outstanding_requests(chain_head *head) if (!_getdns_netreq_finished(node->ds_req)) count++; - - if (!_getdns_netreq_finished(node->soa_req)) - count++; } return count + count_outstanding_requests(head->next); } @@ -3433,12 +3334,6 @@ void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq) node->ds_req->owner); node->ds_req = NULL; } - - if (!_getdns_netreq_finished(node->soa_req)) { - _getdns_context_cancel_request( - node->soa_req->owner); - node->soa_req = NULL; - } } head = next; } @@ -3478,10 +3373,6 @@ void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq) if (node->ds_req) _getdns_context_cancel_request( node->ds_req->owner); - - if (node->soa_req) - _getdns_context_cancel_request( - node->soa_req->owner); } GETDNS_FREE(head->my_mf, head); head = next;