now basically works, although not tested
authordavidb <davidb@verisign.com>
Wed, 9 Jun 2010 22:25:26 +0000 (18:25 -0400)
committerdavidb <davidb@verisign.com>
Wed, 9 Jun 2010 22:25:26 +0000 (18:25 -0400)
build.xml [new file with mode: 0644]
src/com/verisign/cl/DNSSECReconciler.java
src/com/verisign/tat/dnssec/CaptiveValidator.java

diff --git a/build.xml b/build.xml
new file mode 100644 (file)
index 0000000..c403b78
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,92 @@
+<?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>
+
index 49c0777..20765ce 100644 (file)
@@ -1,10 +1,14 @@
 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 {
 
@@ -13,6 +17,10 @@ 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;
@@ -28,7 +36,7 @@ public class DNSSECReconciler {
     /**
      * Convert a query line of the form: <qname> <qtype> <flags> to a request
      * message.
-     *
+     * 
      * @param query_line
      * @return A query message
      * @throws TextParseException
@@ -74,24 +82,150 @@ public class DNSSECReconciler {
             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();
 
@@ -102,15 +236,17 @@ public class 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")) {
@@ -123,7 +259,7 @@ public class DNSSECReconciler {
                 } else {
                     System.err.println("Unrecognized option: " + opt);
                     usage();
-                    return 1;
+                    System.exit(1);
                 }
             }
 
@@ -131,17 +267,19 @@ public class DNSSECReconciler {
             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
@@ -149,9 +287,7 @@ public class DNSSECReconciler {
 
         } catch (Exception e) {
             e.printStackTrace();
-            return 1;
+            System.exit(1);
         }
-
-        return 0;
     }
 }
index 07311ce..74853de 100644 (file)
@@ -943,8 +943,7 @@ public class CaptiveValidator {
             return SecurityStatus.BOGUS;
         }
 
-        ValUtils.ResponseType subtype = ValUtils
-                .classifyResponse(message, zone);
+        ValUtils.ResponseType subtype = ValUtils.classifyResponse(message, zone);
 
         switch (subtype) {
         case POSITIVE: