001: /*
002: * @(#)NetscapeCertTypeExtension.java 1.10 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.security.x509;
029:
030: import java.io.IOException;
031: import java.io.InputStream;
032: import java.io.OutputStream;
033: import java.lang.reflect.Array;
034: import java.util.Vector;
035: import java.util.Enumeration;
036:
037: import sun.security.util.*;
038:
039: /**
040: * Represents Netscape Certificate Type Extension.
041: * The details are defined
042: * <a href=http://www.netscape.com/eng/security/comm4-cert-exts.html>
043: * here </a>.
044: *
045: * <p>This extension, if present, defines both the purpose
046: * (e.g., encipherment, signature, certificate signing) and the application
047: * (e.g., SSL, S/Mime or Object Signing of the key contained in the
048: * certificate. This extension has been superseded by IETF PKIX extensions
049: * but is provided here for compatibility reasons.
050: *
051: * @author Hemma Prafullchandra
052: * @version 1.3
053: * @see Extension
054: * @see CertAttrSet
055: */
056:
057: public class NetscapeCertTypeExtension extends Extension implements
058: CertAttrSet {
059:
060: /**
061: * Identifier for this attribute, to be used with the
062: * get, set, delete methods of Certificate, x509 type.
063: */
064: public static final String IDENT = "x509.info.extensions.NetscapeCertType";
065:
066: /**
067: * Attribute names.
068: */
069: public static final String NAME = "NetscapeCertType";
070: public static final String SSL_CLIENT = "ssl_client";
071: public static final String SSL_SERVER = "ssl_server";
072: public static final String S_MIME = "s_mime";
073: public static final String OBJECT_SIGNING = "object_signing";
074: public static final String SSL_CA = "ssl_ca";
075: public static final String S_MIME_CA = "s_mime_ca";
076: public static final String OBJECT_SIGNING_CA = "object_signing_ca";
077:
078: private static final int CertType_data[] = { 2, 16, 840, 1, 113730,
079: 1, 1 };
080:
081: /**
082: * Object identifier for the Netscape-Cert-Type extension.
083: */
084: public static ObjectIdentifier NetscapeCertType_Id;
085:
086: static {
087: try {
088: NetscapeCertType_Id = new ObjectIdentifier(CertType_data);
089: } catch (IOException ioe) {
090: // should not happen
091: }
092: }
093:
094: private boolean[] bitString;
095:
096: private static class MapEntry {
097: String mName;
098: int mPosition;
099:
100: MapEntry(String name, int position) {
101: mName = name;
102: mPosition = position;
103: }
104: }
105:
106: private static MapEntry[] mMapData = { new MapEntry(SSL_CLIENT, 0),
107: new MapEntry(SSL_SERVER, 1), new MapEntry(S_MIME, 2),
108: new MapEntry(OBJECT_SIGNING, 3),
109: // note that bit 4 is reserved
110: new MapEntry(SSL_CA, 5), new MapEntry(S_MIME_CA, 6),
111: new MapEntry(OBJECT_SIGNING_CA, 7), };
112:
113: private static final Vector mAttributeNames = new Vector();
114: static {
115: for (int i = 0; i < mMapData.length; i++)
116: mAttributeNames.addElement(mMapData[i].mName);
117: }
118:
119: private static int getPosition(String name) throws IOException {
120: for (int i = 0; i < mMapData.length; i++) {
121: if (name.equalsIgnoreCase(mMapData[i].mName))
122: return mMapData[i].mPosition;
123: }
124: throw new IOException("Attribute name [" + name
125: + "] not recognized by CertAttrSet:NetscapeCertType.");
126: }
127:
128: // Encode this extension value
129: private void encodeThis() throws IOException {
130: DerOutputStream os = new DerOutputStream();
131: os.putUnalignedBitString(new BitArray(this .bitString));
132: this .extensionValue = os.toByteArray();
133: }
134:
135: /**
136: * Check if bit is set.
137: *
138: * @param position the position in the bit string to check.
139: */
140: private boolean isSet(int position) {
141: return bitString[position];
142: }
143:
144: /**
145: * Set the bit at the specified position.
146: */
147: private void set(int position, boolean val) {
148: // enlarge bitString if necessary
149: if (position >= bitString.length) {
150: boolean[] tmp = new boolean[position + 1];
151: System.arraycopy(bitString, 0, tmp, 0, bitString.length);
152: bitString = tmp;
153: }
154: bitString[position] = val;
155: }
156:
157: /**
158: * Create a NetscapeCertTypeExtension with the passed bit settings.
159: * The criticality is set to true.
160: *
161: * @param bitString the bits to be set for the extension.
162: */
163: public NetscapeCertTypeExtension(byte[] bitString)
164: throws IOException {
165: this .bitString = new BitArray(bitString.length * 8, bitString)
166: .toBooleanArray();
167: this .extensionId = NetscapeCertType_Id;
168: this .critical = true;
169: encodeThis();
170: }
171:
172: /**
173: * Create a NetscapeCertTypeExtension with the passed bit settings.
174: * The criticality is set to true.
175: *
176: * @param bitString the bits to be set for the extension.
177: */
178: public NetscapeCertTypeExtension(boolean[] bitString)
179: throws IOException {
180: this .bitString = bitString;
181: this .extensionId = NetscapeCertType_Id;
182: this .critical = true;
183: encodeThis();
184: }
185:
186: /**
187: * Create the extension from the passed DER encoded value of the same.
188: *
189: * @param critical true if the extension is to be treated as critical.
190: * @param value Array of DER encoded bytes of the actual value.
191: * @exception IOException on error.
192: */
193: public NetscapeCertTypeExtension(Boolean critical, Object value)
194: throws IOException {
195: this .extensionId = NetscapeCertType_Id;
196: this .critical = critical.booleanValue();
197: int len = Array.getLength(value);
198: byte[] extValue = new byte[len];
199: for (int i = 0; i < len; i++) {
200: extValue[i] = Array.getByte(value, i);
201: }
202: this .extensionValue = extValue;
203: DerValue val = new DerValue(extValue);
204: this .bitString = val.getUnalignedBitString().toBooleanArray();
205: }
206:
207: /**
208: * Create a default key usage.
209: */
210: public NetscapeCertTypeExtension() {
211: extensionId = NetscapeCertType_Id;
212: critical = true;
213: bitString = new boolean[0];
214: }
215:
216: /**
217: * Set the attribute value.
218: */
219: public void set(String name, Object obj) throws IOException {
220: if (!(obj instanceof Boolean))
221: throw new IOException("Attribute must be of type Boolean.");
222:
223: boolean val = ((Boolean) obj).booleanValue();
224: set(getPosition(name), val);
225: encodeThis();
226: }
227:
228: /**
229: * Get the attribute value.
230: */
231: public Object get(String name) throws IOException {
232: return new Boolean(isSet(getPosition(name)));
233: }
234:
235: /**
236: * Delete the attribute value.
237: */
238: public void delete(String name) throws IOException {
239: set(getPosition(name), false);
240: encodeThis();
241: }
242:
243: /**
244: * Returns a printable representation of the NetscapeCertType.
245: */
246: public String toString() {
247: String s = super .toString() + "NetscapeCertType [\n";
248:
249: try {
250: if (isSet(getPosition(SSL_CLIENT)))
251: s += " SSL client\n";
252: if (isSet(getPosition(SSL_SERVER)))
253: s += " SSL server\n";
254: if (isSet(getPosition(S_MIME)))
255: s += " S/MIME\n";
256: if (isSet(getPosition(OBJECT_SIGNING)))
257: s += " Object Signing\n";
258: if (isSet(getPosition(SSL_CA)))
259: s += " SSL CA\n";
260: if (isSet(getPosition(S_MIME_CA)))
261: s += " S/MIME CA\n";
262: if (isSet(getPosition(OBJECT_SIGNING_CA)))
263: s += " Object Signing CA";
264: } catch (Exception e) {
265: }
266:
267: s += "]\n";
268: return (s);
269: }
270:
271: /**
272: * Decode the extension from the InputStream.
273: *
274: * @param in the InputStream to unmarshal the contents from.
275: * @exception IOException on decoding errors.
276: */
277: public void decode(InputStream in) throws IOException {
278: throw new IOException("Method not to be called directly.");
279: }
280:
281: /**
282: * Write the extension to the DerOutputStream.
283: *
284: * @param out the DerOutputStream to write the extension to.
285: * @exception IOException on encoding errors.
286: */
287: public void encode(OutputStream out) throws IOException {
288: DerOutputStream tmp = new DerOutputStream();
289:
290: if (this .extensionValue == null) {
291: this .extensionId = NetscapeCertType_Id;
292: this .critical = true;
293: encodeThis();
294: }
295: super .encode(tmp);
296: out.write(tmp.toByteArray());
297: }
298:
299: /**
300: * Return an enumeration of names of attributes existing within this
301: * attribute.
302: */
303: public Enumeration getElements() {
304: return mAttributeNames.elements();
305: }
306:
307: /**
308: * Return the name of this attribute.
309: */
310: public String getName() {
311: return (NAME);
312: }
313:
314: /**
315: * Get a boolean array representing the bits of this extension,
316: * as it maps to the KeyUsage extension.
317: * @return the bit values of this extension mapped to the bit values
318: * of the KeyUsage extension as an array of booleans.
319: */
320: public boolean[] getKeyUsageMappedBits() {
321: KeyUsageExtension keyUsage = new KeyUsageExtension();
322: Boolean val = new Boolean(true);
323:
324: try {
325: if (isSet(getPosition(SSL_CLIENT))
326: || isSet(getPosition(S_MIME))
327: || isSet(getPosition(OBJECT_SIGNING)))
328: keyUsage.set(keyUsage.DIGITAL_SIGNATURE, val);
329:
330: if (isSet(getPosition(SSL_SERVER)))
331: keyUsage.set(keyUsage.KEY_ENCIPHERMENT, val);
332:
333: if (isSet(getPosition(SSL_CA))
334: || isSet(getPosition(S_MIME_CA))
335: || isSet(getPosition(OBJECT_SIGNING_CA)))
336: keyUsage.set(keyUsage.KEY_CERTSIGN, val);
337: } catch (IOException e) {
338: }
339: return keyUsage.getBits();
340: }
341: }
|