--- /dev/null
+<?xml version="1.0"?>
+
+<project default="jar" basedir=".">
+
+ <property file="build.properties" />
+ <property file="VERSION" />
+
+ <property name="distname" value="dnssecreconciler-${version}" />
+
+ <property name="build.dir" value="build" />
+ <property name="build.dest" value="${build.dir}/classes" />
+ <property name="build.lib.dest" value="${build.dir}/lib" />
+ <property name="build.src" value="src" />
+
+ <property name="packages" value="com.verisignlabs.dnssec.*" />
+ <property name="doc.dir" value="docs" />
+ <property name="javadoc.dest" value="${doc.dir}/javadoc" />
+
+ <property name="lib.dir" value="lib" />
+
+ <!-- set the standard classpath -->
+ <path id="project.classpath">
+ <pathelement location="${build.dest}" />
+ <fileset dir="${lib.dir}" includes="*.jar,*.zip" />
+ </path>
+ <property name="project.classpath" refid="project.classpath" />
+
+ <target name="prepare-src">
+ <mkdir dir="${build.dest}" />
+ <mkdir dir="${build.lib.dest}" />
+ </target>
+
+ <target name="compile" depends="prepare-src" >
+ <javac srcdir="${build.src}"
+ destdir="${build.dest}"
+ classpathref="project.classpath"
+ deprecation="true"
+ includes="com/verisign/" />
+ </target>
+
+ <target name="jar" depends="usage,compile">
+
+ <jar destfile="${build.lib.dest}/dnssecreconciler.jar">
+ <zipfileset dir="${build.dest}" includes="**/*.class" />
+
+ <zipfileset src="${lib.dir}/dnsjava-2.0.8-vrsn-2.jar" />
+ <zipfileset src="${lib.dir}/log4j-1.2.15.jar" />
+
+ <manifest>
+ <attribute name="Main-Class"
+ value="com.verisign.cl.DNSSECReconciler" />
+ </manifest>
+ </jar>
+ </target>
+
+ <target name="javadoc" depends="usage">
+ <mkdir dir="${javadoc.dest}"/>
+ <javadoc packagenames="${packages}"
+ classpath="${project.classpath}"
+ sourcepath="${build.src}"
+ destdir="${javadoc.dest}"
+ verbose="true" author="true"
+ windowtitle="jdnssec-tools-${version}"
+ use="true">
+ <link href="http://java.sun.com/j2se/1.4.2/docs/api/" />
+ <link href="http://www.xbill.org/dnsjava/doc/" />
+ </javadoc>
+ </target>
+
+
+ <target name="clean" depends="usage">
+ <delete dir="${build.dest}" />
+ <delete dir="${build.lib.dest}" />
+ </target>
+
+
+ <target name="usage">
+ <echo message=" " />
+ <echo message="DNSSECReconciler v. ${version} Build System" />
+ <echo message="--------------------------------" />
+ <echo message="Available Targets:" />
+ <echo message=" compile - compiles the source code" />
+ <echo message=" jar (default) - compiles the source code, creates jar" />
+ <echo message=" javadoc - create javadoc from source" />
+ <echo message=" clean - delete class files" />
+ <echo message=" dist - package it up" />
+ <echo message=" usage - this help message" />
+ <echo message=" " />
+ </target>
+
+</project>
+
package com.verisign.cl;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
import java.util.*;
import org.xbill.DNS.*;
import com.verisign.tat.dnssec.CaptiveValidator;
+import com.verisign.tat.dnssec.SecurityStatus;
public class DNSSECReconciler {
* query_file=queries.txt dnskey_query=net dnskey_query=edu
*/
private CaptiveValidator validator;
+ private SimpleResolver resolver;
+
+ private BufferedReader queryStream;
+ private Set<Name> zoneNames;
// Options
public String server;
/**
* Convert a query line of the form: <qname> <qtype> <flags> to a request
* message.
- *
+ *
* @param query_line
* @return A query message
* @throws TextParseException
qclass = DClass.IN;
}
- Message query = Message.newQuery(Record.newRecord(qname, qtype, qclass));
+ Message query = Message
+ .newQuery(Record.newRecord(qname, qtype, qclass));
return query;
}
- public void execute() {
+ /**
+ * Fetch the next query from either the command line or the query file
+ *
+ * @return a query Message, or null if the query list is exhausted
+ * @throws IOException
+ */
+ private Message nextQuery() throws IOException {
+ if (query != null) {
+ Message res = queryFromString(query);
+ query = null;
+ return res;
+ }
+
+ if (queryStream == null && queryFile != null) {
+ queryStream = new BufferedReader(new FileReader(queryFile));
+ }
+
+ if (queryStream != null) {
+ String line = queryStream.readLine();
+
+ if (line == null)
+ return null;
+
+ return queryFromString(line);
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Figure out the correct zone from the query by comparing the qname to the
+ * list of trusted DNSKEY owner names.
+ *
+ * @param query
+ * @return a zone name
+ * @throws IOException
+ */
+ private Name zoneFromQuery(Message query) throws IOException {
+
+ if (zoneNames == null) {
+ zoneNames = new HashSet<Name>();
+ for (String key : validator.listTrustedKeys()) {
+ String[] components = key.split("/");
+ Name keyname = Name.fromString(components[0]);
+ if (! keyname.isAbsolute()) {
+ keyname = Name.concatenate(keyname, Name.root);
+ }
+ zoneNames.add(keyname);
+ }
+ }
+
+ Name qname = query.getQuestion().getName();
+ for (Name n : zoneNames) {
+ if (qname.subdomain(n)) {
+ return n;
+ }
+ }
+
+ return null;
+ }
+
+ public void execute() throws IOException {
+ // Configure our resolver
+ resolver = new SimpleResolver(server);
+ resolver.setEDNS(0, 4096, Flags.DO, null);
+
+ // Prime the validator
+ if (dnskeyFile != null) {
+ validator.addTrustedKeysFromFile(dnskeyFile);
+ } else {
+ for (String name : dnskeyNames) {
+ Message query = queryFromString(name + " DNSKEY");
+ Message response = resolver.send(query);
+ validator.addTrustedKeysFromResponse(response);
+ }
+ }
+
+ // Log our set of trusted keys
+ for (String key : validator.listTrustedKeys()) {
+ System.out.println("Trusted Key: " + key);
+ }
+
+ // Iterate over all queries
+ Message query = nextQuery();
+
+ while (query != null) {
+ Message response = resolver.send(query);
+ if (response == null) {
+ continue;
+ }
+
+ Name zone = zoneFromQuery(query);
+ byte result = validator.validateMessage(response, zone.toString());
+
+ switch (result) {
+ case SecurityStatus.BOGUS:
+ case SecurityStatus.INVALID:
+ System.out.println("BOGUS Answer:");
+ System.out.println("Query: " + query.getQuestion());
+ System.out.println("Response:\n" + response);
+ for (String err : validator.getErrorList()) {
+ System.out.println("Error: " + err);
+ }
+ System.out.println("");
+ break;
+ case SecurityStatus.INSECURE:
+ case SecurityStatus.INDETERMINATE:
+ case SecurityStatus.UNCHECKED:
+ System.out.println("Insecure Answer:");
+ System.out.println("Query: " + query.getQuestion());
+ System.out.println("Response:\n" + response);
+ for (String err : validator.getErrorList()) {
+ System.out.println("Error: " + err);
+ }
+ break;
+ case SecurityStatus.SECURE:
+ break;
+ }
+
+ query = nextQuery();
+ }
}
private static void usage() {
- System.err.println("usage: java -jar dnssecreconiler.jar [..options..]");
+ System.err
+ .println("usage: java -jar dnssecreconiler.jar [..options..]");
System.err.println(" server: the DNS server to query.");
System.err.println(" query: a name [type [flags]] string.");
- System.err.println(" query_file: a list of queries, one query per line.");
- System.err.println(" dnskey_file: a file containing DNSKEY RRs to trust.");
- System.err.println(" dnskey_query: query 'server' for DNSKEY at given name to trust, may repeat");
+ System.err
+ .println(" query_file: a list of queries, one query per line.");
+ System.err
+ .println(" dnskey_file: a file containing DNSKEY RRs to trust.");
+ System.err
+ .println(" dnskey_query: query 'server' for DNSKEY at given name to trust, may repeat");
}
- public static int main(String[] argv) {
+ public static void main(String[] argv) {
DNSSECReconciler dr = new DNSSECReconciler();
if (arg.indexOf('=') < 0) {
System.err.println("Unrecognized option: " + arg);
usage();
- return 1;
+ System.exit(1);
}
- String[] split_arg = arg.split("[ \t]*=[ \t]*", 2);
+ String[] split_arg = arg.split("=", 2);
String opt = split_arg[0];
String optarg = split_arg[1];
if (opt.equals("server")) {
dr.server = optarg;
+ } else if (opt.equals("query")) {
+ dr.query = optarg;
} else if (opt.equals("query_file")) {
dr.queryFile = optarg;
} else if (opt.equals("dnskey_file")) {
} else {
System.err.println("Unrecognized option: " + opt);
usage();
- return 1;
+ System.exit(1);
}
}
if (dr.server == null) {
System.err.println("'server' must be specified");
usage();
- return 1;
+ System.exit(1);
}
if (dr.query == null && dr.queryFile == null) {
- System.err.println("Either 'query' or 'query_file' must be specified");
+ System.err
+ .println("Either 'query' or 'query_file' must be specified");
usage();
- return 1;
+ System.exit(1);
}
if (dr.dnskeyFile == null && dr.dnskeyNames == null) {
- System.err.println("Either 'dnskey_file' or 'dnskey_query' must be specified");
+ System.err
+ .println("Either 'dnskey_file' or 'dnskey_query' must be specified");
usage();
- return 1;
+ System.exit(1);
}
// Execute the job
} catch (Exception e) {
e.printStackTrace();
- return 1;
+ System.exit(1);
}
-
- return 0;
}
}