@@ -26,7 +26,6 @@ struct Nameserver {
2626};
2727
2828struct Zone {
29- // Do not use the zone whose nameserver is being resolved.
3029 bool is_being_resolved{false };
3130 std::string domain;
3231 bool enable_edns;
@@ -195,11 +194,11 @@ std::shared_ptr<Zone> Resolver::SafetyBelt::next() {
195194std::queue<std::shared_ptr<Zone>> Resolver::init_safety_belt (const ResolverConfig &config) const {
196195 std::queue<std::shared_ptr<Zone>> zones;
197196
198- if (dnssec != FeatureState::Require) {
199- // Only the root zone can be used with DNSSEC because it is the only trust anchor.
200- if (config.nameserver .has_value ()) zones.push (new_zone_from_nameserver (config.nameserver .value ()));
201- if (config.use_resolve_config ) zones.push (load_resolve_config ());
197+ if (config.nameserver .has_value ()) {
198+ auto zone = new_zone_from_config (config.nameserver .value ());
199+ if (zone->enable_dnssec || dnssec != FeatureState::Require) zones.push (std::move (zone));
202200 }
201+ if (config.use_resolve_config && dnssec != FeatureState::Require) zones.push (load_resolve_config ());
203202 if (config.use_root_nameservers ) zones.push (new_root_zone ());
204203
205204 if (zones.empty ()) throw std::runtime_error (" No nameserver is specified" );
@@ -255,13 +254,18 @@ std::shared_ptr<Zone> Resolver::load_resolve_config() const {
255254 return zone;
256255}
257256
258- std::shared_ptr<Zone> Resolver::new_zone_from_nameserver (const std::string &address_or_domain) const {
259- auto zone = new_zone (" ." , false );
257+ std::shared_ptr<Zone> Resolver::new_zone_from_config (const NameserverConfig &config) const {
258+ auto zone_domain = config.zone_domain .has_value () ? fully_qualify_domain (config.zone_domain .value ()) : " ." ;
259+ bool enable_dnssec = config.zone_domain .has_value () && (!config.dss .empty () || !config.dnskeys .empty ());
260+ auto zone = new_zone (zone_domain, enable_dnssec);
261+ zone->dss = config.dss ;
262+ zone->dnskeys = config.dnskeys ;
263+
260264 in_addr_t ip_address;
261- if (inet_pton (AF_INET, address_or_domain .c_str (), &ip_address) == 1 ) {
265+ if (inet_pton (AF_INET, config. address .c_str (), &ip_address) == 1 ) {
262266 zone->add_nameserver (ip_address);
263267 } else {
264- zone->add_nameserver (address_or_domain );
268+ zone->add_nameserver (fully_qualify_domain (config. address ) );
265269 }
266270 return zone;
267271}
@@ -343,17 +347,17 @@ bool Resolver::authenticate_rrset(const std::vector<RR> &rrset, RRType rr_type,
343347 const Zone &zone) const {
344348 if (rrset.empty ()) return true ;
345349
346- if (rr_type != RRType::DNSKEY) {
347- return dnssec::authenticate_rrset (rrset, rrsigs, zone.dnskeys , nsec3_rrset, nsec_rrset, zone.domain );
348- }
350+ if (rr_type == RRType::DNSKEY && zone.dnskeys .empty ()) {
351+ if (!zone.dss .empty ()) {
352+ return dnssec::authenticate_delegation (rrset, zone.dss , rrsigs, nsec3_rrset, nsec_rrset, zone.domain );
353+ }
349354
350- if (!zone.dss .empty ()) {
351- return dnssec::authenticate_delegation (rrset, zone.dss , rrsigs, nsec3_rrset, nsec_rrset, zone.domain );
355+ // There is no secure delegation, so just verify that the RRSIG was signed with one of these DNSKEYs.
356+ auto dnskeys = rrset_to_data<DNSKEY>(rrset);
357+ return dnssec::authenticate_rrset (rrset, rrsigs, dnskeys, nsec3_rrset, nsec_rrset, zone.domain );
352358 }
353359
354- // There is no secure delegation, so just verify that the RRSIG was signed with one of these DNSKEYs.
355- auto dnskeys = rrset_to_data<DNSKEY>(rrset);
356- return dnssec::authenticate_rrset (rrset, rrsigs, dnskeys, nsec3_rrset, nsec_rrset, zone.domain );
360+ return dnssec::authenticate_rrset (rrset, rrsigs, zone.dnskeys , nsec3_rrset, nsec_rrset, zone.domain );
357361}
358362
359363std::vector<RR> Resolver::get_unauthenticated_rrset (std::vector<RR> &rrset, RRType rr_type) {
@@ -472,8 +476,11 @@ std::optional<std::vector<RR>> Resolver::resolve_rec(const std::string &domain,
472476 next_zone = nullptr ;
473477
474478 // Get zone's DNSKEYs.
475- if (zone->enable_dnssec && zone->dnskeys .empty () && rr_type != RRType::DNSKEY) {
479+ if (zone->enable_dnssec && zone->dnskeys .empty () && !zone->is_being_resolved ) {
480+ zone->is_being_resolved = true ;
476481 auto dnskey_rrset = resolve_rec (zone->domain , RRType::DNSKEY, depth + 1 , zone);
482+ zone->is_being_resolved = false ;
483+
477484 if (dnskey_rrset.has_value () && !dnskey_rrset->empty ()) {
478485 zone->dnskeys = rrset_to_data<DNSKEY>(std::move (dnskey_rrset.value ()));
479486 } else {
@@ -633,7 +640,7 @@ std::optional<std::vector<RR>> Resolver::resolve_rec(const std::string &domain,
633640 }
634641 referral_zone = new_zone (ns_rr.domain );
635642 } else if (ns_rr.domain != referral_zone->domain ) {
636- throw std::runtime_error (std::format (" Authority contains multiple referrals: {} and {} " ,
643+ throw std::runtime_error (std::format (" Authority contains multiple referrals: \" {} \" and \" {} \" " ,
637644 ns_rr.domain , referral_zone->domain ));
638645 }
639646
@@ -693,9 +700,8 @@ std::optional<std::vector<RR>> Resolver::resolve_rec(const std::string &domain,
693700 // Retry the same nameserver with the new server cookie once.
694701 i--;
695702 nameserver->sent_bad_cookie = true ;
696- } else {
697- // Try a different nameserver.
698703 }
704+ // Try a different nameserver.
699705 } catch (const std::exception &e) {
700706 // Nameserver error, try asking the different nameserver if there are any left.
701707 if (verbose) std::println (stderr, " Failed to resolve the domain: {}." , e.what ());
0 commit comments