Add duplicate RR detection to jdnssec-verifyzone, and a command line option to disable it.
This commit is contained in:
parent
b5775a8fdf
commit
d3e8c4c913
@ -48,6 +48,7 @@ public class VerifyZone extends CLBase
|
|||||||
public int startfudge = 0;
|
public int startfudge = 0;
|
||||||
public int expirefudge = 0;
|
public int expirefudge = 0;
|
||||||
public boolean ignoreTime = false;
|
public boolean ignoreTime = false;
|
||||||
|
public boolean ignoreDups = false;
|
||||||
|
|
||||||
public CLIState()
|
public CLIState()
|
||||||
{
|
{
|
||||||
@ -71,6 +72,10 @@ public class VerifyZone extends CLBase
|
|||||||
OptionBuilder.withLongOpt("ignore-time");
|
OptionBuilder.withLongOpt("ignore-time");
|
||||||
OptionBuilder.withDescription("Ignore RRSIG inception and expiration time errors.");
|
OptionBuilder.withDescription("Ignore RRSIG inception and expiration time errors.");
|
||||||
opts.addOption(OptionBuilder.create());
|
opts.addOption(OptionBuilder.create());
|
||||||
|
|
||||||
|
OptionBuilder.withLongOpt("ignore-duplicate-rrs");
|
||||||
|
OptionBuilder.withDescription("Ignore duplicate record errors.");
|
||||||
|
opts.addOption(OptionBuilder.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void processOptions(CommandLine cli)
|
protected void processOptions(CommandLine cli)
|
||||||
@ -80,6 +85,11 @@ public class VerifyZone extends CLBase
|
|||||||
ignoreTime = true;
|
ignoreTime = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cli.hasOption("ignore-duplicate-rrs"))
|
||||||
|
{
|
||||||
|
ignoreDups = true;
|
||||||
|
}
|
||||||
|
|
||||||
String optstr = null;
|
String optstr = null;
|
||||||
if ((optstr = cli.getOptionValue('S')) != null)
|
if ((optstr = cli.getOptionValue('S')) != null)
|
||||||
{
|
{
|
||||||
@ -126,6 +136,7 @@ public class VerifyZone extends CLBase
|
|||||||
zoneverifier.getVerifier().setStartFudge(state.startfudge);
|
zoneverifier.getVerifier().setStartFudge(state.startfudge);
|
||||||
zoneverifier.getVerifier().setExpireFudge(state.expirefudge);
|
zoneverifier.getVerifier().setExpireFudge(state.expirefudge);
|
||||||
zoneverifier.getVerifier().setIgnoreTime(state.ignoreTime);
|
zoneverifier.getVerifier().setIgnoreTime(state.ignoreTime);
|
||||||
|
zoneverifier.setIgnoreDuplicateRRs(state.ignoreDups);
|
||||||
|
|
||||||
List<Record> records = ZoneUtils.readZoneFile(state.zonefile, null);
|
List<Record> records = ZoneUtils.readZoneFile(state.zonefile, null);
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ import org.xbill.DNS.utils.base32;
|
|||||||
* A class for whole zone DNSSEC verification. Along with cryptographically
|
* A class for whole zone DNSSEC verification. Along with cryptographically
|
||||||
* verifying signatures, this class will also detect invalid NSEC and NSEC3
|
* verifying signatures, this class will also detect invalid NSEC and NSEC3
|
||||||
* chains.
|
* chains.
|
||||||
*
|
*
|
||||||
* @author David Blacka (original)
|
* @author David Blacka (original)
|
||||||
* @author $Author: davidb $
|
* @author $Author: davidb $
|
||||||
* @version $Revision: 172 $
|
* @version $Revision: 172 $
|
||||||
@ -63,6 +63,7 @@ public class ZoneVerifier
|
|||||||
private Name mZoneName;
|
private Name mZoneName;
|
||||||
private DNSSECType mDNSSECType;
|
private DNSSECType mDNSSECType;
|
||||||
private NSEC3PARAMRecord mNSEC3params;
|
private NSEC3PARAMRecord mNSEC3params;
|
||||||
|
private boolean mIgnoreDuplicateRRs;
|
||||||
|
|
||||||
private DnsSecVerifier mVerifier;
|
private DnsSecVerifier mVerifier;
|
||||||
private base32 mBase32;
|
private base32 mBase32;
|
||||||
@ -107,22 +108,48 @@ public class ZoneVerifier
|
|||||||
mVerifier = new DnsSecVerifier();
|
mVerifier = new DnsSecVerifier();
|
||||||
mBase32 = new base32(base32.Alphabet.BASE32HEX, false, true);
|
mBase32 = new base32(base32.Alphabet.BASE32HEX, false, true);
|
||||||
mBAcmp = new ByteArrayComparator();
|
mBAcmp = new ByteArrayComparator();
|
||||||
|
mIgnoreDuplicateRRs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the DnsSecVerifier object used to verify individual RRsets. */
|
||||||
public DnsSecVerifier getVerifier()
|
public DnsSecVerifier getVerifier()
|
||||||
{
|
{
|
||||||
return mVerifier;
|
return mVerifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIgnoreDuplicateRRs(boolean value)
|
||||||
|
{
|
||||||
|
mIgnoreDuplicateRRs = value;
|
||||||
|
}
|
||||||
|
|
||||||
private static String key(Name n, int type)
|
private static String key(Name n, int type)
|
||||||
{
|
{
|
||||||
return n.toString() + ':' + type;
|
return n.toString() + ':' + type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
private boolean addRRtoRRset(RRset rrset, Record rr)
|
||||||
|
{
|
||||||
|
if (mIgnoreDuplicateRRs)
|
||||||
|
{
|
||||||
|
rrset.addRR(rr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator i = rrset.rrs(); i.hasNext(); )
|
||||||
|
{
|
||||||
|
Record record = (Record) i.next();
|
||||||
|
if (rr.equals(record)) return false;
|
||||||
|
}
|
||||||
|
rrset.addRR(rr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a record to the various maps.
|
* Add a record to the various maps.
|
||||||
|
* @return TODO
|
||||||
*/
|
*/
|
||||||
private void addRR(Record r)
|
private boolean addRR(Record r)
|
||||||
{
|
{
|
||||||
Name r_name = r.getName();
|
Name r_name = r.getName();
|
||||||
int r_type = r.getType();
|
int r_type = r.getType();
|
||||||
@ -138,8 +165,8 @@ public class ZoneVerifier
|
|||||||
rrset = new MarkRRset();
|
rrset = new MarkRRset();
|
||||||
mNSECMap.put(r_name, rrset);
|
mNSECMap.put(r_name, rrset);
|
||||||
}
|
}
|
||||||
rrset.addRR(r);
|
|
||||||
return;
|
return addRRtoRRset(rrset, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_type == Type.NSEC3)
|
if (r_type == Type.NSEC3)
|
||||||
@ -151,8 +178,8 @@ public class ZoneVerifier
|
|||||||
rrset = new MarkRRset();
|
rrset = new MarkRRset();
|
||||||
mNSEC3Map.put(r_name, rrset);
|
mNSEC3Map.put(r_name, rrset);
|
||||||
}
|
}
|
||||||
rrset.addRR(r);
|
|
||||||
return;
|
return addRRtoRRset(rrset, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the name and type to the node map
|
// Add the name and type to the node map
|
||||||
@ -172,7 +199,7 @@ public class ZoneVerifier
|
|||||||
rrset = new RRset();
|
rrset = new RRset();
|
||||||
mRRsetMap.put(k, rrset);
|
mRRsetMap.put(k, rrset);
|
||||||
}
|
}
|
||||||
rrset.addRR(r);
|
return addRRtoRRset(rrset, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -198,10 +225,11 @@ public class ZoneVerifier
|
|||||||
/**
|
/**
|
||||||
* Given an unsorted list of records, load the node and rrset maps, as well as
|
* Given an unsorted list of records, load the node and rrset maps, as well as
|
||||||
* determine the NSEC3 parameters and signing type.
|
* determine the NSEC3 parameters and signing type.
|
||||||
*
|
*
|
||||||
* @param records
|
* @param records
|
||||||
|
* @return TODO
|
||||||
*/
|
*/
|
||||||
private void calculateNodes(List<Record> records)
|
private int calculateNodes(List<Record> records)
|
||||||
{
|
{
|
||||||
mNodeMap = new TreeMap<Name, Set<Integer>>();
|
mNodeMap = new TreeMap<Name, Set<Integer>>();
|
||||||
mRRsetMap = new HashMap<String, RRset>();
|
mRRsetMap = new HashMap<String, RRset>();
|
||||||
@ -209,13 +237,19 @@ public class ZoneVerifier
|
|||||||
// The zone is unsigned until we get a clue otherwise.
|
// The zone is unsigned until we get a clue otherwise.
|
||||||
mDNSSECType = DNSSECType.UNSIGNED;
|
mDNSSECType = DNSSECType.UNSIGNED;
|
||||||
|
|
||||||
|
int errors = 0;
|
||||||
for (Record r : records)
|
for (Record r : records)
|
||||||
{
|
{
|
||||||
Name r_name = r.getName();
|
Name r_name = r.getName();
|
||||||
int r_type = r.getType();
|
int r_type = r.getType();
|
||||||
|
|
||||||
// Add the record to the various maps.
|
// Add the record to the various maps.
|
||||||
addRR(r);
|
boolean res = addRR(r);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
log.warning("Record '" + r + "' detected as a duplicate");
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
|
||||||
// Learn some things about the zone as we do this pass.
|
// Learn some things about the zone as we do this pass.
|
||||||
if (r_type == Type.SOA) mZoneName = r_name;
|
if (r_type == Type.SOA) mZoneName = r_name;
|
||||||
@ -229,6 +263,8 @@ public class ZoneVerifier
|
|||||||
|
|
||||||
if (mDNSSECType == DNSSECType.UNSIGNED) mDNSSECType = determineDNSSECType(r);
|
if (mDNSSECType == DNSSECType.UNSIGNED) mDNSSECType = determineDNSSECType(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -290,7 +326,7 @@ public class ZoneVerifier
|
|||||||
last_cut = n;
|
last_cut = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check all of the RRset that should be signed
|
// check all of the RRsets that should be signed
|
||||||
for (int type : typeset)
|
for (int type : typeset)
|
||||||
{
|
{
|
||||||
if (type == Type.RRSIG) continue;
|
if (type == Type.RRSIG) continue;
|
||||||
@ -709,9 +745,9 @@ public class ZoneVerifier
|
|||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
calculateNodes(records);
|
errors += calculateNodes(records);
|
||||||
|
|
||||||
errors = processNodes();
|
errors += processNodes();
|
||||||
|
|
||||||
if (mDNSSECType == DNSSECType.NSEC)
|
if (mDNSSECType == DNSSECType.NSEC)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user