/* * Copyright (c) 2005, 2022 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.security; import org.xbill.DNS.DClass; import org.xbill.DNS.NSEC3Record; import org.xbill.DNS.Name; import org.xbill.DNS.TextParseException; import org.xbill.DNS.utils.base16; import org.xbill.DNS.utils.base32; /** * This is a class representing a "prototype NSEC3" resource record. These are * used as an intermediate stage (in zone signing) between determining the list * of NSEC3 records and forming them into a viable chain. * * @author David Blacka */ public class ProtoNSEC3 { private Name originalOwner; private int hashAlg; private byte flags; private int iterations; private byte[] salt; private byte[] next; private byte[] owner; // cached numerical owner value. private TypeMap typemap; private Name zone; private Name name; private int dclass; private long ttl; private static final base32 b32 = new base32(base32.Alphabet.BASE32HEX, false, false); /** * Creates an NSEC3 Record from the given data. */ public ProtoNSEC3(byte[] owner, Name originalOwner, Name zone, int dclass, long ttl, int hashAlg, byte flags, int iterations, byte[] salt, byte[] next, TypeMap typemap) { this.zone = zone; this.owner = owner; this.dclass = dclass; this.ttl = ttl; this.hashAlg = hashAlg; this.flags = flags; this.iterations = iterations; this.salt = salt; this.next = next; this.typemap = typemap; this.originalOwner = originalOwner; } public ProtoNSEC3(byte[] owner, Name originalOwner, Name zone, int dclass, long ttl, int hashAlg, byte flags, int iterations, byte[] salt, byte[] next, int[] types) { this(owner, originalOwner, zone, dclass, ttl, hashAlg, flags, iterations, salt, next, TypeMap.fromTypes(types)); } private String hashToString(byte[] hash) { if (hash == null) return null; return b32.toString(hash); } public Name getName() { if (name == null) { try { name = new Name(hashToString(owner), zone); } catch (TextParseException e) { // This isn't going to happen. } } return name; } public Name getOriginalOwnerName() { return this.originalOwner; } public byte[] getNext() { return next; } public void setNext(byte[] next) { this.next = next; } public byte getFlags() { return flags; } public boolean getOptOutFlag() { return (flags & NSEC3Record.Flags.OPT_OUT) != 0; } public void setOptOutFlag(boolean optOutFlag) { if (optOutFlag) this.flags |= NSEC3Record.Flags.OPT_OUT; else this.flags &= ~NSEC3Record.Flags.OPT_OUT; } public long getTTL() { return ttl; } public void setTTL(long ttl) { this.ttl = ttl; } public TypeMap getTypemap() { return typemap; } public int[] getTypes() { return typemap.getTypes(); } public void setTypemap(TypeMap typemap) { this.typemap = typemap; } public int getDClass() { return dclass; } public int getHashAlgorithm() { return hashAlg; } public int getIterations() { return iterations; } public byte[] getOwner() { return owner; } public byte[] getSalt() { return salt; } public Name getZone() { return zone; } public NSEC3Record getNSEC3Record() { return new NSEC3Record(getName(), dclass, ttl, hashAlg, flags, iterations, salt, next, getTypes()); } public void mergeTypes(TypeMap newTypes) { int[] nt = newTypes.getTypes(); for (int i = 0; i < nt.length; i++) { if (!typemap.get(nt[i])) typemap.set(nt[i]); } } public int compareTo(ProtoNSEC3 o) { if (o == null) return 1; byte[] origOwner = o.getOwner(); int len = owner.length < origOwner.length ? origOwner.length : owner.length; for (int i = 0; i < len; i++) { int d = ((owner[i] & 0xFF) - (origOwner[i] & 0xFF)); if (d != 0) return d; } return owner.length - origOwner.length; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getName()); sb.append(' '); sb.append(ttl); sb.append(' '); sb.append(DClass.string(dclass)); sb.append(" NSEC3 "); sb.append(flags); sb.append(' '); sb.append(hashAlg); sb.append(' '); sb.append(iterations); sb.append(' '); sb.append(salt == null ? "-" : base16.toString(salt)); sb.append(' '); String nextstr = (next == null) ? "(null)" : b32.toString(next); sb.append(nextstr); sb.append(' '); sb.append(typemap.toString()); return sb.toString(); } public static class Comparator implements java.util.Comparator { public int compare(ProtoNSEC3 a, ProtoNSEC3 b) { return a.compareTo(b); } } }