fix a number of jdnssec-signzone signing bugs: do not incorrectly set the RRSIG bit on NSEC3 RRs corresponding to insecure delegations, ignore junk below a DNAME, ignore delegations below other delegations

git-svn-id: https://svn.verisignlabs.com/jdnssec/tools/trunk@218 4cbd57fe-54e5-0310-bd9a-f30fe5ea5e6e
This commit is contained in:
David Blacka 2010-12-06 00:25:04 +00:00
parent 14ea619299
commit 3c9e33baf7
4 changed files with 92 additions and 39 deletions

View File

@ -1,5 +1,18 @@
2010-12-05 David Blacka <davidb@verisignlabs.com>
* jdnssec-signzone: Fix a bug that would incorrectly handle
delgations below delegations (those should be ignored.)
* jdnssec-signzone: Make the signer ignore junk below a DNAME.
This differs from BIND's dnssec-signzone behavior (currently), but
is the correct behavior, as stuff below a DNAME doesn't actually
exist in DNS. Note that if a name in a zone has both a DNAME and
a NS RRset (and is not at the apex), then the behavior is a bit
undefined.
* jdnssec-signzone: Fix a bug that would incorrectly set the RRSIG
bit for NSEC3 RRs corresponding to insecure delegations.
* jdnssec-signzone: add a "verbose signing" option. This will
cause the pre-signed bytes and the raw signature bytes to be
output when signing.

View File

@ -266,7 +266,7 @@ public class JCEDnsSecSigner
*/
private Name addRRset(List toList, Name zonename, RRset rrset, List kskpairs,
List zskpairs, Date start, Date expire, boolean fullySignKeyset,
Name last_cut) throws IOException, GeneralSecurityException
Name last_cut, Name last_dname) throws IOException, GeneralSecurityException
{
// add the records themselves
for (Iterator i = rrset.rrs(); i.hasNext();)
@ -275,7 +275,7 @@ public class JCEDnsSecSigner
}
int type = SignUtils.recordSecType(zonename, rrset.getName(), rrset.getType(),
last_cut);
last_cut, last_dname);
// we don't sign non-normal sets (delegations, glue, invalid).
if (type == SignUtils.RR_DELEGATION)
@ -410,6 +410,7 @@ public class JCEDnsSecSigner
RRset rrset = new RRset();
ArrayList signed_records = new ArrayList();
Name last_cut = null;
Name last_dname = null;
for (ListIterator i = records.listIterator(); i.hasNext();)
{
@ -436,7 +437,8 @@ public class JCEDnsSecSigner
// add the RRset to the list of signed_records, regardless of
// whether or not we actually end up signing the set.
last_cut = addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start,
expire, fullySignKeyset, last_cut);
expire, fullySignKeyset, last_cut, last_dname);
if (rrset.getType() == Type.DNAME) last_dname = rrset.getName();
rrset.clear();
rrset.addRR(r);
@ -444,7 +446,7 @@ public class JCEDnsSecSigner
// add the last RR set
addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start, expire,
fullySignKeyset, last_cut);
fullySignKeyset, last_cut, last_dname);
return signed_records;
}

View File

@ -42,7 +42,7 @@ public class RecordComparator implements Comparator
}
/**
* In general, types are compared numerically. However, SOA and NS are ordered
* In general, types are compared numerically. However, SOA, NS, and DNAME are ordered
* before the rest.
*/
private int compareTypes(int a, int b)
@ -54,6 +54,9 @@ public class RecordComparator implements Comparator
if (a == Type.NS) return -1;
if (b == Type.NS) return 1;
if (a == Type.DNAME) return -1;
if (b == Type.DNAME) return 1;
if (a < b) return -1;
return 1;

View File

