/* * Copied from the DnsJava project * * Copyright (c) 1998-2011, Brian Wellington. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * 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. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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 io.milton.dns.record; import io.milton.dns.Name; import java.io.*; import java.security.PublicKey; import java.util.*; /** * Key - contains a cryptographic public key. The data can be converted * to objects implementing java.security.interfaces.PublicKey * @see DNSSEC * * @author Brian Wellington */ public class KEYRecord extends KEYBase { private static final long serialVersionUID = 6385613447571488906L; public static class Protocol { /** * KEY protocol identifiers. */ private Protocol() {} /** No defined protocol. */ public static final int NONE = 0; /** Transaction Level Security */ public static final int TLS = 1; /** Email */ public static final int EMAIL = 2; /** DNSSEC */ public static final int DNSSEC = 3; /** IPSEC Control */ public static final int IPSEC = 4; /** Any protocol */ public static final int ANY = 255; private static final Mnemonic protocols = new Mnemonic("KEY protocol", Mnemonic.CASE_UPPER); static { protocols.setMaximum(0xFF); protocols.setNumericAllowed(true); protocols.add(NONE, "NONE"); protocols.add(TLS, "TLS"); protocols.add(EMAIL, "EMAIL"); protocols.add(DNSSEC, "DNSSEC"); protocols.add(IPSEC, "IPSEC"); protocols.add(ANY, "ANY"); } /** * Converts an KEY protocol value into its textual representation */ public static String string(int type) { return protocols.getText(type); } /** * Converts a textual representation of a KEY protocol into its * numeric code. Integers in the range 0..255 are also accepted. * @param s The textual representation of the protocol * @return The protocol code, or -1 on error. */ public static int value(String s) { return protocols.getValue(s); } } public static class Flags { /** * KEY flags identifiers. */ private Flags() {} /** KEY cannot be used for confidentiality */ public static final int NOCONF = 0x4000; /** KEY cannot be used for authentication */ public static final int NOAUTH = 0x8000; /** No key present */ public static final int NOKEY = 0xC000; /** Bitmask of the use fields */ public static final int USE_MASK = 0xC000; /** Flag 2 (unused) */ public static final int FLAG2 = 0x2000; /** Flags extension */ public static final int EXTEND = 0x1000; /** Flag 4 (unused) */ public static final int FLAG4 = 0x0800; /** Flag 5 (unused) */ public static final int FLAG5 = 0x0400; /** Key is owned by a user. */ public static final int USER = 0x0000; /** Key is owned by a zone. */ public static final int ZONE = 0x0100; /** Key is owned by a host. */ public static final int HOST = 0x0200; /** Key owner type 3 (reserved). */ public static final int NTYP3 = 0x0300; /** Key owner bitmask. */ public static final int OWNER_MASK = 0x0300; /** Flag 8 (unused) */ public static final int FLAG8 = 0x0080; /** Flag 9 (unused) */ public static final int FLAG9 = 0x0040; /** Flag 10 (unused) */ public static final int FLAG10 = 0x0020; /** Flag 11 (unused) */ public static final int FLAG11 = 0x0010; /** Signatory value 0 */ public static final int SIG0 = 0; /** Signatory value 1 */ public static final int SIG1 = 1; /** Signatory value 2 */ public static final int SIG2 = 2; /** Signatory value 3 */ public static final int SIG3 = 3; /** Signatory value 4 */ public static final int SIG4 = 4; /** Signatory value 5 */ public static final int SIG5 = 5; /** Signatory value 6 */ public static final int SIG6 = 6; /** Signatory value 7 */ public static final int SIG7 = 7; /** Signatory value 8 */ public static final int SIG8 = 8; /** Signatory value 9 */ public static final int SIG9 = 9; /** Signatory value 10 */ public static final int SIG10 = 10; /** Signatory value 11 */ public static final int SIG11 = 11; /** Signatory value 12 */ public static final int SIG12 = 12; /** Signatory value 13 */ public static final int SIG13 = 13; /** Signatory value 14 */ public static final int SIG14 = 14; /** Signatory value 15 */ public static final int SIG15 = 15; private static final Mnemonic flags = new Mnemonic("KEY flags", Mnemonic.CASE_UPPER); static { flags.setMaximum(0xFFFF); flags.setNumericAllowed(false); flags.add(NOCONF, "NOCONF"); flags.add(NOAUTH, "NOAUTH"); flags.add(NOKEY, "NOKEY"); flags.add(FLAG2, "FLAG2"); flags.add(EXTEND, "EXTEND"); flags.add(FLAG4, "FLAG4"); flags.add(FLAG5, "FLAG5"); flags.add(USER, "USER"); flags.add(ZONE, "ZONE"); flags.add(HOST, "HOST"); flags.add(NTYP3, "NTYP3"); flags.add(FLAG8, "FLAG8"); flags.add(FLAG9, "FLAG9"); flags.add(FLAG10, "FLAG10"); flags.add(FLAG11, "FLAG11"); flags.add(SIG0, "SIG0"); flags.add(SIG1, "SIG1"); flags.add(SIG2, "SIG2"); flags.add(SIG3, "SIG3"); flags.add(SIG4, "SIG4"); flags.add(SIG5, "SIG5"); flags.add(SIG6, "SIG6"); flags.add(SIG7, "SIG7"); flags.add(SIG8, "SIG8"); flags.add(SIG9, "SIG9"); flags.add(SIG10, "SIG10"); flags.add(SIG11, "SIG11"); flags.add(SIG12, "SIG12"); flags.add(SIG13, "SIG13"); flags.add(SIG14, "SIG14"); flags.add(SIG15, "SIG15"); } /** * Converts a textual representation of KEY flags into its * numeric code. Integers in the range 0..65535 are also accepted. * @param s The textual representation of the protocol * @return The protocol code, or -1 on error. */ public static int value(String s) { int value; try { value = Integer.parseInt(s); if (value >= 0 && value <= 0xFFFF) { return value; } return -1; } catch (NumberFormatException e) { } StringTokenizer st = new StringTokenizer(s, "|"); value = 0; while (st.hasMoreTokens()) { int val = flags.getValue(st.nextToken()); if (val < 0) { return -1; } value |= val; } return value; } } /* flags */ /** This key cannot be used for confidentiality (encryption) */ public static final int FLAG_NOCONF = Flags.NOCONF; /** This key cannot be used for authentication */ public static final int FLAG_NOAUTH = Flags.NOAUTH; /** This key cannot be used for authentication or confidentiality */ public static final int FLAG_NOKEY = Flags.NOKEY; /** A zone key */ public static final int OWNER_ZONE = Flags.ZONE; /** A host/end entity key */ public static final int OWNER_HOST = Flags.HOST; /** A user key */ public static final int OWNER_USER = Flags.USER; /* protocols */ /** Key was created for use with transaction level security */ public static final int PROTOCOL_TLS = Protocol.TLS; /** Key was created for use with email */ public static final int PROTOCOL_EMAIL = Protocol.EMAIL; /** Key was created for use with DNSSEC */ public static final int PROTOCOL_DNSSEC = Protocol.DNSSEC; /** Key was created for use with IPSEC */ public static final int PROTOCOL_IPSEC = Protocol.IPSEC; /** Key was created for use with any protocol */ public static final int PROTOCOL_ANY = Protocol.ANY; KEYRecord() {} Record getObject() { return new KEYRecord(); } /** * Creates a KEY Record from the given data * @param flags Flags describing the key's properties * @param proto The protocol that the key was created for * @param alg The key's algorithm * @param key Binary data representing the key */ public KEYRecord(Name name, int dclass, long ttl, int flags, int proto, int alg, byte [] key) { super(name, Type.KEY, dclass, ttl, flags, proto, alg, key); } /** * Creates a KEY Record from the given data * @param flags Flags describing the key's properties * @param proto The protocol that the key was created for * @param alg The key's algorithm * @param key The key as a PublicKey * @throws DNSSEC.DNSSECException The PublicKey could not be converted into DNS * format. */ public KEYRecord(Name name, int dclass, long ttl, int flags, int proto, int alg, PublicKey key) throws DNSSEC.DNSSECException { super(name, Type.KEY, dclass, ttl, flags, proto, alg, DNSSEC.fromPublicKey(key, alg)); publicKey = key; } void rdataFromString(Tokenizer st, Name origin) throws IOException { String flagString = st.getIdentifier(); flags = Flags.value(flagString); if (flags < 0) throw st.exception("Invalid flags: " + flagString); String protoString = st.getIdentifier(); proto = Protocol.value(protoString); if (proto < 0) throw st.exception("Invalid protocol: " + protoString); String algString = st.getIdentifier(); alg = DNSSEC.Algorithm.value(algString); if (alg < 0) throw st.exception("Invalid algorithm: " + algString); /* If this is a null KEY, there's no key data */ if ((flags & Flags.USE_MASK) == Flags.NOKEY) key = null; else key = st.getBase64(); } }