/* * dnssecjava - a DNSSEC validating stub resolver for Java * Copyright (c) 2013-2015 Ingo Bauersachs * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jitsi.dnssec.unbound.rpl; import static org.junit.Assert.assertEquals; import static org.powermock.api.mockito.PowerMockito.whenNew; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.Properties; import org.jitsi.dnssec.SRRset; import org.jitsi.dnssec.TestBase; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.xbill.DNS.CNAMERecord; import org.xbill.DNS.DNAMERecord; import org.xbill.DNS.DNSSEC; import org.xbill.DNS.Flags; import org.xbill.DNS.Message; import org.xbill.DNS.Name; import org.xbill.DNS.RRset; import org.xbill.DNS.Rcode; import org.xbill.DNS.Record; import org.xbill.DNS.Section; import org.xbill.DNS.Type; @RunWith(PowerMockRunner.class) @PrepareForTest(DNSSEC.class) public class UnboundTests extends TestBase { public void runUnboundTest() throws ParseException, IOException { InputStream data = getClass().getResourceAsStream("/unbound/" + testName + ".rpl"); RplParser p = new RplParser(data); Rpl rpl = p.parse(); Properties config = new Properties(); if (rpl.nsec3iterations != null) { for (Entry<Integer, Integer> e : rpl.nsec3iterations.entrySet()) { config.put("org.jitsi.dnssec.nsec3.iterations." + e.getKey(), e.getValue()); } } if (rpl.digestPreference != null) { config.put("org.jitsi.dnssec.digest_preference", rpl.digestPreference); } for (Message m : rpl.replays) { add(stripAdditional(m)); for (RRset set : m.getSectionRRsets(Section.AUTHORITY)) { if (set.getType() == Type.DS && set.sigs().hasNext() && Name.fromString("sub.example.com.").equals(set.getName())) { Message additional = new Message(); additional.addRecord(Record.newRecord(set.getName(), set.getType(), set.getDClass()), Section.QUESTION); Iterator<?> it = set.rrs(); while (it.hasNext()) { additional.addRecord((Record)it.next(), Section.ANSWER); } it = set.sigs(); while (it.hasNext()) { additional.addRecord((Record)it.next(), Section.ANSWER); } add(stripAdditional(additional)); break; } } } // merge xNAME queries into one List<Message> copy = new ArrayList<Message>(rpl.replays.size()); copy.addAll(rpl.replays); List<Name> copiedTargets = new ArrayList<Name>(5); for (Message m : copy) { Name target = null; for (RRset s : m.getSectionRRsets(Section.ANSWER)) { if (s.getType() == Type.CNAME) { target = ((CNAMERecord)s.first()).getTarget(); } else if (s.getType() == Type.DNAME) { target = ((DNAMERecord)s.first()).getTarget(); } while (target != null) { Message a = get(target, m.getQuestion().getType()); if (a == null) { a = get(target, Type.CNAME); } if (a == null) { a = get(target, Type.DNAME); } if (a != null) { target = add(m, a); if (copiedTargets.contains(target)) { break; } copiedTargets.add(target); rpl.replays.remove(a); } else { target = null; } } } } // promote any DS records in auth. sections to real queries copy = new ArrayList<Message>(rpl.replays.size()); copy.addAll(rpl.replays); for (Message m : copy) { for (RRset s : m.getSectionRRsets(Section.AUTHORITY)) { if (s.getType() == Type.DS) { Message ds = new Message(); ds.addRecord(Record.newRecord(s.getName(), s.getType(), s.getDClass()), Section.QUESTION); Iterator<?> rrs = s.rrs(); while (rrs.hasNext()) { ds.addRecord((Record)rrs.next(), Section.ANSWER); } Iterator<?> sigs = s.sigs(); while (sigs.hasNext()) { ds.addRecord((Record)sigs.next(), Section.ANSWER); } rpl.replays.add(ds); } } } clear(); for (Message m : rpl.replays) { add(stripAdditional(m)); } if (rpl.date != null) { try { Date d = new Date(rpl.date.getMillis()); whenNew(Date.class).withNoArguments().thenReturn(d); } catch (Exception e) { throw new RuntimeException(e); } } if (rpl.trustAnchors != null) { resolver.getTrustAnchors().clear(); for (SRRset rrset : rpl.trustAnchors) { resolver.getTrustAnchors().store(rrset); } } resolver.init(config); for (Check c : rpl.checks.values()) { Message s = resolver.send(c.query); assertEquals(c.response.getHeader().getFlag(Flags.AD), s.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.string(c.response.getRcode()), Rcode.string(s.getRcode())); } } private Message stripAdditional(Message m) { if (m.getQuestion().getType() == Type.RRSIG) { return m; } Message copy = new Message(); copy.setHeader(m.getHeader()); for (int i = 0; i < Section.ADDITIONAL; i++) { for (RRset set : m.getSectionRRsets(i)) { if (set.getType() == Type.NS && m.getQuestion().getType() != Type.NS) { continue; } Iterator<?> rrs = set.rrs(); while (rrs.hasNext()) { copy.addRecord((Record)rrs.next(), i); } Iterator<?> sigs = set.sigs(); while (sigs.hasNext()) { copy.addRecord((Record)sigs.next(), i); } } } return copy; } private Name add(Message target, Message source) { Name next = null; target.getHeader().setRcode(source.getRcode()); for (Record r : source.getSectionArray(Section.ANSWER)) { target.addRecord(r, Section.ANSWER); if (r.getType() == Type.CNAME) { next = ((CNAMERecord)r).getTarget(); } else if (r.getType() == Type.DNAME) { next = ((DNAMERecord)r).getTarget(); } } for (Record r : source.getSectionArray(Section.AUTHORITY)) { if (r.getType() != Type.NS) { target.addRecord(r, Section.AUTHORITY); } } return next; } public static void main(String[] srgs) throws ParseException, IOException { String[] ignored = new String[] { "val_faildnskey_ok.rpl", // tests an // unbound // specific // config // option "val_nsec3_nods_negcache.rpl", // we don't do negative caching "val_unsecds_negcache.rpl", // " "val_negcache_dssoa.rpl", // " "val_nsec3_b3_optout_negcache.rpl", // " "val_dsnsec.rpl", // " "val_refer_unsignadd.rpl", // more cache stuff "val_referglue.rpl", // " "val_noadwhennodo.rpl", // irrelevant - if we wouldn't want AD, // we wouldn't be using this stuff "val_fwdds.rpl", // irrelevant, we're not a recursive resolver "val_referd.rpl", // NSEC records missing for validation, tests // caching stuff "val_stubds.rpl", // tests unbound specific config (stub zones) "val_cnametonsec.rpl", // incomplete CNAME answer "val_cnametooptin.rpl", // incomplete CNAME answer "val_cnametoinsecure.rpl", // incomplete CNAME answer "val_nsec3_optout_cache.rpl", // more cache stuff "val_ds_gost.rpl", // we don't support GOST (RFC5933) "val_ds_gost_downgrade.rpl", // no GOST "val_unsecds_qtypeds.rpl", // tests the iterative resolver "val_anchor_nx.rpl", // tests caching of NX from a parent // resolver "val_anchor_nx_nosig.rpl", // " }; List<String> ignoredList = Arrays.asList(ignored); for (String f : new File("./src/test/resources/unbound").list()) { if (ignoredList.contains(f)) { continue; } System.out.println(" @Test"); System.out.println(" public void " + f.split("\\.")[0] + "() throws ParseException, IOException {"); System.out.println(" runUnboundTest();"); System.out.println(" }"); } } @Test public void val_adbit() throws ParseException, IOException { runUnboundTest(); } @Test public void val_adcopy() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ans_dsent() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ans_nx() throws ParseException, IOException { runUnboundTest(); } @Test public void val_any() throws ParseException, IOException { runUnboundTest(); } @Test public void val_any_cname() throws ParseException, IOException { runUnboundTest(); } @Test public void val_any_dname() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnameinsectopos() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnamenx_dblnsec() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnamenx_rcodenx() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnameqtype() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametocloser() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametocloser_nosig() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametocnamewctoposwc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametodname() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametodnametocnametopos() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametonodata() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametonodata_nonsec() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametonx() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametooptout() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametopos() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametoposnowc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnametoposwc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnamewctonodata() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnamewctonx() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cnamewctoposwc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cname_loop1() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cname_loop2() throws ParseException, IOException { runUnboundTest(); } @Test public void val_cname_loop3() throws ParseException, IOException { runUnboundTest(); } @Test public void val_dnametoolong() throws ParseException, IOException { runUnboundTest(); } @Test public void val_dnametopos() throws ParseException, IOException { runUnboundTest(); } @Test public void val_dnametoposwc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_dnamewc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ds_afterprime() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ds_cname() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ds_cnamesub() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ds_cnamesubbogus() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ds_sha2() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ds_sha2_downgrade() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ds_sha2_downgrade_override() throws ParseException, IOException { runUnboundTest(); } @Test public void val_entds() throws ParseException, IOException { runUnboundTest(); } @Test public void val_faildnskey() throws ParseException, IOException { runUnboundTest(); } @Test public void val_keyprefetch() throws ParseException, IOException { runUnboundTest(); } @Test public void val_keyprefetch_verify() throws ParseException, IOException { runUnboundTest(); } @Test public void val_mal_wc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_negcache_ds() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodata() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodatawc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodatawc_badce() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodatawc_nodeny() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodatawc_wrongdeleg() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodatawc_wcns() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodatawc_one() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodata_ent() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodata_entwc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodata_failsig() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodata_hasdata() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nodata_zonecut() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nokeyprime() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b1_nameerror() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b1_nameerror_noce() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b1_nameerror_nonc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b1_nameerror_nowc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b21_nodataent() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b21_nodataent_wr() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b2_nodata() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b2_nodata_nons() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b3_optout() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b3_optout_noce() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b3_optout_nonc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b4_wild() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b4_wild_wr() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b5_wcnodata() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b5_wcnodata_noce() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b5_wcnodata_nonc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_b5_wcnodata_nowc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_cnametocnamewctoposwc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_cname_ds() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_cname_par() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_cname_sub() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_entnodata_optout() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_entnodata_optout_badopt() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_entnodata_optout_match() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_iter_high() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_nodatawccname() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_nods() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_nods_badopt() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_nods_badsig() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_nods_soa() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_optout_ad() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_wcany() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nsec3_wcany_nodeny() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nodeny() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nowc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nsec3_collision() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nsec3_collision2() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nsec3_collision3() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nsec3_collision4() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nsec3_hashalg() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nsec3_nsecmix() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_nsec3_params() throws ParseException, IOException { runUnboundTest(); } @Test public void val_nx_overreach() throws ParseException, IOException { runUnboundTest(); } @Test public void val_positive() throws ParseException, IOException { runUnboundTest(); } @Test public void val_positive_nosigs() throws ParseException, IOException { runUnboundTest(); } @Test public void val_positive_wc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_positive_wc_nodeny() throws ParseException, IOException { runUnboundTest(); } @Test public void val_pos_truncns() throws ParseException, IOException { runUnboundTest(); } @Test public void val_qds_badanc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_qds_oneanc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_qds_twoanc() throws ParseException, IOException { runUnboundTest(); } @Test public void val_rrsig() throws ParseException, IOException { runUnboundTest(); } @Test public void val_secds() throws ParseException, IOException { runUnboundTest(); } @Test public void val_secds_nosig() throws ParseException, IOException { runUnboundTest(); } @Test public void val_stub_noroot() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ta_algo_dnskey() throws ParseException, IOException { runUnboundTest(); } @Test public void val_ta_algo_missing() throws ParseException, IOException { runUnboundTest(); } @Test public void val_twocname() throws ParseException, IOException { runUnboundTest(); } @Test public void val_unalgo_anchor() throws ParseException, IOException { runUnboundTest(); } @Test public void val_unalgo_dlv() throws ParseException, IOException { runUnboundTest(); } @Test public void val_unalgo_ds() throws ParseException, IOException { runUnboundTest(); } @Test public void val_unsecds() throws ParseException, IOException { runUnboundTest(); } @Test public void val_unsec_cname() throws ParseException, IOException { runUnboundTest(); } @Test public void val_wild_pos() throws ParseException, IOException { runUnboundTest(); } }