View Javadoc
1   /*
2    * Copyright (c) 1997, 2006, 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.InputStream;
30  import java.io.OutputStream;
31  import java.util.Enumeration;
32  
33  import sun.security.util.*;
34  
35  /**
36   * Represent the CRL Reason Flags.
37   *
38   * <p>This extension, if present, defines the identifies
39   * the reason for the certificate revocation.
40   * <p>The ASN.1 syntax for this is:
41   * <pre>
42   * ReasonFlags ::= BIT STRING {
43   *    unused                  (0),
44   *    keyCompromise           (1),
45   *    cACompromise            (2),
46   *    affiliationChanged      (3),
47   *    superseded              (4),
48   *    cessationOfOperation    (5),
49   *    certificateHold         (6),
50   *    privilegeWithdrawn      (7),
51   *    aACompromise            (8) }
52   * </pre>
53   *
54   * @author Hemma Prafullchandra
55   */
56  public class ReasonFlags {
57  
58      /**
59       * Reasons
60       */
61      public static final String UNUSED = "unused";
62      public static final String KEY_COMPROMISE = "key_compromise";
63      public static final String CA_COMPROMISE = "ca_compromise";
64      public static final String AFFILIATION_CHANGED = "affiliation_changed";
65      public static final String SUPERSEDED = "superseded";
66      public static final String CESSATION_OF_OPERATION
67                                     = "cessation_of_operation";
68      public static final String CERTIFICATE_HOLD = "certificate_hold";
69      public static final String PRIVILEGE_WITHDRAWN = "privilege_withdrawn";
70      public static final String AA_COMPROMISE = "aa_compromise";
71  
72      private final static String[] NAMES = {
73          UNUSED,
74          KEY_COMPROMISE,
75          CA_COMPROMISE,
76          AFFILIATION_CHANGED,
77          SUPERSEDED,
78          CESSATION_OF_OPERATION,
79          CERTIFICATE_HOLD,
80          PRIVILEGE_WITHDRAWN,
81          AA_COMPROMISE,
82      };
83  
84      private static int name2Index(String name) throws IOException {
85          for( int i=0; i<NAMES.length; i++ ) {
86              if( NAMES[i].equalsIgnoreCase(name) ) {
87                  return i;
88              }
89          }
90          throw new IOException("Name not recognized by ReasonFlags");
91      }
92  
93      // Private data members
94      private boolean[] bitString;
95  
96      /**
97       * Check if bit is set.
98       *
99       * @param position the position in the bit string to check.
100      */
101     private boolean isSet(int position) {
102         return bitString[position];
103     }
104 
105     /**
106      * Set the bit at the specified position.
107      */
108     private void set(int position, boolean val) {
109         // enlarge bitString if necessary
110         if (position >= bitString.length) {
111             boolean[] tmp = new boolean[position+1];
112             System.arraycopy(bitString, 0, tmp, 0, bitString.length);
113             bitString = tmp;
114         }
115         bitString[position] = val;
116     }
117 
118     /**
119      * Create a ReasonFlags with the passed bit settings.
120      *
121      * @param reasons the bits to be set for the ReasonFlags.
122      */
123     public ReasonFlags(byte[] reasons) {
124         bitString = new BitArray(reasons.length*8, reasons).toBooleanArray();
125     }
126 
127     /**
128      * Create a ReasonFlags with the passed bit settings.
129      *
130      * @param reasons the bits to be set for the ReasonFlags.
131      */
132     public ReasonFlags(boolean[] reasons) {
133         this.bitString = reasons;
134     }
135 
136     /**
137      * Create a ReasonFlags with the passed bit settings.
138      *
139      * @param reasons the bits to be set for the ReasonFlags.
140      */
141     public ReasonFlags(BitArray reasons) {
142         this.bitString = reasons.toBooleanArray();
143     }
144 
145     /**
146      * Create the object from the passed DER encoded value.
147      *
148      * @param in the DerInputStream to read the ReasonFlags from.
149      * @exception IOException on decoding errors.
150      */
151     public ReasonFlags(DerInputStream in) throws IOException {
152         DerValue derVal = in.getDerValue();
153         this.bitString = derVal.getUnalignedBitString(true).toBooleanArray();
154     }
155 
156     /**
157      * Create the object from the passed DER encoded value.
158      *
159      * @param derVal the DerValue decoded from the stream.
160      * @exception IOException on decoding errors.
161      */
162     public ReasonFlags(DerValue derVal) throws IOException {
163         this.bitString = derVal.getUnalignedBitString(true).toBooleanArray();
164     }
165 
166     /**
167      * Returns the reason flags as a boolean array.
168      */
169     public boolean[] getFlags() {
170         return bitString;
171     }
172 
173     /**
174      * Set the attribute value.
175      */
176     public void set(String name, Object obj) throws IOException {
177         if (!(obj instanceof Boolean)) {
178             throw new IOException("Attribute must be of type Boolean.");
179         }
180         boolean val = ((Boolean)obj).booleanValue();
181         set(name2Index(name), val);
182     }
183 
184     /**
185      * Get the attribute value.
186      */
187     public Object get(String name) throws IOException {
188         return Boolean.valueOf(isSet(name2Index(name)));
189     }
190 
191     /**
192      * Delete the attribute value.
193      */
194     public void delete(String name) throws IOException {
195         set(name, Boolean.FALSE);
196     }
197 
198     /**
199      * Returns a printable representation of the ReasonFlags.
200      */
201     public String toString() {
202         String s = "Reason Flags [\n";
203 
204         try {
205             if (isSet(0)) s += "  Unused\n";
206             if (isSet(1)) s += "  Key Compromise\n";
207             if (isSet(2)) s += "  CA Compromise\n";
208             if (isSet(3)) s += "  Affiliation_Changed\n";
209             if (isSet(4)) s += "  Superseded\n";
210             if (isSet(5)) s += "  Cessation Of Operation\n";
211             if (isSet(6)) s += "  Certificate Hold\n";
212             if (isSet(7)) s += "  Privilege Withdrawn\n";
213             if (isSet(8)) s += "  AA Compromise\n";
214         } catch (ArrayIndexOutOfBoundsException ex) {}
215 
216         s += "]\n";
217 
218         return (s);
219     }
220 
221     /**
222      * Write the extension to the DerOutputStream.
223      *
224      * @param out the DerOutputStream to write the extension to.
225      * @exception IOException on encoding errors.
226      */
227     public void encode(DerOutputStream out) throws IOException {
228         out.putTruncatedUnalignedBitString(new BitArray(this.bitString));
229     }
230 
231     /**
232      * Return an enumeration of names of attributes existing within this
233      * attribute.
234      */
235     public Enumeration<String> getElements () {
236         AttributeNameEnumeration elements = new AttributeNameEnumeration();
237         for( int i=0; i<NAMES.length; i++ ) {
238             elements.addElement(NAMES[i]);
239         }
240         return (elements.elements());
241     }
242 }