001: /*
002: * @(#)CRLReasonCodeExtension.java 1.14 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.Enumeration;
035:
036: import sun.security.util.*;
037:
038: /**
039: * The reasonCode is a non-critical CRL entry extension that identifies
040: * the reason for the certificate revocation. CAs are strongly
041: * encouraged to include reason codes in CRL entries; however, the
042: * reason code CRL entry extension should be absent instead of using the
043: * unspecified (0) reasonCode value.
044: * <p>The ASN.1 syntax for this is:
045: * <pre>
046: * id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 }
047: *
048: * -- reasonCode ::= { CRLReason }
049: *
050: * CRLReason ::= ENUMERATED {
051: * unspecified (0),
052: * keyCompromise (1),
053: * cACompromise (2),
054: * affiliationChanged (3),
055: * superseded (4),
056: * cessationOfOperation (5),
057: * certificateHold (6),
058: * removeFromCRL (8),
059: * privilegeWithdrawn (9),
060: * aACompromise (10) }
061: * </pre>
062: * @author Hemma Prafullchandra
063: * @version 1.7
064: * @see Extension
065: * @see CertAttrSet
066: */
067: public class CRLReasonCodeExtension extends Extension implements
068: CertAttrSet {
069:
070: /**
071: * Attribute name and Reason codes
072: */
073: public static final String NAME = "CRLReasonCode";
074: public static final String REASON = "reason";
075:
076: public static final int UNSPECIFIED = 0;
077: public static final int KEY_COMPROMISE = 1;
078: public static final int CA_COMPROMISE = 2;
079: public static final int AFFLIATION_CHANGED = 3;
080: public static final int SUPERSEDED = 4;
081: public static final int CESSATION_OF_OPERATION = 5;
082: public static final int CERTIFICATE_HOLD = 6;
083: // note 7 missing in syntax
084: public static final int REMOVE_FROM_CRL = 8;
085: public static final int PRIVILEGE_WITHDRAWN = 9;
086: public static final int AA_COMPROMISE = 10;
087:
088: private int reasonCode = 0;
089:
090: private void encodeThis() throws IOException {
091: if (reasonCode == 0) {
092: this .extensionValue = null;
093: return;
094: }
095: DerOutputStream dos = new DerOutputStream();
096: dos.putEnumerated(reasonCode);
097: this .extensionValue = dos.toByteArray();
098: }
099:
100: /**
101: * Create a CRLReasonCodeExtension with the passed in reason.
102: * Criticality automatically set to false.
103: *
104: * @param reason the enumerated value for the reason code.
105: */
106: public CRLReasonCodeExtension(int reason) throws IOException {
107: reasonCode = reason;
108: this .extensionId = PKIXExtensions.ReasonCode_Id;
109: this .critical = false;
110: encodeThis();
111: }
112:
113: /**
114: * Create a CRLReasonCodeExtension with the passed in reason.
115: *
116: * @param critical true if the extension is to be treated as critical.
117: * @param reason the enumerated value for the reason code.
118: */
119: public CRLReasonCodeExtension(boolean critical, int reason)
120: throws IOException {
121: this .extensionId = PKIXExtensions.ReasonCode_Id;
122: this .critical = critical;
123: this .reasonCode = reason;
124: encodeThis();
125: }
126:
127: /**
128: * Create the extension from the passed DER encoded value of the same.
129: *
130: * @param critical true if the extension is to be treated as critical.
131: * @param value Array of DER encoded bytes of the actual value.
132: * @exception IOException on error.
133: */
134: public CRLReasonCodeExtension(Boolean critical, Object value)
135: throws IOException {
136: this .extensionId = PKIXExtensions.ReasonCode_Id;
137: this .critical = critical.booleanValue();
138:
139: if (!(value instanceof byte[]))
140: throw new IOException("Illegal argument type");
141:
142: int len = Array.getLength(value);
143: byte[] extValue = new byte[len];
144: System.arraycopy(value, 0, extValue, 0, len);
145:
146: this .extensionValue = extValue;
147: DerValue val = new DerValue(extValue);
148: this .reasonCode = val.getEnumerated();
149: }
150:
151: /**
152: * Set the attribute value.
153: */
154: public void set(String name, Object obj) throws IOException {
155: if (!(obj instanceof Integer)) {
156: throw new IOException("Attribute must be of type Integer.");
157: }
158: if (name.equalsIgnoreCase(REASON)) {
159: reasonCode = ((Integer) obj).intValue();
160: } else {
161: throw new IOException(
162: "Name not supported by CRLReasonCodeExtension");
163: }
164: encodeThis();
165: }
166:
167: /**
168: * Get the attribute value.
169: */
170: public Object get(String name) throws IOException {
171: if (name.equalsIgnoreCase(REASON)) {
172: return new Integer(reasonCode);
173: } else {
174: throw new IOException(
175: "Name not supported by CRLReasonCodeExtension");
176: }
177: }
178:
179: /**
180: * Delete the attribute value.
181: */
182: public void delete(String name) throws IOException {
183: if (name.equalsIgnoreCase(REASON)) {
184: reasonCode = 0;
185: } else {
186: throw new IOException(
187: "Name not supported by CRLReasonCodeExtension");
188: }
189: encodeThis();
190: }
191:
192: /**
193: * Returns a printable representation of the Reason code.
194: */
195: public String toString() {
196: String s = super .toString() + " Reason Code: ";
197:
198: switch (reasonCode) {
199: case UNSPECIFIED:
200: s += "Unspecified";
201: break;
202: case KEY_COMPROMISE:
203: s += "Key Compromise";
204: break;
205: case CA_COMPROMISE:
206: s += "CA Compromise";
207: break;
208: case AFFLIATION_CHANGED:
209: s += "Affiliation Changed";
210: break;
211: case SUPERSEDED:
212: s += "Superseded";
213: break;
214: case CESSATION_OF_OPERATION:
215: s += "Cessation Of Operation";
216: break;
217: case CERTIFICATE_HOLD:
218: s += "Certificate Hold";
219: break;
220: case REMOVE_FROM_CRL:
221: s += "Remove from CRL";
222: break;
223: case PRIVILEGE_WITHDRAWN:
224: s += "Privilege Withdrawn";
225: break;
226: case AA_COMPROMISE:
227: s += "AA Compromise";
228: break;
229: default:
230: s += "Unrecognized reason code (" + reasonCode + ")";
231: }
232: return (s);
233: }
234:
235: /**
236: * Decode the extension from the InputStream - not just the
237: * value but the OID, criticality and the extension value.
238: *
239: * @param in the InputStream to unmarshal the contents from.
240: * @exception IOException on parsing errors.
241: */
242: public void decode(InputStream in) throws IOException {
243:
244: DerValue val = new DerValue(in);
245: DerInputStream derStrm = val.toDerInputStream();
246:
247: // Object identifier
248: this .extensionId = derStrm.getOID();
249:
250: // If the criticality flag was false, it will not have been encoded.
251: DerValue derVal = derStrm.getDerValue();
252: if (derVal.tag == DerValue.tag_Boolean) {
253: this .critical = derVal.getBoolean();
254: // Extension value (DER encoded)
255: derVal = derStrm.getDerValue();
256: this .extensionValue = derVal.getOctetString();
257: } else {
258: this .critical = false;
259: this .extensionValue = derVal.getOctetString();
260: }
261: val = new DerValue(this .extensionValue);
262: this .reasonCode = val.getEnumerated();
263: if (val.data.available() != 0)
264: throw new IOException(
265: "Illegal encoding of CRLReasonCodeExtension");
266: }
267:
268: /**
269: * Write the extension to the DerOutputStream.
270: *
271: * @param out the DerOutputStream to write the extension to.
272: * @exception IOException on encoding errors.
273: */
274: public void encode(OutputStream out) throws IOException {
275: DerOutputStream tmp = new DerOutputStream();
276:
277: if (this .extensionValue == null) {
278: this .extensionId = PKIXExtensions.ReasonCode_Id;
279: this .critical = false;
280: encodeThis();
281: }
282: super .encode(tmp);
283: out.write(tmp.toByteArray());
284: }
285:
286: /**
287: * Return an enumeration of names of attributes existing within this
288: * attribute.
289: */
290: public Enumeration getElements() {
291: AttributeNameEnumeration elements = new AttributeNameEnumeration();
292: elements.addElement(REASON);
293:
294: return (elements.elements());
295: }
296:
297: /**
298: * Return the name of this attribute.
299: */
300: public String getName() {
301: return (NAME);
302: }
303: }
|