1 // Copyright (c) 1999-2004 Brian Wellington (bwelling (at) xbill.org) 2 3 package org.xbill.DNS; 4 5 import java.io.*; 6 import java.security.PublicKey; 7 import java.util.*; 8 9 /** 10 * Key - contains a cryptographic public key. The data can be converted 11 * to objects implementing java.security.interfaces.PublicKey 12 * @see DNSSEC 13 * 14 * @author Brian Wellington 15 */ 16 17 public class KEYRecord extends KEYBase { 18 19 private static final long serialVersionUID = 6385613447571488906L; 20 21 public static class Protocol { 22 /** 23 * KEY protocol identifiers. 24 */ 25 26 private Protocol() {} 27 28 /** No defined protocol. */ 29 public static final int NONE = 0; 30 31 /** Transaction Level Security */ 32 public static final int TLS = 1; 33 34 /** Email */ 35 public static final int EMAIL = 2; 36 37 /** DNSSEC */ 38 public static final int DNSSEC = 3; 39 40 /** IPSEC Control */ 41 public static final int IPSEC = 4; 42 43 /** Any protocol */ 44 public static final int ANY = 255; 45 46 private static Mnemonic protocols = new Mnemonic("KEY protocol", 47 Mnemonic.CASE_UPPER); 48 49 static { 50 protocols.setMaximum(0xFF); 51 protocols.setNumericAllowed(true); 52 53 protocols.add(NONE, "NONE"); 54 protocols.add(TLS, "TLS"); 55 protocols.add(EMAIL, "EMAIL"); 56 protocols.add(DNSSEC, "DNSSEC"); 57 protocols.add(IPSEC, "IPSEC"); 58 protocols.add(ANY, "ANY"); 59 } 60 61 /** 62 * Converts an KEY protocol value into its textual representation 63 */ 64 public static String 65 string(int type) { 66 return protocols.getText(type); 67 } 68 69 /** 70 * Converts a textual representation of a KEY protocol into its 71 * numeric code. Integers in the range 0..255 are also accepted. 72 * @param s The textual representation of the protocol 73 * @return The protocol code, or -1 on error. 74 */ 75 public static int 76 value(String s) { 77 return protocols.getValue(s); 78 } 79 } 80 81 public static class Flags { 82 /** 83 * KEY flags identifiers. 84 */ 85 86 private Flags() {} 87 88 /** KEY cannot be used for confidentiality */ 89 public static final int NOCONF = 0x4000; 90 91 /** KEY cannot be used for authentication */ 92 public static final int NOAUTH = 0x8000; 93 94 /** No key present */ 95 public static final int NOKEY = 0xC000; 96 97 /** Bitmask of the use fields */ 98 public static final int USE_MASK = 0xC000; 99 100 /** Flag 2 (unused) */ 101 public static final int FLAG2 = 0x2000; 102 103 /** Flags extension */ 104 public static final int EXTEND = 0x1000; 105 106 /** Flag 4 (unused) */ 107 public static final int FLAG4 = 0x0800; 108 109 /** Flag 5 (unused) */ 110 public static final int FLAG5 = 0x0400; 111 112 /** Key is owned by a user. */ 113 public static final int USER = 0x0000; 114 115 /** Key is owned by a zone. */ 116 public static final int ZONE = 0x0100; 117 118 /** Key is owned by a host. */ 119 public static final int HOST = 0x0200; 120 121 /** Key owner type 3 (reserved). */ 122 public static final int NTYP3 = 0x0300; 123 124 /** Key owner bitmask. */ 125 public static final int OWNER_MASK = 0x0300; 126 127 /** Flag 8 (unused) */ 128 public static final int FLAG8 = 0x0080; 129 130 /** Flag 9 (unused) */ 131 public static final int FLAG9 = 0x0040; 132 133 /** Flag 10 (unused) */ 134 public static final int FLAG10 = 0x0020; 135 136 /** Flag 11 (unused) */ 137 public static final int FLAG11 = 0x0010; 138 139 /** Signatory value 0 */ 140 public static final int SIG0 = 0; 141 142 /** Signatory value 1 */ 143 public static final int SIG1 = 1; 144 145 /** Signatory value 2 */ 146 public static final int SIG2 = 2; 147 148 /** Signatory value 3 */ 149 public static final int SIG3 = 3; 150 151 /** Signatory value 4 */ 152 public static final int SIG4 = 4; 153 154 /** Signatory value 5 */ 155 public static final int SIG5 = 5; 156 157 /** Signatory value 6 */ 158 public static final int SIG6 = 6; 159 160 /** Signatory value 7 */ 161 public static final int SIG7 = 7; 162 163 /** Signatory value 8 */ 164 public static final int SIG8 = 8; 165 166 /** Signatory value 9 */ 167 public static final int SIG9 = 9; 168 169 /** Signatory value 10 */ 170 public static final int SIG10 = 10; 171 172 /** Signatory value 11 */ 173 public static final int SIG11 = 11; 174 175 /** Signatory value 12 */ 176 public static final int SIG12 = 12; 177 178 /** Signatory value 13 */ 179 public static final int SIG13 = 13; 180 181 /** Signatory value 14 */ 182 public static final int SIG14 = 14; 183 184 /** Signatory value 15 */ 185 public static final int SIG15 = 15; 186 187 private static Mnemonic flags = new Mnemonic("KEY flags", 188 Mnemonic.CASE_UPPER); 189 190 static { 191 flags.setMaximum(0xFFFF); 192 flags.setNumericAllowed(false); 193 194 flags.add(NOCONF, "NOCONF"); 195 flags.add(NOAUTH, "NOAUTH"); 196 flags.add(NOKEY, "NOKEY"); 197 flags.add(FLAG2, "FLAG2"); 198 flags.add(EXTEND, "EXTEND"); 199 flags.add(FLAG4, "FLAG4"); 200 flags.add(FLAG5, "FLAG5"); 201 flags.add(USER, "USER"); 202 flags.add(ZONE, "ZONE"); 203 flags.add(HOST, "HOST"); 204 flags.add(NTYP3, "NTYP3"); 205 flags.add(FLAG8, "FLAG8"); 206 flags.add(FLAG9, "FLAG9"); 207 flags.add(FLAG10, "FLAG10"); 208 flags.add(FLAG11, "FLAG11"); 209 flags.add(SIG0, "SIG0"); 210 flags.add(SIG1, "SIG1"); 211 flags.add(SIG2, "SIG2"); 212 flags.add(SIG3, "SIG3"); 213 flags.add(SIG4, "SIG4"); 214 flags.add(SIG5, "SIG5"); 215 flags.add(SIG6, "SIG6"); 216 flags.add(SIG7, "SIG7"); 217 flags.add(SIG8, "SIG8"); 218 flags.add(SIG9, "SIG9"); 219 flags.add(SIG10, "SIG10"); 220 flags.add(SIG11, "SIG11"); 221 flags.add(SIG12, "SIG12"); 222 flags.add(SIG13, "SIG13"); 223 flags.add(SIG14, "SIG14"); 224 flags.add(SIG15, "SIG15"); 225 } 226 227 /** 228 * Converts a textual representation of KEY flags into its 229 * numeric code. Integers in the range 0..65535 are also accepted. 230 * @param s The textual representation of the protocol 231 * @return The protocol code, or -1 on error. 232 */ 233 public static int 234 value(String s) { 235 int value; 236 try { 237 value = Integer.parseInt(s); 238 if (value >= 0 && value <= 0xFFFF) { 239 return value; 240 } 241 return -1; 242 } catch (NumberFormatException e) { 243 } 244 StringTokenizer st = new StringTokenizer(s, "|"); 245 value = 0; 246 while (st.hasMoreTokens()) { 247 int val = flags.getValue(st.nextToken()); 248 if (val < 0) { 249 return -1; 250 } 251 value |= val; 252 } 253 return value; 254 } 255 } 256 257 /* flags */ 258 /** This key cannot be used for confidentiality (encryption) */ 259 public static final int FLAG_NOCONF = Flags.NOCONF; 260 261 /** This key cannot be used for authentication */ 262 public static final int FLAG_NOAUTH = Flags.NOAUTH; 263 264 /** This key cannot be used for authentication or confidentiality */ 265 public static final int FLAG_NOKEY = Flags.NOKEY; 266 267 /** A zone key */ 268 public static final int OWNER_ZONE = Flags.ZONE; 269 270 /** A host/end entity key */ 271 public static final int OWNER_HOST = Flags.HOST; 272 273 /** A user key */ 274 public static final int OWNER_USER = Flags.USER; 275 276 /* protocols */ 277 /** Key was created for use with transaction level security */ 278 public static final int PROTOCOL_TLS = Protocol.TLS; 279 280 /** Key was created for use with email */ 281 public static final int PROTOCOL_EMAIL = Protocol.EMAIL; 282 283 /** Key was created for use with DNSSEC */ 284 public static final int PROTOCOL_DNSSEC = Protocol.DNSSEC; 285 286 /** Key was created for use with IPSEC */ 287 public static final int PROTOCOL_IPSEC = Protocol.IPSEC; 288 289 /** Key was created for use with any protocol */ 290 public static final int PROTOCOL_ANY = Protocol.ANY; 291 292 KEYRecord() {} 293 294 Record 295 getObject() { 296 return new KEYRecord(); 297 } 298 299 /** 300 * Creates a KEY Record from the given data 301 * @param flags Flags describing the key's properties 302 * @param proto The protocol that the key was created for 303 * @param alg The key's algorithm 304 * @param key Binary data representing the key 305 */ 306 public 307 KEYRecord(Name name, int dclass, long ttl, int flags, int proto, int alg, 308 byte [] key) 309 { 310 super(name, Type.KEY, dclass, ttl, flags, proto, alg, key); 311 } 312 313 /** 314 * Creates a KEY Record from the given data 315 * @param flags Flags describing the key's properties 316 * @param proto The protocol that the key was created for 317 * @param alg The key's algorithm 318 * @param key The key as a PublicKey 319 * @throws DNSSEC.DNSSECException The PublicKey could not be converted into DNS 320 * format. 321 */ 322 public 323 KEYRecord(Name name, int dclass, long ttl, int flags, int proto, int alg, 324 PublicKey key) throws DNSSEC.DNSSECException 325 { 326 super(name, Type.KEY, dclass, ttl, flags, proto, alg, 327 DNSSEC.fromPublicKey(key, alg)); 328 publicKey = key; 329 } 330 331 void 332 rdataFromString(Tokenizer st, Name origin) throws IOException { 333 String flagString = st.getIdentifier(); 334 flags = Flags.value(flagString); 335 if (flags < 0) 336 throw st.exception("Invalid flags: " + flagString); 337 String protoString = st.getIdentifier(); 338 proto = Protocol.value(protoString); 339 if (proto < 0) 340 throw st.exception("Invalid protocol: " + protoString); 341 String algString = st.getIdentifier(); 342 alg = DNSSEC.Algorithm.value(algString); 343 if (alg < 0) 344 throw st.exception("Invalid algorithm: " + algString); 345 /* If this is a null KEY, there's no key data */ 346 if ((flags & Flags.USE_MASK) == Flags.NOKEY) 347 key = null; 348 else 349 key = st.getBase64(); 350 } 351 352 } 353