/*
* 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();
}
}