1// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2
3package org.xbill.DNS;
4
5import java.io.*;
6import org.xbill.DNS.utils.*;
7
8/**
9 * Certificate Record  - Stores a certificate associated with a name.  The
10 * certificate might also be associated with a KEYRecord.
11 * @see KEYRecord
12 *
13 * @author Brian Wellington
14 */
15
16public class CERTRecord extends Record {
17
18public static class CertificateType {
19	/** Certificate type identifiers.  See RFC 4398 for more detail. */
20
21	private CertificateType() {}
22
23	/** PKIX (X.509v3) */
24	public static final int PKIX = 1;
25
26	/** Simple Public Key Infrastructure */
27	public static final int SPKI = 2;
28
29	/** Pretty Good Privacy */
30	public static final int PGP = 3;
31
32	/** URL of an X.509 data object */
33	public static final int IPKIX = 4;
34
35	/** URL of an SPKI certificate */
36	public static final int ISPKI = 5;
37
38	/** Fingerprint and URL of an OpenPGP packet */
39	public static final int IPGP = 6;
40
41	/** Attribute Certificate */
42	public static final int ACPKIX = 7;
43
44	/** URL of an Attribute Certificate */
45	public static final int IACPKIX = 8;
46
47	/** Certificate format defined by URI */
48	public static final int URI = 253;
49
50	/** Certificate format defined by OID */
51	public static final int OID = 254;
52
53	private static Mnemonic types = new Mnemonic("Certificate type",
54						     Mnemonic.CASE_UPPER);
55
56	static {
57		types.setMaximum(0xFFFF);
58		types.setNumericAllowed(true);
59
60		types.add(PKIX, "PKIX");
61		types.add(SPKI, "SPKI");
62		types.add(PGP, "PGP");
63		types.add(PKIX, "IPKIX");
64		types.add(SPKI, "ISPKI");
65		types.add(PGP, "IPGP");
66		types.add(PGP, "ACPKIX");
67		types.add(PGP, "IACPKIX");
68		types.add(URI, "URI");
69		types.add(OID, "OID");
70	}
71
72	/**
73	 * Converts a certificate type into its textual representation
74	 */
75	public static String
76	string(int type) {
77		return types.getText(type);
78	}
79
80	/**
81	 * Converts a textual representation of an certificate type into its
82	 * numeric code.  Integers in the range 0..65535 are also accepted.
83	 * @param s The textual representation of the algorithm
84	 * @return The algorithm code, or -1 on error.
85	 */
86	public static int
87	value(String s) {
88		return types.getValue(s);
89	}
90}
91
92/** PKIX (X.509v3) */
93public static final int PKIX = CertificateType.PKIX;
94
95/** Simple Public Key Infrastructure  */
96public static final int SPKI = CertificateType.SPKI;
97
98/** Pretty Good Privacy */
99public static final int PGP = CertificateType.PGP;
100
101/** Certificate format defined by URI */
102public static final int URI = CertificateType.URI;
103
104/** Certificate format defined by IOD */
105public static final int OID = CertificateType.OID;
106
107private static final long serialVersionUID = 4763014646517016835L;
108
109private int certType, keyTag;
110private int alg;
111private byte [] cert;
112
113CERTRecord() {}
114
115Record
116getObject() {
117	return new CERTRecord();
118}
119
120/**
121 * Creates a CERT Record from the given data
122 * @param certType The type of certificate (see constants)
123 * @param keyTag The ID of the associated KEYRecord, if present
124 * @param alg The algorithm of the associated KEYRecord, if present
125 * @param cert Binary data representing the certificate
126 */
127public
128CERTRecord(Name name, int dclass, long ttl, int certType, int keyTag,
129	   int alg, byte []  cert)
130{
131	super(name, Type.CERT, dclass, ttl);
132	this.certType = checkU16("certType", certType);
133	this.keyTag = checkU16("keyTag", keyTag);
134	this.alg = checkU8("alg", alg);
135	this.cert = cert;
136}
137
138void
139rrFromWire(DNSInput in) throws IOException {
140	certType = in.readU16();
141	keyTag = in.readU16();
142	alg = in.readU8();
143	cert = in.readByteArray();
144}
145
146void
147rdataFromString(Tokenizer st, Name origin) throws IOException {
148	String certTypeString = st.getString();
149	certType = CertificateType.value(certTypeString);
150	if (certType < 0)
151		throw st.exception("Invalid certificate type: " +
152				   certTypeString);
153	keyTag = st.getUInt16();
154	String algString = st.getString();
155	alg = DNSSEC.Algorithm.value(algString);
156	if (alg < 0)
157		throw st.exception("Invalid algorithm: " + algString);
158	cert = st.getBase64();
159}
160
161/**
162 * Converts rdata to a String
163 */
164String
165rrToString() {
166	StringBuffer sb = new StringBuffer();
167	sb.append (certType);
168	sb.append (" ");
169	sb.append (keyTag);
170	sb.append (" ");
171	sb.append (alg);
172	if (cert != null) {
173		if (Options.check("multiline")) {
174			sb.append(" (\n");
175			sb.append(base64.formatString(cert, 64, "\t", true));
176		} else {
177			sb.append(" ");
178			sb.append(base64.toString(cert));
179		}
180	}
181	return sb.toString();
182}
183
184/**
185 * Returns the type of certificate
186 */
187public int
188getCertType() {
189	return certType;
190}
191
192/**
193 * Returns the ID of the associated KEYRecord, if present
194 */
195public int
196getKeyTag() {
197	return keyTag;
198}
199
200/**
201 * Returns the algorithm of the associated KEYRecord, if present
202 */
203public int
204getAlgorithm() {
205	return alg;
206}
207
208/**
209 * Returns the binary representation of the certificate
210 */
211public byte []
212getCert() {
213	return cert;
214}
215
216void
217rrToWire(DNSOutput out, Compression c, boolean canonical) {
218	out.writeU16(certType);
219	out.writeU16(keyTag);
220	out.writeU8(alg);
221	out.writeByteArray(cert);
222}
223
224}
225