1 /* 2 * Copyright (c) 1997, 2015, 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 name2Index(String name)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 */ isSet(int position)101 private boolean isSet(int position) { 102 return (position < bitString.length) && 103 bitString[position]; 104 } 105 106 /** 107 * Set the bit at the specified position. 108 */ set(int position, boolean val)109 private void set(int position, boolean val) { 110 // enlarge bitString if necessary 111 if (position >= bitString.length) { 112 boolean[] tmp = new boolean[position+1]; 113 System.arraycopy(bitString, 0, tmp, 0, bitString.length); 114 bitString = tmp; 115 } 116 bitString[position] = val; 117 } 118 119 /** 120 * Create a ReasonFlags with the passed bit settings. 121 * 122 * @param reasons the bits to be set for the ReasonFlags. 123 */ ReasonFlags(byte[] reasons)124 public ReasonFlags(byte[] reasons) { 125 bitString = new BitArray(reasons.length*8, reasons).toBooleanArray(); 126 } 127 128 /** 129 * Create a ReasonFlags with the passed bit settings. 130 * 131 * @param reasons the bits to be set for the ReasonFlags. 132 */ ReasonFlags(boolean[] reasons)133 public ReasonFlags(boolean[] reasons) { 134 this.bitString = reasons; 135 } 136 137 /** 138 * Create a ReasonFlags with the passed bit settings. 139 * 140 * @param reasons the bits to be set for the ReasonFlags. 141 */ ReasonFlags(BitArray reasons)142 public ReasonFlags(BitArray reasons) { 143 this.bitString = reasons.toBooleanArray(); 144 } 145 146 /** 147 * Create the object from the passed DER encoded value. 148 * 149 * @param in the DerInputStream to read the ReasonFlags from. 150 * @exception IOException on decoding errors. 151 */ ReasonFlags(DerInputStream in)152 public ReasonFlags(DerInputStream in) throws IOException { 153 DerValue derVal = in.getDerValue(); 154 this.bitString = derVal.getUnalignedBitString(true).toBooleanArray(); 155 } 156 157 /** 158 * Create the object from the passed DER encoded value. 159 * 160 * @param derVal the DerValue decoded from the stream. 161 * @exception IOException on decoding errors. 162 */ ReasonFlags(DerValue derVal)163 public ReasonFlags(DerValue derVal) throws IOException { 164 this.bitString = derVal.getUnalignedBitString(true).toBooleanArray(); 165 } 166 167 /** 168 * Returns the reason flags as a boolean array. 169 */ getFlags()170 public boolean[] getFlags() { 171 return bitString; 172 } 173 174 /** 175 * Set the attribute value. 176 */ set(String name, Object obj)177 public void set(String name, Object obj) throws IOException { 178 if (!(obj instanceof Boolean)) { 179 throw new IOException("Attribute must be of type Boolean."); 180 } 181 boolean val = ((Boolean)obj).booleanValue(); 182 set(name2Index(name), val); 183 } 184 185 /** 186 * Get the attribute value. 187 */ get(String name)188 public Object get(String name) throws IOException { 189 return Boolean.valueOf(isSet(name2Index(name))); 190 } 191 192 /** 193 * Delete the attribute value. 194 */ delete(String name)195 public void delete(String name) throws IOException { 196 set(name, Boolean.FALSE); 197 } 198 199 /** 200 * Returns a printable representation of the ReasonFlags. 201 */ toString()202 public String toString() { 203 StringBuilder sb = new StringBuilder("Reason Flags [\n"); 204 205 if (isSet(0)) { 206 sb.append(" Unused\n"); 207 } 208 if (isSet(1)) { 209 sb.append(" Key Compromise\n"); 210 } 211 if (isSet(2)) { 212 sb.append(" CA Compromise\n"); 213 } 214 if (isSet(3)) { 215 sb.append(" Affiliation_Changed\n"); 216 } 217 if (isSet(4)) { 218 sb.append(" Superseded\n"); 219 } 220 if (isSet(5)) { 221 sb.append(" Cessation Of Operation\n"); 222 } 223 if (isSet(6)) { 224 sb.append(" Certificate Hold\n"); 225 } 226 if (isSet(7)) { 227 sb.append(" Privilege Withdrawn\n"); 228 } 229 if (isSet(8)) { 230 sb.append(" AA Compromise\n"); 231 } 232 sb.append("]\n"); 233 234 return sb.toString(); 235 } 236 237 /** 238 * Write the extension to the DerOutputStream. 239 * 240 * @param out the DerOutputStream to write the extension to. 241 * @exception IOException on encoding errors. 242 */ encode(DerOutputStream out)243 public void encode(DerOutputStream out) throws IOException { 244 out.putTruncatedUnalignedBitString(new BitArray(this.bitString)); 245 } 246 247 /** 248 * Return an enumeration of names of attributes existing within this 249 * attribute. 250 */ getElements()251 public Enumeration<String> getElements () { 252 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 253 for( int i=0; i<NAMES.length; i++ ) { 254 elements.addElement(NAMES[i]); 255 } 256 return (elements.elements()); 257 } 258 } 259