blob: 634e5727b504bd3dbbac176f10f8a7def7771694 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.x509;
27
28import java.io.IOException;
29import java.io.OutputStream;
30import java.util.*;
31
32import sun.security.util.*;
33
34/**
35 * Represents Netscape Certificate Type Extension.
36 * The details are defined
37 * <a href=http://www.netscape.com/eng/security/comm4-cert-exts.html>
38 * here </a>.
39 *
40 * <p>This extension, if present, defines both the purpose
41 * (e.g., encipherment, signature, certificate signing) and the application
42 * (e.g., SSL, S/Mime or Object Signing of the key contained in the
43 * certificate. This extension has been superseded by IETF PKIX extensions
44 * but is provided here for compatibility reasons.
45 *
46 * @author Hemma Prafullchandra
47 * @see Extension
48 * @see CertAttrSet
49 */
50
51public class NetscapeCertTypeExtension extends Extension
52implements CertAttrSet<String> {
53
54 /**
55 * Identifier for this attribute, to be used with the
56 * get, set, delete methods of Certificate, x509 type.
57 */
58 public static final String IDENT = "x509.info.extensions.NetscapeCertType";
59
60 /**
61 * Attribute names.
62 */
63 public static final String NAME = "NetscapeCertType";
64 public static final String SSL_CLIENT = "ssl_client";
65 public static final String SSL_SERVER = "ssl_server";
66 public static final String S_MIME = "s_mime";
67 public static final String OBJECT_SIGNING = "object_signing";
68 public static final String SSL_CA = "ssl_ca";
69 public static final String S_MIME_CA = "s_mime_ca";
70 public static final String OBJECT_SIGNING_CA = "object_signing_ca";
71
72 private static final int CertType_data[] = { 2, 16, 840, 1, 113730, 1, 1 };
73
74 /**
75 * Object identifier for the Netscape-Cert-Type extension.
76 */
77 public static ObjectIdentifier NetscapeCertType_Id;
78
79 static {
80 try {
81 NetscapeCertType_Id = new ObjectIdentifier(CertType_data);
82 } catch (IOException ioe) {
83 // should not happen
84 }
85 }
86
87 private boolean[] bitString;
88
89 private static class MapEntry {
90 String mName;
91 int mPosition;
92
93 MapEntry(String name, int position) {
94 mName = name;
95 mPosition = position;
96 }
97 }
98
99 private static MapEntry[] mMapData = {
100 new MapEntry(SSL_CLIENT, 0),
101 new MapEntry(SSL_SERVER, 1),
102 new MapEntry(S_MIME, 2),
103 new MapEntry(OBJECT_SIGNING, 3),
104 // note that bit 4 is reserved
105 new MapEntry(SSL_CA, 5),
106 new MapEntry(S_MIME_CA, 6),
107 new MapEntry(OBJECT_SIGNING_CA, 7),
108 };
109
110 private static final Vector<String> mAttributeNames = new Vector<String>();
111 static {
112 for (MapEntry entry : mMapData) {
113 mAttributeNames.add(entry.mName);
114 }
115 }
116
117 private static int getPosition(String name) throws IOException {
118 for (int i = 0; i < mMapData.length; i++) {
119 if (name.equalsIgnoreCase(mMapData[i].mName))
120 return mMapData[i].mPosition;
121 }
122 throw new IOException("Attribute name [" + name
123 + "] not recognized by CertAttrSet:NetscapeCertType.");
124 }
125
126 // Encode this extension value
127 private void encodeThis() throws IOException {
128 DerOutputStream os = new DerOutputStream();
129 os.putTruncatedUnalignedBitString(new BitArray(this.bitString));
130 this.extensionValue = os.toByteArray();
131 }
132
133 /**
134 * Check if bit is set.
135 *
136 * @param position the position in the bit string to check.
137 */
138 private boolean isSet(int position) {
139 return bitString[position];
140 }
141
142 /**
143 * Set the bit at the specified position.
144 */
145 private void set(int position, boolean val) {
146 // enlarge bitString if necessary
147 if (position >= bitString.length) {
148 boolean[] tmp = new boolean[position+1];
149 System.arraycopy(bitString, 0, tmp, 0, bitString.length);
150 bitString = tmp;
151 }
152 bitString[position] = val;
153 }
154
155 /**
156 * Create a NetscapeCertTypeExtension with the passed bit settings.
157 * The criticality is set to true.
158 *
159 * @param bitString the bits to be set for the extension.
160 */
161 public NetscapeCertTypeExtension(byte[] bitString) throws IOException {
162 this.bitString =
163 new BitArray(bitString.length*8, bitString).toBooleanArray();
164 this.extensionId = NetscapeCertType_Id;
165 this.critical = true;
166 encodeThis();
167 }
168
169 /**
170 * Create a NetscapeCertTypeExtension with the passed bit settings.
171 * The criticality is set to true.
172 *
173 * @param bitString the bits to be set for the extension.
174 */
175 public NetscapeCertTypeExtension(boolean[] bitString) throws IOException {
176 this.bitString = bitString;
177 this.extensionId = NetscapeCertType_Id;
178 this.critical = true;
179 encodeThis();
180 }
181
182 /**
183 * Create the extension from the passed DER encoded value of the same.
184 *
185 * @param critical true if the extension is to be treated as critical.
186 * @param value an array of DER encoded bytes of the actual value.
187 * @exception ClassCastException if value is not an array of bytes
188 * @exception IOException on error.
189 */
190 public NetscapeCertTypeExtension(Boolean critical, Object value)
191 throws IOException {
192 this.extensionId = NetscapeCertType_Id;
193 this.critical = critical.booleanValue();
194 this.extensionValue = (byte[]) value;
195 DerValue val = new DerValue(this.extensionValue);
196 this.bitString = val.getUnalignedBitString().toBooleanArray();
197 }
198
199 /**
200 * Create a default key usage.
201 */
202 public NetscapeCertTypeExtension() {
203 extensionId = NetscapeCertType_Id;
204 critical = true;
205 bitString = new boolean[0];
206 }
207
208 /**
209 * Set the attribute value.
210 */
211 public void set(String name, Object obj) throws IOException {
212 if (!(obj instanceof Boolean))
213 throw new IOException("Attribute must be of type Boolean.");
214
215 boolean val = ((Boolean)obj).booleanValue();
216 set(getPosition(name), val);
217 encodeThis();
218 }
219
220 /**
221 * Get the attribute value.
222 */
223 public Object get(String name) throws IOException {
224 return Boolean.valueOf(isSet(getPosition(name)));
225 }
226
227 /**
228 * Delete the attribute value.
229 */
230 public void delete(String name) throws IOException {
231 set(getPosition(name), false);
232 encodeThis();
233 }
234
235 /**
236 * Returns a printable representation of the NetscapeCertType.
237 */
238 public String toString() {
239 String s = super.toString() + "NetscapeCertType [\n";
240
241 try {
242 if (isSet(getPosition(SSL_CLIENT)))
243 s += " SSL client\n";
244 if (isSet(getPosition(SSL_SERVER)))
245 s += " SSL server\n";
246 if (isSet(getPosition(S_MIME)))
247 s += " S/MIME\n";
248 if (isSet(getPosition(OBJECT_SIGNING)))
249 s += " Object Signing\n";
250 if (isSet(getPosition(SSL_CA)))
251 s += " SSL CA\n";
252 if (isSet(getPosition(S_MIME_CA)))
253 s += " S/MIME CA\n";
254 if (isSet(getPosition(OBJECT_SIGNING_CA)))
255 s += " Object Signing CA" ;
256 } catch (Exception e) { }
257
258 s += "]\n";
259 return (s);
260 }
261
262 /**
263 * Write the extension to the DerOutputStream.
264 *
265 * @param out the DerOutputStream to write the extension to.
266 * @exception IOException on encoding errors.
267 */
268 public void encode(OutputStream out) throws IOException {
269 DerOutputStream tmp = new DerOutputStream();
270
271 if (this.extensionValue == null) {
272 this.extensionId = NetscapeCertType_Id;
273 this.critical = true;
274 encodeThis();
275 }
276 super.encode(tmp);
277 out.write(tmp.toByteArray());
278 }
279
280 /**
281 * Return an enumeration of names of attributes existing within this
282 * attribute.
283 */
284 public Enumeration<String> getElements() {
285 return mAttributeNames.elements();
286 }
287
288 /**
289 * Return the name of this attribute.
290 */
291 public String getName() {
292 return (NAME);
293 }
294
295 /**
296 * Get a boolean array representing the bits of this extension,
297 * as it maps to the KeyUsage extension.
298 * @return the bit values of this extension mapped to the bit values
299 * of the KeyUsage extension as an array of booleans.
300 */
301 public boolean[] getKeyUsageMappedBits() {
302 KeyUsageExtension keyUsage = new KeyUsageExtension();
303 Boolean val = Boolean.TRUE;
304
305 try {
306 if (isSet(getPosition(SSL_CLIENT)) ||
307 isSet(getPosition(S_MIME)) ||
308 isSet(getPosition(OBJECT_SIGNING)))
309 keyUsage.set(keyUsage.DIGITAL_SIGNATURE, val);
310
311 if (isSet(getPosition(SSL_SERVER)))
312 keyUsage.set(keyUsage.KEY_ENCIPHERMENT, val);
313
314 if (isSet(getPosition(SSL_CA)) ||
315 isSet(getPosition(S_MIME_CA)) ||
316 isSet(getPosition(OBJECT_SIGNING_CA)))
317 keyUsage.set(keyUsage.KEY_CERTSIGN, val);
318 } catch (IOException e) { }
319 return keyUsage.getBits();
320 }
321}