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:
parent
14ea619299
commit
3c9e33baf7
13
ChangeLog
13
ChangeLog
@ -1,5 +1,18 @@
|
|||||||
2010-12-05 David Blacka <davidb@verisignlabs.com>
|
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
|
* jdnssec-signzone: add a "verbose signing" option. This will
|
||||||
cause the pre-signed bytes and the raw signature bytes to be
|
cause the pre-signed bytes and the raw signature bytes to be
|
||||||
output when signing.
|
output when signing.
|
||||||
|
@ -266,7 +266,7 @@ public class JCEDnsSecSigner
|
|||||||
*/
|
*/
|
||||||
private Name addRRset(List toList, Name zonename, RRset rrset, List kskpairs,
|
private Name addRRset(List toList, Name zonename, RRset rrset, List kskpairs,
|
||||||
List zskpairs, Date start, Date expire, boolean fullySignKeyset,
|
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
|
// add the records themselves
|
||||||
for (Iterator i = rrset.rrs(); i.hasNext();)
|
for (Iterator i = rrset.rrs(); i.hasNext();)
|
||||||
@ -275,7 +275,7 @@ public class JCEDnsSecSigner
|
|||||||
}
|
}
|
||||||
|
|
||||||
int type = SignUtils.recordSecType(zonename, rrset.getName(), rrset.getType(),
|
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).
|
// we don't sign non-normal sets (delegations, glue, invalid).
|
||||||
if (type == SignUtils.RR_DELEGATION)
|
if (type == SignUtils.RR_DELEGATION)
|
||||||
@ -410,6 +410,7 @@ public class JCEDnsSecSigner
|
|||||||
RRset rrset = new RRset();
|
RRset rrset = new RRset();
|
||||||
ArrayList signed_records = new ArrayList();
|
ArrayList signed_records = new ArrayList();
|
||||||
Name last_cut = null;
|
Name last_cut = null;
|
||||||
|
Name last_dname = null;
|
||||||
|
|
||||||
for (ListIterator i = records.listIterator(); i.hasNext();)
|
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
|
// add the RRset to the list of signed_records, regardless of
|
||||||
// whether or not we actually end up signing the set.
|
// whether or not we actually end up signing the set.
|
||||||
last_cut = addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start,
|
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.clear();
|
||||||
rrset.addRR(r);
|
rrset.addRR(r);
|
||||||
@ -444,7 +446,7 @@ public class JCEDnsSecSigner
|
|||||||
|
|
||||||
// add the last RR set
|
// add the last RR set
|
||||||
addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start, expire,
|
addRRset(signed_records, zonename, rrset, kskpairs, zskpairs, start, expire,
|
||||||
fullySignKeyset, last_cut);
|
fullySignKeyset, last_cut, last_dname);
|
||||||
|
|
||||||
return signed_records;
|
return signed_records;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* before the rest.
|
||||||
*/
|
*/
|
||||||
private int compareTypes(int a, int b)
|
private int compareTypes(int a, int b)
|
||||||
@ -54,6 +54,9 @@ public class RecordComparator implements Comparator
|
|||||||
if (a == Type.NS) return -1;
|
if (a == Type.NS) return -1;
|
||||||
if (b == 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;
|
if (a < b) return -1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -49,6 +49,7 @@ public class SignUtils
|
|||||||
public static final int RR_DELEGATION = 1;
|
public static final int RR_DELEGATION = 1;
|
||||||
public static final int RR_GLUE = 2;
|
public static final int RR_GLUE = 2;
|
||||||
public static final int RR_INVALID = 3;
|
public static final int RR_INVALID = 3;
|
||||||
|
public static final int RR_DNAME = 4;
|
||||||
|
|
||||||
private static Logger log;
|
private static Logger log;
|
||||||
|
|
||||||
@ -478,32 +479,43 @@ public class SignUtils
|
|||||||
* while iterating over the zone in canonical order.
|
* while iterating over the zone in canonical order.
|
||||||
*/
|
*/
|
||||||
public static int recordSecType(Name zonename, Name name, int type,
|
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.
|
// records not even in the zone itself are invalid.
|
||||||
if (!name.subdomain(zonename)) return RR_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 (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
|
// since we are not at zone level, any NS records are delegations
|
||||||
if (type == Type.NS) return RR_DELEGATION;
|
if (type == Type.NS) return RR_DELEGATION;
|
||||||
|
|
||||||
if (last_cut != null)
|
// and everything else is normal
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RR_NORMAL;
|
return RR_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,16 +590,16 @@ public class SignUtils
|
|||||||
public boolean hasOptInSpan; // opt-in support.
|
public boolean hasOptInSpan; // opt-in support.
|
||||||
public int nsecIndex;
|
public int nsecIndex;
|
||||||
|
|
||||||
public NodeInfo(Record r)
|
public NodeInfo(Record r, int nodeType)
|
||||||
{
|
{
|
||||||
this.name = r.getName();
|
this.name = r.getName();
|
||||||
this.type = r.getType();
|
this.type = nodeType;
|
||||||
this.ttl = r.getTTL();
|
this.ttl = r.getTTL();
|
||||||
this.dclass = r.getDClass();
|
this.dclass = r.getDClass();
|
||||||
this.typemap = new HashSet();
|
this.typemap = new HashSet();
|
||||||
this.isSecureNode = false;
|
this.isSecureNode = false;
|
||||||
this.hasOptInSpan = false;
|
this.hasOptInSpan = false;
|
||||||
addType(type);
|
addType(r.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addType(int type)
|
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()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuffer sb = new StringBuffer(name.toString());
|
StringBuffer sb = new StringBuffer(name.toString());
|
||||||
@ -645,6 +661,7 @@ public class SignUtils
|
|||||||
NodeInfo current_node = null;
|
NodeInfo current_node = null;
|
||||||
|
|
||||||
Name last_cut = null;
|
Name last_cut = null;
|
||||||
|
Name last_dname = null;
|
||||||
int backup;
|
int backup;
|
||||||
long nsec_ttl = 0;
|
long nsec_ttl = 0;
|
||||||
|
|
||||||
@ -670,7 +687,7 @@ public class SignUtils
|
|||||||
Record r = (Record) i.next();
|
Record r = (Record) i.next();
|
||||||
Name r_name = r.getName();
|
Name r_name = r.getName();
|
||||||
int r_type = r.getType();
|
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
|
// skip irrelevant records
|
||||||
if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) continue;
|
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.
|
// note our last delegation point so we can recognize glue.
|
||||||
if (r_sectype == RR_DELEGATION) last_cut = r_name;
|
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
|
// first node -- initialize
|
||||||
if (current_node == null)
|
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.RRSIG);
|
||||||
current_node.addType(Type.NSEC);
|
current_node.addType(Type.NSEC);
|
||||||
continue;
|
continue;
|
||||||
@ -715,7 +735,7 @@ public class SignUtils
|
|||||||
last_node = current_node;
|
last_node = current_node;
|
||||||
|
|
||||||
current_node.nsecIndex = i.previousIndex();
|
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.RRSIG);
|
||||||
current_node.addType(Type.NSEC);
|
current_node.addType(Type.NSEC);
|
||||||
}
|
}
|
||||||
@ -771,6 +791,8 @@ public class SignUtils
|
|||||||
NodeInfo last_node = null;
|
NodeInfo last_node = null;
|
||||||
// For detecting glue.
|
// For detecting glue.
|
||||||
Name last_cut = null;
|
Name last_cut = null;
|
||||||
|
// For detecting junk below a DNAME
|
||||||
|
Name last_dname = null;
|
||||||
|
|
||||||
long nsec3_ttl = 0;
|
long nsec3_ttl = 0;
|
||||||
|
|
||||||
@ -781,7 +803,7 @@ public class SignUtils
|
|||||||
int r_type = r.getType();
|
int r_type = r.getType();
|
||||||
|
|
||||||
// Classify this record so we know if we can skip it.
|
// 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
|
// skip irrelevant records
|
||||||
if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) continue;
|
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.
|
// note our last delegation point so we can recognize glue.
|
||||||
if (r_sectype == RR_DELEGATION) last_cut = r_name;
|
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)
|
if (r_type == Type.SOA)
|
||||||
{
|
{
|
||||||
SOARecord soa = (SOARecord) r;
|
SOARecord soa = (SOARecord) r;
|
||||||
@ -802,7 +827,7 @@ public class SignUtils
|
|||||||
// For the first iteration, we create our current node.
|
// For the first iteration, we create our current node.
|
||||||
if (current_node == null)
|
if (current_node == null)
|
||||||
{
|
{
|
||||||
current_node = new NodeInfo(r);
|
current_node = new NodeInfo(r, r_sectype);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,7 +845,7 @@ public class SignUtils
|
|||||||
proto_nsec3s);
|
proto_nsec3s);
|
||||||
|
|
||||||
last_node = current_node;
|
last_node = current_node;
|
||||||
current_node = new NodeInfo(r);
|
current_node = new NodeInfo(r, r_sectype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process last two nodes.
|
// process last two nodes.
|
||||||
@ -889,6 +914,8 @@ public class SignUtils
|
|||||||
NodeInfo last_node = null;
|
NodeInfo last_node = null;
|
||||||
// For detecting glue.
|
// For detecting glue.
|
||||||
Name last_cut = null;
|
Name last_cut = null;
|
||||||
|
// For detecting out-of-zone records below a DNAME
|
||||||
|
Name last_dname = null;
|
||||||
|
|
||||||
long nsec3_ttl = 0;
|
long nsec3_ttl = 0;
|
||||||
|
|
||||||
@ -905,7 +932,7 @@ public class SignUtils
|
|||||||
int r_type = r.getType();
|
int r_type = r.getType();
|
||||||
|
|
||||||
// Classify this record so we know if we can skip it.
|
// 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
|
// skip irrelevant records
|
||||||
if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) continue;
|
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.
|
// note our last delegation point so we can recognize glue.
|
||||||
if (r_sectype == RR_DELEGATION) last_cut = r_name;
|
if (r_sectype == RR_DELEGATION) last_cut = r_name;
|
||||||
|
|
||||||
|
if (r_type == Type.DNAME) last_dname = r_name;
|
||||||
|
|
||||||
if (r_type == Type.SOA)
|
if (r_type == Type.SOA)
|
||||||
{
|
{
|
||||||
SOARecord soa = (SOARecord) r;
|
SOARecord soa = (SOARecord) r;
|
||||||
@ -926,7 +955,7 @@ public class SignUtils
|
|||||||
// For the first iteration, we create our current node.
|
// For the first iteration, we create our current node.
|
||||||
if (current_node == null)
|
if (current_node == null)
|
||||||
{
|
{
|
||||||
current_node = new NodeInfo(r);
|
current_node = new NodeInfo(r, r_sectype);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -957,7 +986,7 @@ public class SignUtils
|
|||||||
last_node.hasOptInSpan = true;
|
last_node.hasOptInSpan = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_node = new NodeInfo(r);
|
current_node = new NodeInfo(r, r_sectype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process last two nodes.
|
// process last two nodes.
|
||||||
@ -1007,7 +1036,9 @@ public class SignUtils
|
|||||||
if (optIn && !node.isSecureNode) return;
|
if (optIn && !node.isSecureNode) return;
|
||||||
|
|
||||||
// Add our default types.
|
// Add our default types.
|
||||||
|
if (node.type == RR_NORMAL || (node.type == RR_DELEGATION && node.hasType(Type.DS))) {
|
||||||
node.addType(Type.RRSIG);
|
node.addType(Type.RRSIG);
|
||||||
|
}
|
||||||
if (node.name.equals(zonename)) node.addType(Type.NSEC3PARAM);
|
if (node.name.equals(zonename)) node.addType(Type.NSEC3PARAM);
|
||||||
|
|
||||||
// Check for ENTs -- note this will generate duplicate ENTs because it
|
// Check for ENTs -- note this will generate duplicate ENTs because it
|
||||||
@ -1170,6 +1201,8 @@ public class SignUtils
|
|||||||
NodeInfo current_node = null;
|
NodeInfo current_node = null;
|
||||||
|
|
||||||
Name last_cut = null;
|
Name last_cut = null;
|
||||||
|
Name last_dname = null;
|
||||||
|
|
||||||
int backup;
|
int backup;
|
||||||
HashSet includeSet = null;
|
HashSet includeSet = null;
|
||||||
|
|
||||||
@ -1183,7 +1216,7 @@ public class SignUtils
|
|||||||
Record r = (Record) i.next();
|
Record r = (Record) i.next();
|
||||||
Name r_name = r.getName();
|
Name r_name = r.getName();
|
||||||
int r_type = r.getType();
|
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
|
// skip irrelevant records
|
||||||
if (r_sectype == RR_INVALID || r_sectype == RR_GLUE) continue;
|
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.
|
// note our last delegation point so we can recognize glue.
|
||||||
if (r_sectype == RR_DELEGATION) last_cut = r_name;
|
if (r_sectype == RR_DELEGATION) last_cut = r_name;
|
||||||
|
|
||||||
|
if (r_type == Type.DNAME) last_dname = r_name;
|
||||||
|
|
||||||
// first node -- initialize
|
// first node -- initialize
|
||||||
if (current_node == null)
|
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.RRSIG);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1249,7 +1284,7 @@ public class SignUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
current_node.nsecIndex = i.previousIndex();
|
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.RRSIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user