1 // Copyright (c) 1999-2004 Brian Wellington (bwelling@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
Protocol()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
protocols.add(NONE, "NONE")53 protocols.add(NONE, "NONE");
protocols.add(TLS, "TLS")54 protocols.add(TLS, "TLS");
protocols.add(EMAIL, "EMAIL")55 protocols.add(EMAIL, "EMAIL");
protocols.add(DNSSEC, "DNSSEC")56 protocols.add(DNSSEC, "DNSSEC");
protocols.add(IPSEC, "IPSEC")57 protocols.add(IPSEC, "IPSEC");
protocols.add(ANY, "ANY")58 protocols.add(ANY, "ANY");
59 }
60
61 /**
62 * Converts an KEY protocol value into its textual representation
63 */
64 public static String
string(int type)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
value(String s)76 value(String s) {
77 return protocols.getValue(s);
78 }
79 }
80
81 public static class Flags {
82 /**
83 * KEY flags identifiers.
84 */
85
Flags()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
flags.add(NOCONF, "NOCONF")194 flags.add(NOCONF, "NOCONF");
flags.add(NOAUTH, "NOAUTH")195 flags.add(NOAUTH, "NOAUTH");
flags.add(NOKEY, "NOKEY")196 flags.add(NOKEY, "NOKEY");
flags.add(FLAG2, "FLAG2")197 flags.add(FLAG2, "FLAG2");
flags.add(EXTEND, "EXTEND")198 flags.add(EXTEND, "EXTEND");
flags.add(FLAG4, "FLAG4")199 flags.add(FLAG4, "FLAG4");
flags.add(FLAG5, "FLAG5")200 flags.add(FLAG5, "FLAG5");
flags.add(USER, "USER")201 flags.add(USER, "USER");
flags.add(ZONE, "ZONE")202 flags.add(ZONE, "ZONE");
flags.add(HOST, "HOST")203 flags.add(HOST, "HOST");
flags.add(NTYP3, "NTYP3")204 flags.add(NTYP3, "NTYP3");
flags.add(FLAG8, "FLAG8")205 flags.add(FLAG8, "FLAG8");
flags.add(FLAG9, "FLAG9")206 flags.add(FLAG9, "FLAG9");
flags.add(FLAG10, "FLAG10")207 flags.add(FLAG10, "FLAG10");
flags.add(FLAG11, "FLAG11")208 flags.add(FLAG11, "FLAG11");
flags.add(SIG0, "SIG0")209 flags.add(SIG0, "SIG0");
flags.add(SIG1, "SIG1")210 flags.add(SIG1, "SIG1");
flags.add(SIG2, "SIG2")211 flags.add(SIG2, "SIG2");
flags.add(SIG3, "SIG3")212 flags.add(SIG3, "SIG3");
flags.add(SIG4, "SIG4")213 flags.add(SIG4, "SIG4");
flags.add(SIG5, "SIG5")214 flags.add(SIG5, "SIG5");
flags.add(SIG6, "SIG6")215 flags.add(SIG6, "SIG6");
flags.add(SIG7, "SIG7")216 flags.add(SIG7, "SIG7");
flags.add(SIG8, "SIG8")217 flags.add(SIG8, "SIG8");
flags.add(SIG9, "SIG9")218 flags.add(SIG9, "SIG9");
flags.add(SIG10, "SIG10")219 flags.add(SIG10, "SIG10");
flags.add(SIG11, "SIG11")220 flags.add(SIG11, "SIG11");
flags.add(SIG12, "SIG12")221 flags.add(SIG12, "SIG12");
flags.add(SIG13, "SIG13")222 flags.add(SIG13, "SIG13");
flags.add(SIG14, "SIG14")223 flags.add(SIG14, "SIG14");
flags.add(SIG15, "SIG15")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
value(String s)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
KEYRecord()292 KEYRecord() {}
293
294 Record
getObject()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
KEYRecord(Name name, int dclass, long ttl, int flags, int proto, int alg, byte [] key)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
KEYRecord(Name name, int dclass, long ttl, int flags, int proto, int alg, PublicKey key)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
rdataFromString(Tokenizer st, Name origin)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