1 /*
2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.security.x509;
27 
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.security.cert.CRLReason;
31 import java.util.Enumeration;
32 
33 import sun.security.util.*;
34 
35 /**
36  * The reasonCode is a non-critical CRL entry extension that identifies
37  * the reason for the certificate revocation.
38  * @author Hemma Prafullchandra
39  * @see java.security.cert.CRLReason
40  * @see Extension
41  * @see CertAttrSet
42  */
43 public class CRLReasonCodeExtension extends Extension
44         implements CertAttrSet<String> {
45 
46     /**
47      * Attribute name
48      */
49     public static final String NAME = "CRLReasonCode";
50     public static final String REASON = "reason";
51 
52     private static CRLReason[] values = CRLReason.values();
53 
54     private int reasonCode = 0;
55 
encodeThis()56     private void encodeThis() throws IOException {
57         if (reasonCode == 0) {
58             this.extensionValue = null;
59             return;
60         }
61         DerOutputStream dos = new DerOutputStream();
62         dos.putEnumerated(reasonCode);
63         this.extensionValue = dos.toByteArray();
64     }
65 
66     /**
67      * Create a CRLReasonCodeExtension with the passed in reason.
68      * Criticality automatically set to false.
69      *
70      * @param reason the enumerated value for the reason code.
71      */
CRLReasonCodeExtension(int reason)72     public CRLReasonCodeExtension(int reason) throws IOException {
73         this(false, reason);
74     }
75 
76     /**
77      * Create a CRLReasonCodeExtension with the passed in reason.
78      *
79      * @param critical true if the extension is to be treated as critical.
80      * @param reason the enumerated value for the reason code.
81      */
CRLReasonCodeExtension(boolean critical, int reason)82     public CRLReasonCodeExtension(boolean critical, int reason)
83     throws IOException {
84         this.extensionId = PKIXExtensions.ReasonCode_Id;
85         this.critical = critical;
86         this.reasonCode = reason;
87         encodeThis();
88     }
89 
90     /**
91      * Create the extension from the passed DER encoded value of the same.
92      *
93      * @param critical true if the extension is to be treated as critical.
94      * @param value an array of DER encoded bytes of the actual value.
95      * @exception ClassCastException if value is not an array of bytes
96      * @exception IOException on error.
97      */
CRLReasonCodeExtension(Boolean critical, Object value)98     public CRLReasonCodeExtension(Boolean critical, Object value)
99     throws IOException {
100         this.extensionId = PKIXExtensions.ReasonCode_Id;
101         this.critical = critical.booleanValue();
102         this.extensionValue = (byte[]) value;
103         DerValue val = new DerValue(this.extensionValue);
104         this.reasonCode = val.getEnumerated();
105     }
106 
107     /**
108      * Set the attribute value.
109      */
set(String name, Object obj)110     public void set(String name, Object obj) throws IOException {
111         if (!(obj instanceof Integer)) {
112             throw new IOException("Attribute must be of type Integer.");
113         }
114         if (name.equalsIgnoreCase(REASON)) {
115             reasonCode = ((Integer)obj).intValue();
116         } else {
117             throw new IOException
118                 ("Name not supported by CRLReasonCodeExtension");
119         }
120         encodeThis();
121     }
122 
123     /**
124      * Get the attribute value.
125      */
get(String name)126     public Integer get(String name) throws IOException {
127         if (name.equalsIgnoreCase(REASON)) {
128             return new Integer(reasonCode);
129         } else {
130             throw new IOException
131                 ("Name not supported by CRLReasonCodeExtension");
132         }
133     }
134 
135     /**
136      * Delete the attribute value.
137      */
delete(String name)138     public void delete(String name) throws IOException {
139         if (name.equalsIgnoreCase(REASON)) {
140             reasonCode = 0;
141         } else {
142             throw new IOException
143                 ("Name not supported by CRLReasonCodeExtension");
144         }
145         encodeThis();
146     }
147 
148     /**
149      * Returns a printable representation of the Reason code.
150      */
toString()151     public String toString() {
152         return super.toString() + "    Reason Code: " + getReasonCode();
153     }
154 
155     /**
156      * Write the extension to the DerOutputStream.
157      *
158      * @param out the DerOutputStream to write the extension to.
159      * @exception IOException on encoding errors.
160      */
encode(OutputStream out)161     public void encode(OutputStream out) throws IOException {
162         DerOutputStream  tmp = new DerOutputStream();
163 
164         if (this.extensionValue == null) {
165             this.extensionId = PKIXExtensions.ReasonCode_Id;
166             this.critical = false;
167             encodeThis();
168         }
169         super.encode(tmp);
170         out.write(tmp.toByteArray());
171     }
172 
173     /**
174      * Return an enumeration of names of attributes existing within this
175      * attribute.
176      */
getElements()177     public Enumeration<String> getElements() {
178         AttributeNameEnumeration elements = new AttributeNameEnumeration();
179         elements.addElement(REASON);
180 
181         return elements.elements();
182     }
183 
184     /**
185      * Return the name of this attribute.
186      */
getName()187     public String getName() {
188         return NAME;
189     }
190 
191     /**
192      * Return the reason as a CRLReason enum.
193      */
getReasonCode()194     public CRLReason getReasonCode() {
195         // if out-of-range, return UNSPECIFIED
196         if (reasonCode > 0 && reasonCode < values.length) {
197             return values[reasonCode];
198         } else {
199             return CRLReason.UNSPECIFIED;
200         }
201     }
202 }
203