Add ability to define the TTL of the NSEC3PARAM record.

git-svn-id: https://svn.verisignlabs.com/jdnssec/tools/trunk@133 4cbd57fe-54e5-0310-bd9a-f30fe5ea5e6e
This commit is contained in:
David Blacka 2009-02-07 20:37:29 +00:00
parent 6202d0a0a3
commit b35bab0bdd
3 changed files with 187 additions and 51 deletions

View File

@ -97,6 +97,7 @@ public class SignZone
public byte[] salt = null; public byte[] salt = null;
public int iterations = 0; public int iterations = 0;
public int digest_id = DSRecord.SHA1_DIGEST_ID; public int digest_id = DSRecord.SHA1_DIGEST_ID;
public long nsec3paramttl = -1;
public CLIState() public CLIState()
{ {
@ -189,6 +190,12 @@ public class SignZone
OptionBuilder.withDescription("use this value for the iterations in NSEC3."); OptionBuilder.withDescription("use this value for the iterations in NSEC3.");
opts.addOption(OptionBuilder.create()); opts.addOption(OptionBuilder.create());
OptionBuilder.hasArg();
OptionBuilder.withLongOpt("nsec3paramttl");
OptionBuilder.withArgName("ttl");
OptionBuilder.withDescription("use this value for the NSEC3PARAM RR ttl");
opts.addOption(OptionBuilder.create());
OptionBuilder.hasArg(); OptionBuilder.hasArg();
OptionBuilder.withArgName("alias:original:mnemonic"); OptionBuilder.withArgName("alias:original:mnemonic");
OptionBuilder.withLongOpt("alg-alias"); OptionBuilder.withLongOpt("alg-alias");
@ -351,6 +358,11 @@ public class SignZone
} }
} }
if ((optstr = cli.getOptionValue("nsec3paramttl")) != null)
{
nsec3paramttl = parseInt(optstr, -1);
}
String[] files = cli.getArgs(); String[] files = cli.getArgs();
if (files.length < 1) if (files.length < 1)
@ -715,7 +727,10 @@ public class SignZone
{ {
DnsKeyPair kp = (DnsKeyPair) i.next(); DnsKeyPair kp = (DnsKeyPair) i.next();
Name keyname = kp.getDNSKEYRecord().getName(); Name keyname = kp.getDNSKEYRecord().getName();
if (!keyname.equals(zonename)) { return false; } if (!keyname.equals(zonename))
{
return false;
}
} }
return true; return true;
@ -852,7 +867,8 @@ public class SignZone
state.fullySignKeyset, state.fullySignKeyset,
state.useOptOut, state.useOptOut,
state.includeNames, state.salt, state.includeNames, state.salt,
state.iterations, state.digest_id); state.iterations, state.digest_id,
state.nsec3paramttl);
} }
else else
{ {

View File

@ -246,8 +246,14 @@ public class JCEDnsSecSigner
rrset.getType(), last_cut); rrset.getType(), last_cut);
// 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) { return rrset.getName(); } if (type == SignUtils.RR_DELEGATION)
if (type == SignUtils.RR_GLUE || type == SignUtils.RR_INVALID) { return last_cut; } {
return rrset.getName();
}
if (type == SignUtils.RR_GLUE || type == SignUtils.RR_INVALID)
{
return last_cut;
}
// check for the zone apex keyset. // check for the zone apex keyset.
if (rrset.getName().equals(zonename) && rrset.getType() == Type.DNSKEY) if (rrset.getName().equals(zonename) && rrset.getType() == Type.DNSKEY)
@ -316,7 +322,9 @@ public class JCEDnsSecSigner
* If true, then only turn on the Opt-In flag when there are insecure * If true, then only turn on the Opt-In flag when there are insecure
* delegations in the span. Currently this only works for * delegations in the span. Currently this only works for
* NSEC_EXP_OPT_IN mode. * NSEC_EXP_OPT_IN mode.
* * @param nsec3paramttl
* The TTL to use for the generated NSEC3PARAM record. Negative
* values will use the SOA TTL.
* @return an ordered list of {@link org.xbill.DNS.Record} objects, * @return an ordered list of {@link org.xbill.DNS.Record} objects,
* representing the signed zone. * representing the signed zone.
* *
@ -327,7 +335,7 @@ public class JCEDnsSecSigner
List zskpairs, Date start, Date expire, List zskpairs, Date start, Date expire,
boolean fullySignKeyset, int ds_digest_alg, int mode, boolean fullySignKeyset, int ds_digest_alg, int mode,
List includedNames, byte[] salt, int iterations, List includedNames, byte[] salt, int iterations,
boolean beConservative) long nsec3paramttl, boolean beConservative)
throws IOException, GeneralSecurityException throws IOException, GeneralSecurityException
{ {
// Remove any existing generated DNSSEC records (NSEC, NSEC3, NSEC3PARAM, // Remove any existing generated DNSSEC records (NSEC, NSEC3, NSEC3PARAM,
@ -352,11 +360,12 @@ public class JCEDnsSecSigner
SignUtils.generateNSECRecords(zonename, records); SignUtils.generateNSECRecords(zonename, records);
break; break;
case NSEC3_MODE: case NSEC3_MODE:
SignUtils.generateNSEC3Records(zonename, records, salt, iterations); SignUtils.generateNSEC3Records(zonename, records, salt, iterations,
nsec3paramttl);
break; break;
case NSEC3_OPTOUT_MODE: case NSEC3_OPTOUT_MODE:
SignUtils.generateOptOutNSEC3Records(zonename, records, includedNames, SignUtils.generateOptOutNSEC3Records(zonename, records, includedNames,
salt, iterations); salt, iterations, nsec3paramttl);
break; break;
case NSEC_EXP_OPT_IN: case NSEC_EXP_OPT_IN:
SignUtils.generateOptInNSECRecords(zonename, records, includedNames, SignUtils.generateOptInNSECRecords(zonename, records, includedNames,
@ -443,7 +452,7 @@ public class JCEDnsSecSigner
{ {
return signZone(zonename, records, kskpairs, zskpairs, start, expire, return signZone(zonename, records, kskpairs, zskpairs, start, expire,
fullySignKeyset, ds_digest_alg, NSEC_MODE, null, null, 0, fullySignKeyset, ds_digest_alg, NSEC_MODE, null, null, 0,
false); 0, false);
} }
/** /**
@ -478,7 +487,9 @@ public class JCEDnsSecSigner
* The number of iterations to use for the NSEC3 hashing. * The number of iterations to use for the NSEC3 hashing.
* @param ds_digest_alg * @param ds_digest_alg
* The digest algorithm to use when generating DS records. * The digest algorithm to use when generating DS records.
* * @param nsec3paramttl
* The TTL to use for the generated NSEC3PARAM record. Negative
* values will use the SOA TTL.
* @return an ordered list of {@link org.xbill.DNS.Record} objects, * @return an ordered list of {@link org.xbill.DNS.Record} objects,
* representing the signed zone. * representing the signed zone.
* *
@ -489,20 +500,20 @@ public class JCEDnsSecSigner
List zskpairs, Date start, Date expire, List zskpairs, Date start, Date expire,
boolean fullySignKeyset, boolean useOptOut, boolean fullySignKeyset, boolean useOptOut,
List includedNames, byte[] salt, int iterations, List includedNames, byte[] salt, int iterations,
int ds_digest_alg) int ds_digest_alg, long nsec3paramttl)
throws IOException, GeneralSecurityException throws IOException, GeneralSecurityException
{ {
if (useOptOut) if (useOptOut)
{ {
return signZone(zonename, records, kskpairs, zskpairs, start, expire, return signZone(zonename, records, kskpairs, zskpairs, start, expire,
fullySignKeyset, ds_digest_alg, NSEC3_OPTOUT_MODE, fullySignKeyset, ds_digest_alg, NSEC3_OPTOUT_MODE,
includedNames, salt, iterations, false); includedNames, salt, iterations, nsec3paramttl, false);
} }
else else
{ {
return signZone(zonename, records, kskpairs, zskpairs, start, expire, return signZone(zonename, records, kskpairs, zskpairs, start, expire,
fullySignKeyset, ds_digest_alg, NSEC3_MODE, null, salt, fullySignKeyset, ds_digest_alg, NSEC3_MODE, null, salt,
iterations, false); iterations, nsec3paramttl, false);
} }
} }
@ -546,6 +557,6 @@ public class JCEDnsSecSigner
return signZone(zonename, records, kskpairs, zskpairs, start, expire, return signZone(zonename, records, kskpairs, zskpairs, start, expire,
fullySignKeyset, ds_digest_alg, NSEC_EXP_OPT_IN, fullySignKeyset, ds_digest_alg, NSEC_EXP_OPT_IN,
NSECIncludeNames, null, 0, useConservativeOptIn); NSECIncludeNames, null, 0, 0, useConservativeOptIn);
} }
} }

View File

@ -340,14 +340,16 @@ public class SignUtils
{ {
if (signature[0] != ASN1_SEQ || signature[2] != ASN1_INT) if (signature[0] != ASN1_SEQ || signature[2] != ASN1_INT)
{ {
throw new SignatureException("Invalid ASN.1 signature format: expected SEQ, INT"); throw new SignatureException(
"Invalid ASN.1 signature format: expected SEQ, INT");
} }
byte r_pad = (byte) (signature[3] - 20); byte r_pad = (byte) (signature[3] - 20);
if (signature[24 + r_pad] != ASN1_INT) if (signature[24 + r_pad] != ASN1_INT)
{ {
throw new SignatureException("Invalid ASN.1 signature format: expected SEQ, INT, INT"); throw new SignatureException(
"Invalid ASN.1 signature format: expected SEQ, INT, INT");
} }
log.finer("(start) ASN.1 DSA Sig:\n" + base64.toString(signature)); log.finer("(start) ASN.1 DSA Sig:\n" + base64.toString(signature));
@ -503,8 +505,7 @@ public class SignUtils
// Current record is part of the current RRset. // Current record is part of the current RRset.
if (rrset.getName().equals(r.getName()) if (rrset.getName().equals(r.getName())
&& rrset.getDClass() == r.getDClass() && rrset.getDClass() == r.getDClass()
&& ((r.getType() == Type.RRSIG && rrset.getType() == ((RRSIGRecord) r).getTypeCovered()) || && ((r.getType() == Type.RRSIG && rrset.getType() == ((RRSIGRecord) r).getTypeCovered()) || rrset.getType() == r.getType()))
rrset.getType() == r.getType()))
{ {
rrset.addRR(r); rrset.addRR(r);
continue; continue;
@ -585,7 +586,7 @@ public class SignUtils
/** /**
* Given a canonical (by name) ordered list of records in a zone, generate the * Given a canonical (by name) ordered list of records in a zone, generate the
* NXT records in place. * NSEC records in place.
* *
* Note that the list that the records are stored in must support the * Note that the list that the records are stored in must support the
* listIterator.add() operation. * listIterator.add() operation.
@ -699,8 +700,31 @@ public class SignUtils
log.finer("Generated: " + nsec); log.finer("Generated: " + nsec);
} }
/**
* Given a canonical (by name) ordered list of records in a zone, generate the
* NSEC3 records in place.
*
* Note that the list that the records are stored in must support the
* listIterator.add() operation.
*
* @param zonename
* the name of the zone (used to distinguish between zone apex NS
* RRsets and delegations).
* @param records
* a list of {@link org.xbill.DNS.Record} objects in DNSSEC canonical
* order.
* @param salt
* The NSEC3 salt to use (may be null or empty for no salt).
* @param iterations
* The number of hash iterations to use.
* @param nsec3param_ttl
* The TTL to use for the generated NSEC3PARAM records (NSEC3 records
* will use the SOA minimum)
* @throws NoSuchAlgorithmException
*/
public static void generateNSEC3Records(Name zonename, List records, public static void generateNSEC3Records(Name zonename, List records,
byte[] salt, int iterations) byte[] salt, int iterations,
long nsec3param_ttl)
throws NoSuchAlgorithmException throws NoSuchAlgorithmException
{ {
List proto_nsec3s = new ArrayList(); List proto_nsec3s = new ArrayList();
@ -710,7 +734,6 @@ public class SignUtils
Name last_cut = null; Name last_cut = null;
long nsec3_ttl = 0; long nsec3_ttl = 0;
long nsec3param_ttl = 0;
for (Iterator i = records.iterator(); i.hasNext();) for (Iterator i = records.iterator(); i.hasNext();)
{ {
@ -731,8 +754,11 @@ public class SignUtils
{ {
SOARecord soa = (SOARecord) r; SOARecord soa = (SOARecord) r;
nsec3_ttl = soa.getMinimum(); nsec3_ttl = soa.getMinimum();
if (nsec3param_ttl < 0)
{
nsec3param_ttl = soa.getTTL(); nsec3param_ttl = soa.getTTL();
} }
}
// 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)
@ -785,9 +811,38 @@ public class SignUtils
} }
/**
* Given a canonical (by name) ordered list of records in a zone, generate the
* NSEC3 records in place using Opt-Out NSEC3 records. This means that
* non-apex NS RRs (and glue below those delegations) will, by default, not be
* included in the NSEC3 chain.
*
* Note that the list that the records are stored in must support the
* listIterator.add() operation.
*
* @param zonename
* the name of the zone (used to distinguish between zone apex NS
* RRsets and delegations).
* @param records
* a list of {@link org.xbill.DNS.Record} objects in DNSSEC canonical
* order.
* @param includedNames
* A list of {@link org.xbill.DNS.Name} objects. These names will be
* included in the NSEC3 chain (if they exist in the zone)
* regardless.
* @param salt
* The NSEC3 salt to use (may be null or empty for no salt).
* @param iterations
* The number of hash iterations to use.
* @param nsec3param_ttl
* The TTL to use for the generated NSEC3PARAM records (NSEC3 records
* will use the SOA minimum)
* @throws NoSuchAlgorithmException
*/
public static void generateOptOutNSEC3Records(Name zonename, List records, public static void generateOptOutNSEC3Records(Name zonename, List records,
List includedNames, List includedNames,
byte[] salt, int iterations) byte[] salt, int iterations,
long nsec3param_ttl)
throws NoSuchAlgorithmException throws NoSuchAlgorithmException
{ {
List proto_nsec3s = new ArrayList(); List proto_nsec3s = new ArrayList();
@ -797,7 +852,6 @@ public class SignUtils
Name last_cut = null; Name last_cut = null;
long nsec3_ttl = 0; long nsec3_ttl = 0;
long nsec3param_ttl = 0;
HashSet includeSet = null; HashSet includeSet = null;
if (includedNames != null) if (includedNames != null)
@ -824,8 +878,11 @@ public class SignUtils
{ {
SOARecord soa = (SOARecord) r; SOARecord soa = (SOARecord) r;
nsec3_ttl = soa.getMinimum(); nsec3_ttl = soa.getMinimum();
if (nsec3param_ttl < 0)
{
nsec3param_ttl = soa.getTTL(); nsec3param_ttl = soa.getTTL();
} }
}
// 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)
@ -883,6 +940,25 @@ public class SignUtils
records.add(nsec3param); records.add(nsec3param);
} }
/**
* For a given node (representing all of the RRsets at a given name), generate
* all of the necessary NSEC3 records for it. That is, generate the NSEC3 for
* the node itself, and for any potential empty non-terminals.
*
* @param node
* The node in question.
* @param zonename
* The zonename.
* @param salt
* The salt to use for the NSEC3 RRs
* @param iterations
* The iterations to use for the NSEC3 RRs.
* @param optIn
* If true, the NSEC3 will have the Opt-Out flag set.
* @param nsec3s
* The current list of NSEC3s -- this will be updated.
* @throws NoSuchAlgorithmException
*/
private static void generateNSEC3ForNode(NodeInfo node, Name zonename, private static void generateNSEC3ForNode(NodeInfo node, Name zonename,
byte[] salt, int iterations, byte[] salt, int iterations,
boolean optIn, List nsec3s) boolean optIn, List nsec3s)
@ -912,6 +988,27 @@ public class SignUtils
nsec3s.add(nsec3); nsec3s.add(nsec3);
} }
/**
* Create a "prototype" NSEC3 record. Basically, a mutable NSEC3 record.
*
* @param name
* The original ownername to use.
* @param zonename
* The zonename to use.
* @param ttl
* The TTL to use.
* @param salt
* The salt to use.
* @param iterations
* The number of hash iterations to use.
* @param optIn
* The value of the Opt-Out flag.
* @param types
* The typecodes present at this name.
* @return A mutable NSEC3 record.
*
* @throws NoSuchAlgorithmException
*/
private static ProtoNSEC3 generateNSEC3(Name name, Name zonename, long ttl, private static ProtoNSEC3 generateNSEC3(Name name, Name zonename, long ttl,
byte[] salt, int iterations, byte[] salt, int iterations,
boolean optIn, int[] types) boolean optIn, int[] types)
@ -921,14 +1018,26 @@ public class SignUtils
iterations, salt); iterations, salt);
byte flags = (byte) (optIn ? 0x01 : 0x00); byte flags = (byte) (optIn ? 0x01 : 0x00);
ProtoNSEC3 r = new ProtoNSEC3(hash, name, zonename, DClass.IN, ttl, flags, ProtoNSEC3 r = new ProtoNSEC3(hash, name, zonename, DClass.IN, ttl,
NSEC3Record.SHA1_DIGEST_ID, iterations, salt, NSEC3Record.SHA1_DIGEST_ID, flags,
null, types); iterations, salt, null, types);
log.finer("Generated: " + r); log.finer("Generated: " + r);
return r; return r;
} }
/**
* Given a list of {@link ProtoNSEC3} object (mutable NSEC3 RRs), convert the
* list into the set of actual {@link org.xbill.DNS.NSEC3Record} objects. This
* will remove duplicates and finalize the records.
*
* @param nsec3s
* The list of ProtoNSEC3 objects
* @param ttl
* The TTL to assign to the finished NSEC3 records. In general, this
* should match the SOA minimum value for the zone.
* @return The list of {@link org.xbill.DNS.NSEC3Record} objects.
*/
private static List finishNSEC3s(List nsec3s, long ttl) private static List finishNSEC3s(List nsec3s, long ttl)
{ {
if (nsec3s == null) return null; if (nsec3s == null) return null;