aboutsummaryrefslogtreecommitdiff
path: root/src/org/xbill/DNS/NSEC3Record.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/xbill/DNS/NSEC3Record.java')
-rw-r--r--src/org/xbill/DNS/NSEC3Record.java266
1 files changed, 266 insertions, 0 deletions
diff --git a/src/org/xbill/DNS/NSEC3Record.java b/src/org/xbill/DNS/NSEC3Record.java
new file mode 100644
index 0000000..aa086b8
--- /dev/null
+++ b/src/org/xbill/DNS/NSEC3Record.java
@@ -0,0 +1,266 @@
+// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
+
+package org.xbill.DNS;
+
+import java.io.*;
+import java.security.*;
+
+import org.xbill.DNS.utils.*;
+
+/**
+ * Next SECure name 3 - this record contains the next hashed name in an
+ * ordered list of hashed names in the zone, and a set of types for which
+ * records exist for this name. The presence of this record in a response
+ * signifies a negative response from a DNSSEC-signed zone.
+ *
+ * This replaces the NSEC and NXT records, when used.
+ *
+ * @author Brian Wellington
+ * @author David Blacka
+ */
+
+public class NSEC3Record extends Record {
+
+public static class Flags {
+ /**
+ * NSEC3 flags identifiers.
+ */
+
+ private Flags() {}
+
+ /** Unsigned delegation are not included in the NSEC3 chain.
+ *
+ */
+ public static final int OPT_OUT = 0x01;
+}
+
+public static class Digest {
+ private Digest() {}
+
+ /** SHA-1 */
+ public static final int SHA1 = 1;
+}
+
+public static final int SHA1_DIGEST_ID = Digest.SHA1;
+
+private static final long serialVersionUID = -7123504635968932855L;
+
+private int hashAlg;
+private int flags;
+private int iterations;
+private byte [] salt;
+private byte [] next;
+private TypeBitmap types;
+
+private static final base32 b32 = new base32(base32.Alphabet.BASE32HEX,
+ false, false);
+
+NSEC3Record() {}
+
+Record getObject() {
+ return new NSEC3Record();
+}
+
+/**
+ * Creates an NSEC3 record from the given data.
+ *
+ * @param name The ownername of the NSEC3 record (base32'd hash plus zonename).
+ * @param dclass The class.
+ * @param ttl The TTL.
+ * @param hashAlg The hash algorithm.
+ * @param flags The value of the flags field.
+ * @param iterations The number of hash iterations.
+ * @param salt The salt to use (may be null).
+ * @param next The next hash (may not be null).
+ * @param types The types present at the original ownername.
+ */
+public NSEC3Record(Name name, int dclass, long ttl, int hashAlg,
+ int flags, int iterations, byte [] salt, byte [] next,
+ int [] types)
+{
+ super(name, Type.NSEC3, dclass, ttl);
+ this.hashAlg = checkU8("hashAlg", hashAlg);
+ this.flags = checkU8("flags", flags);
+ this.iterations = checkU16("iterations", iterations);
+
+ if (salt != null) {
+ if (salt.length > 255)
+ throw new IllegalArgumentException("Invalid salt");
+ if (salt.length > 0) {
+ this.salt = new byte[salt.length];
+ System.arraycopy(salt, 0, this.salt, 0, salt.length);
+ }
+ }
+
+ if (next.length > 255) {
+ throw new IllegalArgumentException("Invalid next hash");
+ }
+ this.next = new byte[next.length];
+ System.arraycopy(next, 0, this.next, 0, next.length);
+ this.types = new TypeBitmap(types);
+}
+
+void
+rrFromWire(DNSInput in) throws IOException {
+ hashAlg = in.readU8();
+ flags = in.readU8();
+ iterations = in.readU16();
+
+ int salt_length = in.readU8();
+ if (salt_length > 0)
+ salt = in.readByteArray(salt_length);
+ else
+ salt = null;
+
+ int next_length = in.readU8();
+ next = in.readByteArray(next_length);
+ types = new TypeBitmap(in);
+}
+
+void
+rrToWire(DNSOutput out, Compression c, boolean canonical) {
+ out.writeU8(hashAlg);
+ out.writeU8(flags);
+ out.writeU16(iterations);
+
+ if (salt != null) {
+ out.writeU8(salt.length);
+ out.writeByteArray(salt);
+ } else
+ out.writeU8(0);
+
+ out.writeU8(next.length);
+ out.writeByteArray(next);
+ types.toWire(out);
+}
+
+void
+rdataFromString(Tokenizer st, Name origin) throws IOException {
+ hashAlg = st.getUInt8();
+ flags = st.getUInt8();
+ iterations = st.getUInt16();
+
+ String s = st.getString();
+ if (s.equals("-"))
+ salt = null;
+ else {
+ st.unget();
+ salt = st.getHexString();
+ if (salt.length > 255)
+ throw st.exception("salt value too long");
+ }
+
+ next = st.getBase32String(b32);
+ types = new TypeBitmap(st);
+}
+
+/** Converts rdata to a String */
+String
+rrToString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(hashAlg);
+ sb.append(' ');
+ sb.append(flags);
+ sb.append(' ');
+ sb.append(iterations);
+ sb.append(' ');
+ if (salt == null)
+ sb.append('-');
+ else
+ sb.append(base16.toString(salt));
+ sb.append(' ');
+ sb.append(b32.toString(next));
+
+ if (!types.empty()) {
+ sb.append(' ');
+ sb.append(types.toString());
+ }
+
+ return sb.toString();
+}
+
+/** Returns the hash algorithm */
+public int
+getHashAlgorithm() {
+ return hashAlg;
+}
+
+/** Returns the flags */
+public int
+getFlags() {
+ return flags;
+}
+
+/** Returns the number of iterations */
+public int
+getIterations() {
+ return iterations;
+}
+
+/** Returns the salt */
+public byte []
+getSalt()
+{
+ return salt;
+}
+
+/** Returns the next hash */
+public byte []
+getNext() {
+ return next;
+}
+
+ /** Returns the set of types defined for this name */
+public int []
+getTypes() {
+ return types.toArray();
+}
+
+/** Returns whether a specific type is in the set of types. */
+public boolean
+hasType(int type)
+{
+ return types.contains(type);
+}
+
+static byte []
+hashName(Name name, int hashAlg, int iterations, byte [] salt)
+throws NoSuchAlgorithmException
+{
+ MessageDigest digest;
+ switch (hashAlg) {
+ case Digest.SHA1:
+ digest = MessageDigest.getInstance("sha-1");
+ break;
+ default:
+ throw new NoSuchAlgorithmException("Unknown NSEC3 algorithm" +
+ "identifier: " +
+ hashAlg);
+ }
+ byte [] hash = null;
+ for (int i = 0; i <= iterations; i++) {
+ digest.reset();
+ if (i == 0)
+ digest.update(name.toWireCanonical());
+ else
+ digest.update(hash);
+ if (salt != null)
+ digest.update(salt);
+ hash = digest.digest();
+ }
+ return hash;
+}
+
+/**
+ * Hashes a name with the parameters of this NSEC3 record.
+ * @param name The name to hash
+ * @return The hashed version of the name
+ * @throws NoSuchAlgorithmException The hash algorithm is unknown.
+ */
+public byte []
+hashName(Name name) throws NoSuchAlgorithmException
+{
+ return hashName(name, hashAlg, iterations, salt);
+}
+
+}