From 0b8c4c747dcb1f3d550e61e1aa0977bb3b5a4f2c Mon Sep 17 00:00:00 2001 From: David Blacka Date: Tue, 8 Nov 2005 19:08:13 +0000 Subject: [PATCH] new zoneformatter, bug fixes git-svn-id: https://svn.verisignlabs.com/jdnssec/tools/trunk@42 4cbd57fe-54e5-0310-bd9a-f30fe5ea5e6e --- README | 9 +- bin/_jdnssec-zoneformat | 16 ++ bin/jdnssec-zoneformat | 14 + build.xml | 2 +- .../verisignlabs/dnssec/cl/ZoneFormat.java | 244 ++++++++++++++++++ .../dnssec/security/SignUtils.java | 21 +- 6 files changed, 303 insertions(+), 3 deletions(-) create mode 100755 bin/_jdnssec-zoneformat create mode 100755 bin/jdnssec-zoneformat create mode 100644 src/com/verisignlabs/dnssec/cl/ZoneFormat.java diff --git a/README b/README index eb7d2b5..40ad66b 100644 --- a/README +++ b/README @@ -12,7 +12,8 @@ These tools depend upon DNSjava (http://www.xbill.org/dnsjava), the Jakarta Commons CLI and Logging libraries (http://jakarta.apache.org), and Sun's Java Cryptography extensions. A copy of each of these libraries is included in the distribution. Currently, these tools use -a custom version of the DNSjava library (for NSEC3 support) +a custom version of the DNSjava library (for NSEC3 support), which is +provided. See the "licenses" directory for the licensing information of this package and the other packages that are distributed with it. @@ -47,6 +48,12 @@ build tool). run the tools directly from the build area by using the ./bin/_jdnssec_* wrappers. + +The source for this project is available in subversion, at +http://svn.verisignlabs.com/main/dnssec/sectools/trunk. Source for +the modified DNSjava library can be found in subversion at +http://svn.verisignlabs.com/main/dnssec/dnsjava/trunk. + --- Questions or comments may be directed to the author diff --git a/bin/_jdnssec-zoneformat b/bin/_jdnssec-zoneformat new file mode 100755 index 0000000..f81fb60 --- /dev/null +++ b/bin/_jdnssec-zoneformat @@ -0,0 +1,16 @@ +#! /bin/sh + +thisdir=`dirname $0` +basedir=`cd $thisdir/..; pwd` + +ulimit -n `ulimit -H -n` + +# set the classpath +CLASSPATH=$CLASSPATH:$basedir/build/classes + +for i in $basedir/lib/*.jar $basedir/lib/*.zip; do + CLASSPATH="$CLASSPATH":"$i" +done +export CLASSPATH + +exec java com.verisignlabs.dnssec.cl.ZoneFormat "$@" diff --git a/bin/jdnssec-zoneformat b/bin/jdnssec-zoneformat new file mode 100755 index 0000000..8499d81 --- /dev/null +++ b/bin/jdnssec-zoneformat @@ -0,0 +1,14 @@ +#! /bin/sh + +thisdir=`dirname $0` +basedir=`cd $thisdir/..; pwd` + +ulimit -n `ulimit -H -n` + +# set the classpath +for i in $basedir/lib/*.jar $basedir/lib/*.zip; do + CLASSPATH="$CLASSPATH":"$i" +done +export CLASSPATH + +exec java com.verisignlabs.dnssec.cl.ZoneFormat "$@" diff --git a/build.xml b/build.xml index 9ccc2c5..0fece34 100644 --- a/build.xml +++ b/build.xml @@ -23,7 +23,7 @@ - + diff --git a/src/com/verisignlabs/dnssec/cl/ZoneFormat.java b/src/com/verisignlabs/dnssec/cl/ZoneFormat.java new file mode 100644 index 0000000..ee15eca --- /dev/null +++ b/src/com/verisignlabs/dnssec/cl/ZoneFormat.java @@ -0,0 +1,244 @@ +/* + * $Id$ + * + * Copyright (c) 2005 VeriSign. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. The name of the author may not + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package com.verisignlabs.dnssec.cl; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.commons.cli.*; +import org.xbill.DNS.Master; +import org.xbill.DNS.Record; + +import com.verisignlabs.dnssec.security.RecordComparator; + +public class ZoneFormat +{ + // private static Logger log; + + /** + * This is a small inner class used to hold all of the command line option + * state. + */ + private static class CLIState + { + private org.apache.commons.cli.Options opts; + public String file; + + public CLIState() + { + setupCLI(); + } + + public void parseCommandLine(String[] args) + throws org.apache.commons.cli.ParseException + { + CommandLineParser cli_parser = new PosixParser(); + CommandLine cli = cli_parser.parse(opts, args); + + // String optstr = null; + + if (cli.hasOption('h')) usage(); + + if (cli.hasOption('v')) + { + int value = parseInt(cli.getOptionValue('v'), 5); + Logger rootLogger = Logger.getLogger(""); + switch (value) + { + case 0 : + rootLogger.setLevel(Level.OFF); + break; + case 5 : + default : + rootLogger.setLevel(Level.FINE); + break; + case 6 : + rootLogger.setLevel(Level.ALL); + break; + } + } + + String[] cl_args = cli.getArgs(); + + if (cl_args.length < 1) + { + System.err.println("error: must specify a zone file"); + usage(); + } + + file = cl_args[0]; + } + + /** + * Set up the command line options. + * + * @return a set of command line options. + */ + private void setupCLI() + { + opts = new org.apache.commons.cli.Options(); + + // boolean options + opts.addOption("h", "help", false, "Print this message."); + + // Argument options + OptionBuilder.hasOptionalArg(); + OptionBuilder.withLongOpt("verbose"); + OptionBuilder.withArgName("level"); + OptionBuilder.withDescription("verbosity level -- 0 is silence, " + + "5 is debug information, 6 is trace information.\n" + + "default is level 5."); + opts.addOption(OptionBuilder.create('v')); + } + + /** Print out the usage and help statements, then quit. */ + public void usage() + { + HelpFormatter f = new HelpFormatter(); + + PrintWriter out = new PrintWriter(System.err); + + // print our own usage statement: + f.printHelp(out, + 75, + "jdnssec-zoneformat [..options..] zonefile", + null, + opts, + HelpFormatter.DEFAULT_LEFT_PAD, + HelpFormatter.DEFAULT_DESC_PAD, + null); + + out.flush(); + System.exit(64); + + } + + /** + * This is just a convenience method for parsing integers from strings. + * + * @param s the string to parse. + * @param def the default value, if the string doesn't parse. + * @return the parsed integer, or the default. + */ + private static int parseInt(String s, int def) + { + try + { + int v = Integer.parseInt(s); + return v; + } + catch (NumberFormatException e) + { + return def; + } + } + + } + + private static List readZoneFile(String filename) throws IOException + { + Master master = new Master(filename); + + List res = new ArrayList(); + Record r = null; + + while ((r = master.nextRecord()) != null) + { + res.add(r); + } + + return res; + } + + private static void formatZone(List zone) + { + // Sort both zones. + RecordComparator cmp = new RecordComparator(); + + Collections.sort(zone, cmp); + + for (Iterator i = zone.iterator(); i.hasNext(); ) + { + Record r = (Record) i.next(); + System.out.println(r.toString()); + } + } + private static void execute(CLIState state) throws IOException + { + List z = readZoneFile(state.file); + formatZone(z); + } + + public static void main(String[] args) + { + CLIState state = new CLIState(); + + try + { + state.parseCommandLine(args); + } + catch (UnrecognizedOptionException e) + { + System.err.println("error: unknown option encountered: " + + e.getMessage()); + state.usage(); + } + catch (AlreadySelectedException e) + { + System.err.println("error: mutually exclusive options have " + + "been selected:\n " + e.getMessage()); + state.usage(); + } + catch (Exception e) + { + System.err.println("error: unknown command line parsing exception:"); + e.printStackTrace(); + state.usage(); + } + + // log = Logger.getLogger(VerifyZone.class.toString()); + + try + { + execute(state); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + +} diff --git a/src/com/verisignlabs/dnssec/security/SignUtils.java b/src/com/verisignlabs/dnssec/security/SignUtils.java index 737ec5e..376cdd9 100644 --- a/src/com/verisignlabs/dnssec/security/SignUtils.java +++ b/src/com/verisignlabs/dnssec/security/SignUtils.java @@ -29,6 +29,7 @@ import java.util.*; import java.util.logging.Logger; import org.xbill.DNS.*; +import org.xbill.DNS.utils.base16; import org.xbill.DNS.utils.base64; /** @@ -718,6 +719,13 @@ public class SignUtils proto_nsec3s); List nsec3s = finishNSEC3s(proto_nsec3s); + // DEBUG +// for (Iterator i = nsec3s.iterator(); i.hasNext();) +// { +// NSEC3Record nsec3 = (NSEC3Record) i.next(); +// log.fine("NSEC3: " + nsec3 + "\nRDATA: " +// + base16.toString(nsec3.rdataToWireCanonical())); +// } records.addAll(nsec3s); } @@ -909,8 +917,19 @@ public class SignUtils } // Handle last NSEC3. - cur_nsec3.setNext(first_nsec3_hash); + if (prev_nsec3.getNext() == null) + { + // if prev_nsec3's next field hasn't been set, then it is the last + // record (i.e., all remaining records were duplicates.) + prev_nsec3.setNext(first_nsec3_hash); + } + else + { + // otherwise, cur_nsec3 is the last record. + cur_nsec3.setNext(first_nsec3_hash); + } + // Convert our ProtoNSEC3s to actual (immutable) NSEC3Record objects. List res = new ArrayList(nsec3s.size()); for (Iterator i = nsec3s.iterator(); i.hasNext();) {