diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index ed721ef..1c73ace 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,11 +1,11 @@
-#Mon May 31 12:14:23 EDT 2010
+#Thu Jun 10 13:45:36 EDT 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
@@ -15,7 +15,7 @@ org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
diff --git a/build.xml b/build.xml
index c403b78..9723e53 100644
--- a/build.xml
+++ b/build.xml
@@ -45,7 +45,7 @@
-
+
diff --git a/lib/log4j.properties b/lib/log4j.properties
new file mode 100644
index 0000000..ebcdfba
--- /dev/null
+++ b/lib/log4j.properties
@@ -0,0 +1,24 @@
+
+####################################################################
+#
+# L O G 4 j A P P E N D E R s
+#
+###################################################################
+
+###################
+# Write Output to Console (aka TTY)
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
+####################################################################
+#
+# R O O T D E B U G G I N G L E V E L
+#
+###################################################################
+
+######################
+# Set root logger level to an (Appender)
+#
+log4j.rootLogger=FATAL, console
diff --git a/src/com/verisign/cl/DNSSECReconciler.java b/src/com/verisign/cl/DNSSECReconciler.java
index 9740880..64a3f05 100644
--- a/src/com/verisign/cl/DNSSECReconciler.java
+++ b/src/com/verisign/cl/DNSSECReconciler.java
@@ -1,15 +1,15 @@
package com.verisign.cl;
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
+import java.io.*;
import java.net.SocketTimeoutException;
import java.util.*;
+import org.apache.log4j.PropertyConfigurator;
import org.xbill.DNS.*;
import com.verisign.tat.dnssec.CaptiveValidator;
import com.verisign.tat.dnssec.SecurityStatus;
+import com.verisign.tat.dnssec.Util;
public class DNSSECReconciler {
@@ -21,6 +21,7 @@ public class DNSSECReconciler {
private SimpleResolver resolver;
private BufferedReader queryStream;
+ private PrintStream errorStream;
private Set zoneNames;
// Options
@@ -29,6 +30,8 @@ public class DNSSECReconciler {
public String queryFile;
public String dnskeyFile;
public List dnskeyNames;
+ public String errorFile;
+ public long count = 0;
DNSSECReconciler() {
validator = new CaptiveValidator();
@@ -62,6 +65,7 @@ public class DNSSECReconciler {
for (int i = 1; i < tokens.length; i++) {
if (tokens[i].startsWith("+")) {
// For now, we ignore flags as uninteresting
+ // All queries will get the DO bit anyway
continue;
}
@@ -83,8 +87,7 @@ 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;
}
@@ -125,7 +128,7 @@ public class DNSSECReconciler {
*
* @param query
* @return a zone name
- * @throws IOException
+ * @throws IOException
*/
private Name zoneFromQuery(Message query) throws IOException {
@@ -134,39 +137,43 @@ public class DNSSECReconciler {
for (String key : validator.listTrustedKeys()) {
String[] components = key.split("/");
Name keyname = Name.fromString(components[0]);
- if (! keyname.isAbsolute()) {
+ 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;
}
private Message resolve(Message query) {
-
+
try {
return resolver.send(query);
} catch (SocketTimeoutException e) {
- System.err.println("Error: timed out querying " + server + " for " + queryToString(query));
+ System.err.println("Error: timed out querying " + server + " for "
+ + queryToString(query));
} catch (IOException e) {
- System.err.println("Error: error querying " + server + " for " + queryToString(query) + ":" + e.getMessage());
+ System.err.println("Error: error querying " + server + " for "
+ + queryToString(query) + ":" + e.getMessage());
}
return null;
}
-
+
private String queryToString(Message query) {
- if (query == null) return null;
+ if (query == null)
+ return null;
Record question = query.getQuestion();
- return question.getName() + "/" + Type.string(question.getType()) + "/" + DClass.string(question.getDClass());
+ return question.getName() + "/" + Type.string(question.getType()) + "/"
+ + DClass.string(question.getDClass());
}
public void execute() throws IOException {
@@ -174,6 +181,13 @@ public class DNSSECReconciler {
resolver = new SimpleResolver(server);
resolver.setEDNS(0, 4096, Flags.DO, null);
+ // Create our DNSSEC error stream
+ if (errorFile != null) {
+ errorStream = new PrintStream(new FileOutputStream(errorFile, true));
+ } else {
+ errorStream = System.out;
+ }
+
// Prime the validator
if (dnskeyFile != null) {
validator.addTrustedKeysFromFile(dnskeyFile);
@@ -192,16 +206,18 @@ public class DNSSECReconciler {
// Iterate over all queries
Message query = nextQuery();
- long count = 0;
+ long total = 0;
+ long validCount = 0;
+ long errorCount = 0;
while (query != null) {
-
+
Name zone = zoneFromQuery(query);
// Skip queries in zones that we don't have keys for
if (zone == null) {
continue;
}
-
+
Message response = resolve(query);
if (response == null) {
continue;
@@ -211,53 +227,63 @@ public class DNSSECReconciler {
switch (result) {
case SecurityStatus.BOGUS:
case SecurityStatus.INVALID:
- System.out.println("BOGUS Answer:");
- System.out.println("Query: " + queryToString(query));
- System.out.println("Response:\n" + response);
+ errorStream.println("BOGUS Answer:");
+ errorStream.println("Query: " + queryToString(query));
+ errorStream.println("Response:\n" + response);
for (String err : validator.getErrorList()) {
- System.out.println("Error: " + err);
+ errorStream.println("Error: " + err);
}
- System.out.println("");
+ errorStream.println("");
+ errorCount++;
break;
case SecurityStatus.INSECURE:
case SecurityStatus.INDETERMINATE:
case SecurityStatus.UNCHECKED:
- System.out.println("Insecure Answer:");
- System.out.println("Query: " + queryToString(query));
- System.out.println("Response:\n" + response);
+ errorStream.println("Insecure Answer:");
+ errorStream.println("Query: " + queryToString(query));
+ errorStream.println("Response:\n" + response);
for (String err : validator.getErrorList()) {
- System.out.println("Error: " + err);
+ errorStream.println("Error: " + err);
}
+ errorCount++;
break;
case SecurityStatus.SECURE:
+ validCount++;
break;
}
-
- if (++count % 1000 == 0) {
- System.out.println("Completed " + count + " queries.");
+
+ if (++total % 1000 == 0) {
+ System.out.println("Completed " + total + " queries: "
+ + validCount + " valid, " + errorCount + " errors.");
+ }
+
+ if (count > 0 && total >= count) {
+ break;
}
query = nextQuery();
}
-
- System.out.println("Completed " + count + (count > 1 ? " queries" : " query"));
+
+ System.out.println("Completed " + total
+ + (total > 1 ? " queries" : " query") +
+ ": " + validCount + " valid, " + errorCount + " errors.");
}
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(" count: send up to'count' queries, then stop.");
+ 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(" error_file: write DNSSEC validation failure details to this file");
}
public static void main(String[] argv) {
+ PropertyConfigurator.configure("lib/log4j.properties");
+
DNSSECReconciler dr = new DNSSECReconciler();
try {
@@ -280,6 +306,10 @@ public class DNSSECReconciler {
dr.query = optarg;
} else if (opt.equals("query_file")) {
dr.queryFile = optarg;
+ } else if (opt.equals("count")) {
+ dr.count = Util.parseInt(optarg, 0);
+ } else if (opt.equals("error_file")) {
+ dr.errorFile = optarg;
} else if (opt.equals("dnskey_file")) {
dr.dnskeyFile = optarg;
} else if (opt.equals("dnskey_query")) {
@@ -301,14 +331,12 @@ public class DNSSECReconciler {
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();
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();
System.exit(1);
}