@ -49,6 +49,7 @@ public class SignUtils
public static final int RR_DELEGATION = 1;
public static final int RR_GLUE = 2;
public static final int RR_INVALID = 3;
public static final int RR_DNAME = 4;
private static Logger log;
@ -478,32 +479,43 @@ public class SignUtils
* while iterating over the zone in canonical order.
*/
public static int recordSecType(Name zonename, Name name, int type,
Name last_cut)
Name last_cut, Name last_dname)
{
// records not even in the zone itself are invalid.
if (!name.subdomain(zonename)) return RR_INVALID;
// records that are at the zonename node are definitely normal.
// all records a the zone apex are normal, by definition.
if (name.equals(zonename)) return RR_NORMAL;
if (last_cut != null && name.subdomain(last_cut))
{
// if we are at the same level as a delegation point, but not one of a set of types allowed at
// a delegation point (NS, DS, NSEC), this is glue.
if (name.equals(last_cut))
{
if (type != Type.NS && type != Type.DS && type != Type.NXT && type != Type.NSEC)
{
return RR_GLUE;
}
}
// if we are below the delegation point, this is glue.
else
{
return RR_GLUE;
}
}
// if we are below a DNAME, then the RR is invalid.
if (last_dname != null && name.subdomain(last_dname) && name.labels() > last_dname.labels())
{
return RR_INVALID;
}
// since we are not at zone level, any NS records are delegations
if (type == Type.NS) return RR_DELEGATION;
if (last_cut != null)
{
// if we are at the same level as a delegation point, but not an
// NS record, then we either a DS record or glue.
if (name.equals(last_cut))
{
if (type == Type.DS || type == Type.NXT || type == Type.NSEC)
return RR_NORMAL;
// actually, this is probably INVALID, but it could be glue.
return RR_GLUE;
}
// below the delegation, we are glue
if (name.subdomain(last_cut)) return RR_GLUE;
}
// and everything else is normal
return RR_NORMAL;
}
@ -578,16 +590,16 @@ public class SignUtils
public boolean hasOptInSpan; // opt-in support.
public int nsecIndex;
public NodeInfo(Record r)
public NodeInfo(Record r, int nodeType)
{
this.name = r.getName();
this.type = r.getType();
this.type = nodeType;
this.ttl = r.getTTL();
this.dclass = r.getDClass();
this.typemap = new HashSet();
this.isSecureNode = false;
this.hasOptInSpan = false;
addType(type);
addType(r.getType());
}
public void addType(int type)
@ -602,6 +614,10 @@ public class SignUtils
}
}
public boolean hasType(int type) {
return this.typemap.contains(new Integer(type));
}
public String toString()
{
StringBuffer sb = new StringBuffer(name.toString());
@ -645,6 +661,7 @@ public class SignUtils
NodeInfo current_node = null;
Name last_cut = null;
Name last_dname = null;
int backup;
long nsec_ttl = 0;
@ -670,7 +687,7 @@ public class SignUtils
Record r = (Record) i.next();
Name r_name = r.getName();
int r_type = r.getType();
int r_sectype = recordSecType(zonename, r_name, r_type, last_cut);
int r_sectype = recordSecType(zonename, r_name, r_type, last_cut, last_dname);
// skip irrelevant records
if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) continue;
@ -678,10 +695,13 @@ public class SignUtils
// note our last delegation point so we can recognize glue.
if (r_sectype == RR_DELEGATION) last_cut = r_name;
// if this is a DNAME, note it so we can recognize junk
if (r_type == Type.DNAME) last_dname = r_name;
// first node -- initialize
if (current_node == null)
{
current_node = new NodeInfo(r);
current_node = new NodeInfo(r, r_sectype);
current_node.addType(Type.RRSIG);
current_node.addType(Type.NSEC);
continue;
@ -715,7 +735,7 @@ public class SignUtils
last_node = current_node;
current_node.nsecIndex = i.previousIndex();
current_node = new NodeInfo(r);
current_node = new NodeInfo(r, r_sectype);
current_node.addType(Type.RRSIG);
current_node.addType(Type.NSEC);
}
@ -771,6 +791,8 @@ public class SignUtils
NodeInfo last_node = null;
// For detecting glue.
Name last_cut = null;
// For detecting junk below a DNAME
Name last_dname = null;
long nsec3_ttl = 0;
@ -781,7 +803,7 @@ public class SignUtils
int r_type = r.getType();
// Classify this record so we know if we can skip it.
int r_sectype = recordSecType(zonename, r_name, r_type, last_cut);
int r_sectype = recordSecType(zonename, r_name, r_type, last_cut, last_dname);
// skip irrelevant records
if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) continue;
@ -789,6 +811,9 @@ public class SignUtils
// note our last delegation point so we can recognize glue.
if (r_sectype == RR_DELEGATION) last_cut = r_name;
// note our last DNAME point, so we can recognize junk.
if (r_type == Type.DNAME) last_dname = r_name;
if (r_type == Type.SOA)
{
SOARecord soa = (SOARecord) r;
@ -802,7 +827,7 @@ public class SignUtils
// For the first iteration, we create our current node.
if (current_node == null)
{
current_node = new NodeInfo(r);
current_node = new NodeInfo(r, r_sectype);
continue;
}
@ -820,7 +845,7 @@ public class SignUtils
proto_nsec3s);
last_node = current_node;
current_node = new NodeInfo(r);
current_node = new NodeInfo(r, r_sectype);
}
// process last two nodes.
@ -889,6 +914,8 @@ public class SignUtils
NodeInfo last_node = null;
// For detecting glue.
Name last_cut = null;
// For detecting out-of-zone records below a DNAME
Name last_dname = null;
long nsec3_ttl = 0;
@ -905,7 +932,7 @@ public class SignUtils
int r_type = r.getType();
// Classify this record so we know if we can skip it.
int r_sectype = recordSecType(zonename, r_name, r_type, last_cut);
int r_sectype = recordSecType(zonename, r_name, r_type, last_cut, last_dname);
// skip irrelevant records
if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) continue;
@ -913,6 +940,8 @@ public class SignUtils
// note our last delegation point so we can recognize glue.
if (r_sectype == RR_DELEGATION) last_cut = r_name;
if (r_type == Type.DNAME) last_dname = r_name;
if (r_type == Type.SOA)
{
SOARecord soa = (SOARecord) r;
@ -926,7 +955,7 @@ public class SignUtils
// For the first iteration, we create our current node.
if (current_node == null)
{
current_node = new NodeInfo(r);
current_node = new NodeInfo(r, r_sectype);
continue;
}
@ -957,7 +986,7 @@ public class SignUtils
last_node.hasOptInSpan = true;
}
current_node = new NodeInfo(r);
current_node = new NodeInfo(r, r_sectype);
}
// process last two nodes.
@ -1007,7 +1036,9 @@ public class SignUtils
if (optIn && !node.isSecureNode) return;
// Add our default types.
if (node.type == RR_NORMAL || (node.type == RR_DELEGATION && node.hasType(Type.DS))) {
node.addType(Type.RRSIG);
}
if (node.name.equals(zonename)) node.addType(Type.NSEC3PARAM);
// Check for ENTs -- note this will generate duplicate ENTs because it
@ -1170,6 +1201,8 @@ public class SignUtils
NodeInfo current_node = null;
Name last_cut = null;
Name last_dname = null;
int backup;
HashSet includeSet = null;
@ -1183,7 +1216,7 @@ public class SignUtils
Record r = (Record) i.next();
Name r_name = r.getName();
int r_type = r.getType();
int r_sectype = recordSecType(zonename, r_name, r_type, last_cut);
int r_sectype = recordSecType(zonename, r_name, r_type, last_cut, last_dname);
// skip irrelevant records
if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) continue;
@ -1191,10 +1224,12 @@ public class SignUtils
// note our last delegation point so we can recognize glue.
if (r_sectype == RR_DELEGATION) last_cut = r_name;
if (r_type == Type.DNAME) last_dname = r_name;
// first node -- initialize
if (current_node == null)
{
current_node = new NodeInfo(r);
current_node = new NodeInfo(r, r_sectype);
current_node.addType(Type.RRSIG);
continue;
}
@ -1249,7 +1284,7 @@ public class SignUtils
}
current_node.nsecIndex = i.previousIndex();
current_node = new NodeInfo(r);
current_node = new NodeInfo(r, r_sectype);
current_node.addType(Type.RRSIG);
}