- let dnskeys = inp.iter()
- .filter_map(|rr| if let RR::DnsKey(dnskey) = rr { Some(dnskey) } else { None })
- .filter(move |dnskey| dnskey.name.as_str() == zone);
- let dnskeys_verified = if zone == "." {
- verify_dnskey_rrsig(rrsig, &root_hints(), dnskeys.clone().collect())
- } else {
- debug_assert!(next_ds_set.is_some());
- if next_ds_set.is_none() { break 'next_zone; }
- verify_dnskey_rrsig(rrsig, next_ds_set.clone().unwrap(), dnskeys.clone().collect())
- };
- if dnskeys_verified.is_ok() {
- latest_inception = cmp::max(latest_inception, resolve_time(rrsig.inception));
- earliest_expiry = cmp::min(earliest_expiry, resolve_time(rrsig.expiration));
- min_ttl = cmp::min(min_ttl, rrsig.orig_ttl);
- for rrsig in inp.iter()
- .filter_map(|rr| if let RR::RRSig(sig) = rr { Some(sig) } else { None })
- .filter(move |rrsig| rrsig.key_name.as_str() == zone && rrsig.ty != DnsKey::TYPE)
- {
- if !rrsig.name.ends_with(zone) { return Err(ValidationError::Invalid); }
- let signed_records = inp.iter()
- .filter(|rr| rr.name() == &rrsig.name && rr.ty() == rrsig.ty);
- verify_rrsig(rrsig, dnskeys.clone(), signed_records.clone().collect())?;
- latest_inception = cmp::max(latest_inception, resolve_time(rrsig.inception));
- earliest_expiry = cmp::min(earliest_expiry, resolve_time(rrsig.expiration));
- min_ttl = cmp::min(min_ttl, rrsig.orig_ttl);
- match rrsig.ty {
- // RRSigs shouldn't cover child `DnsKey`s or other `RRSig`s
- RRSig::TYPE|DnsKey::TYPE => return Err(ValidationError::Invalid),
- DS::TYPE => {
- if !pending_ds_sets.iter().any(|(pending_zone, _)| pending_zone == &rrsig.name.as_str()) {
- pending_ds_sets.push((
- &rrsig.name,
- signed_records.filter_map(|rr|
- if let RR::DS(ds) = rr { Some(ds) }
- else { debug_assert!(false, "We already filtered by type"); None })
- ));
- }
- },
- _ => {
- if rrsig.labels != rrsig.name.labels() && rrsig.ty != NSec::TYPE {
- if rrsig.ty == NSec3::TYPE {
- // NSEC3 records should never appear on wildcards, so treat the
- // whole proof as invalid
- return Err(ValidationError::Invalid);
- }
- // If the RR used a wildcard, we need an NSEC/NSEC3 proof, which we
- // check for at the end. Note that the proof should be for the
- // "next closest" name, i.e. if the name here is a.b.c and it was
- // signed as *.c, we want a proof for nothing being in b.c.
- // Alternatively, if it was signed as *.b.c, we'd want a proof for
- // a.b.c.
- let proof_name = rrsig.name.trailing_n_labels(rrsig.labels + 1)
- .ok_or(ValidationError::Invalid)?;
- rrs_needing_non_existence_proofs.push((proof_name, &rrsig.key_name, rrsig.ty));
- }
- for record in signed_records {
- if !res.contains(&record) { res.push(record); }
- }
- },
- }
+ if !rrsig.name.ends_with(zone) { return Err(ValidationError::Invalid); }
+ let signed_records = inp.iter()
+ .filter(|rr| rr.name() == &rrsig.name && rr.ty() == rrsig.ty);
+ match verify_rrsig(rrsig, dnskeys.clone(), signed_records.clone().collect()) {
+ Ok(()) => {},
+ Err(ValidationError::UnsupportedAlgorithm) => continue,
+ Err(ValidationError::Invalid) => {
+ // If a signature is invalid, just immediately fail, avoiding KeyTrap issues.
+ return Err(ValidationError::Invalid);