22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.security.cert; 27 28 import java.io.ObjectInputStream; 29 import java.io.ObjectOutputStream; 30 import java.io.IOException; 31 import java.util.Collections; 32 import java.util.Date; 33 import java.util.HashMap; 34 import java.util.Map; 35 import javax.security.auth.x500.X500Principal; 36 37 import sun.security.util.ObjectIdentifier; 38 import sun.security.x509.InvalidityDateExtension; 39 40 /** 41 * An exception that indicates an X.509 certificate is revoked. A 42 * <code>CertificateRevokedException</code> contains additional information 43 * about the revoked certificate, such as the date on which the 44 * certificate was revoked and the reason it was revoked. 45 * 46 * @author Sean Mullan 47 * @since 1.7 48 * @see CertPathValidatorException 49 */ 50 public class CertificateRevokedException extends CertificateException { 51 52 private static final long serialVersionUID = 7839996631571608627L; 53 54 /** 55 * @serial the date on which the certificate was revoked 56 */ 57 private Date revocationDate; 58 /** 59 * @serial the revocation reason 60 */ 61 private final CRLReason reason; 62 /** 63 * @serial the <code>X500Principal</code> that represents the name of the 64 * authority that signed the certificate's revocation status information 65 */ 66 private final X500Principal authority; 67 68 private transient Map<String, Extension> extensions; 69 70 /** 71 * Constructs a <code>CertificateRevokedException</code> with 72 * the specified revocation date, reason code, authority name, and map 73 * of extensions. 74 * 75 * @param revocationDate the date on which the certificate was revoked. The 76 * date is copied to protect against subsequent modification. 77 * @param reason the revocation reason 78 * @param extensions a map of X.509 Extensions. Each key is an OID String 79 * that maps to the corresponding Extension. The map is copied to 80 * prevent subsequent modification. 81 * @param authority the <code>X500Principal</code> that represents the name 82 * of the authority that signed the certificate's revocation status 83 * information 84 * @throws NullPointerException if <code>revocationDate</code>, 85 * <code>reason</code>, <code>authority</code>, or 86 * <code>extensions</code> is <code>null</code> 87 */ 88 public CertificateRevokedException(Date revocationDate, CRLReason reason, 89 X500Principal authority, Map<String, Extension> extensions) { 90 if (revocationDate == null || reason == null || authority == null || 91 extensions == null) { 92 throw new NullPointerException(); 93 } 94 this.revocationDate = new Date(revocationDate.getTime()); 95 this.reason = reason; 96 this.authority = authority; 97 this.extensions = new HashMap<String, Extension>(extensions); 98 } 99 100 /** 101 * Returns the date on which the certificate was revoked. A new copy is 102 * returned each time the method is invoked to protect against subsequent 103 * modification. 104 * 105 * @return the revocation date 106 */ 107 public Date getRevocationDate() { 108 return (Date) revocationDate.clone(); 109 } 110 111 /** 112 * Returns the reason the certificate was revoked. 113 * 114 * @return the revocation reason 115 */ 116 public CRLReason getRevocationReason() { 117 return reason; 118 } 119 120 /** 121 * Returns the name of the authority that signed the certificate's 122 * revocation status information. 123 * 124 * @return the <code>X500Principal</code> that represents the name of the 125 * authority that signed the certificate's revocation status information 126 */ 127 public X500Principal getAuthorityName() { 128 return authority; 129 } 130 131 /** 132 * Returns the invalidity date, as specifed in the Invalidity Date 133 * extension of this <code>CertificateRevokedException</code>. The 134 * invalidity date is the date on which it is known or suspected that the 135 * private key was compromised or that the certificate otherwise became 136 * invalid. This implementation calls <code>getExtensions()</code> and 137 * checks the returned map for an entry for the Invalidity Date extension 138 * OID ("2.5.29.24"). If found, it returns the invalidity date in the 139 * extension; otherwise null. A new Date object is returned each time the 140 * method is invoked to protect against subsequent modification. 141 * 142 * @return the invalidity date, or <code>null</code> if not specified 143 */ 144 public Date getInvalidityDate() { 145 Extension ext = getExtensions().get("2.5.29.24"); 146 if (ext == null) { 147 return null; 148 } else { 149 try { 150 Date invalidity = InvalidityDateExtension.toImpl(ext).get("DATE"); 151 return new Date(invalidity.getTime()); 152 } catch (IOException ioe) { 153 return null; 154 } 155 } 156 } 157 158 /** 159 * Returns a map of X.509 extensions containing additional information 160 * about the revoked certificate, such as the Invalidity Date 161 * Extension. Each key is an OID String that maps to the corresponding 162 * Extension. 163 * 164 * @return an unmodifiable map of X.509 extensions, or an empty map 165 * if there are no extensions 166 */ 167 public Map<String, Extension> getExtensions() { 168 return Collections.unmodifiableMap(extensions); 169 } 170 171 @Override 172 public String getMessage() { 173 return "Certificate has been revoked, reason: " 174 + reason + ", revocation date: " + revocationDate 175 + ", authority: " + authority + ", extensions: " + extensions; 176 } 177 178 /** 179 * Serialize this <code>CertificateRevokedException</code> instance. 180 * 181 * @serialData the size of the extensions map (int), followed by all of 182 * the extensions in the map, in no particular order. For each extension, 183 * the following data is emitted: the OID String (Object), the criticality 184 * flag (boolean), the length of the encoded extension value byte array 185 * (int), and the encoded extension value bytes. 186 */ 187 private void writeObject(ObjectOutputStream oos) throws IOException { 188 // Write out the non-transient fields 189 // (revocationDate, reason, authority) 190 oos.defaultWriteObject(); 191 192 // Write out the size (number of mappings) of the extensions map 193 oos.writeInt(extensions.size()); 194 195 // For each extension in the map, the following are emitted (in order): 196 // the OID String (Object), the criticality flag (boolean), the length 197 // of the encoded extension value byte array (int), and the encoded 198 // extension value byte array. The extensions themselves are emitted 199 // in no particular order. 200 for (Map.Entry<String, Extension> entry : extensions.entrySet()) { 201 Extension ext = entry.getValue(); 202 oos.writeObject(ext.getId()); 203 oos.writeBoolean(ext.isCritical()); 204 byte[] extVal = ext.getValue(); 205 oos.writeInt(extVal.length); 206 oos.write(extVal); 207 } 208 } 209 210 /** 211 * Deserialize the <code>CertificateRevokedException</code> instance. 212 */ 213 private void readObject(ObjectInputStream ois) 214 throws IOException, ClassNotFoundException { 215 // Read in the non-transient fields 216 // (revocationDate, reason, authority) 217 ois.defaultReadObject(); 218 219 // Defensively copy the revocation date 220 revocationDate = new Date(revocationDate.getTime()); 221 222 // Read in the size (number of mappings) of the extensions map 223 // and create the extensions map 224 int size = ois.readInt(); 225 if (size == 0) { 226 extensions = Collections.emptyMap(); 227 } else { 228 extensions = new HashMap<String, Extension>(size); 229 } 230 231 // Read in the extensions and put the mappings in the extensions map | 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.security.cert; 27 28 import java.io.ObjectInputStream; 29 import java.io.ObjectOutputStream; 30 import java.io.IOException; 31 import java.util.Collections; 32 import java.util.Date; 33 import java.util.HashMap; 34 import java.util.Map; 35 import javax.security.auth.x500.X500Principal; 36 37 import sun.security.util.ObjectIdentifier; 38 import sun.security.x509.InvalidityDateExtension; 39 40 /** 41 * An exception that indicates an X.509 certificate is revoked. A 42 * {@code CertificateRevokedException} contains additional information 43 * about the revoked certificate, such as the date on which the 44 * certificate was revoked and the reason it was revoked. 45 * 46 * @author Sean Mullan 47 * @since 1.7 48 * @see CertPathValidatorException 49 */ 50 public class CertificateRevokedException extends CertificateException { 51 52 private static final long serialVersionUID = 7839996631571608627L; 53 54 /** 55 * @serial the date on which the certificate was revoked 56 */ 57 private Date revocationDate; 58 /** 59 * @serial the revocation reason 60 */ 61 private final CRLReason reason; 62 /** 63 * @serial the {@code X500Principal} that represents the name of the 64 * authority that signed the certificate's revocation status information 65 */ 66 private final X500Principal authority; 67 68 private transient Map<String, Extension> extensions; 69 70 /** 71 * Constructs a {@code CertificateRevokedException} with 72 * the specified revocation date, reason code, authority name, and map 73 * of extensions. 74 * 75 * @param revocationDate the date on which the certificate was revoked. The 76 * date is copied to protect against subsequent modification. 77 * @param reason the revocation reason 78 * @param extensions a map of X.509 Extensions. Each key is an OID String 79 * that maps to the corresponding Extension. The map is copied to 80 * prevent subsequent modification. 81 * @param authority the {@code X500Principal} that represents the name 82 * of the authority that signed the certificate's revocation status 83 * information 84 * @throws NullPointerException if {@code revocationDate}, 85 * {@code reason}, {@code authority}, or 86 * {@code extensions} is {@code null} 87 */ 88 public CertificateRevokedException(Date revocationDate, CRLReason reason, 89 X500Principal authority, Map<String, Extension> extensions) { 90 if (revocationDate == null || reason == null || authority == null || 91 extensions == null) { 92 throw new NullPointerException(); 93 } 94 this.revocationDate = new Date(revocationDate.getTime()); 95 this.reason = reason; 96 this.authority = authority; 97 this.extensions = new HashMap<String, Extension>(extensions); 98 } 99 100 /** 101 * Returns the date on which the certificate was revoked. A new copy is 102 * returned each time the method is invoked to protect against subsequent 103 * modification. 104 * 105 * @return the revocation date 106 */ 107 public Date getRevocationDate() { 108 return (Date) revocationDate.clone(); 109 } 110 111 /** 112 * Returns the reason the certificate was revoked. 113 * 114 * @return the revocation reason 115 */ 116 public CRLReason getRevocationReason() { 117 return reason; 118 } 119 120 /** 121 * Returns the name of the authority that signed the certificate's 122 * revocation status information. 123 * 124 * @return the {@code X500Principal} that represents the name of the 125 * authority that signed the certificate's revocation status information 126 */ 127 public X500Principal getAuthorityName() { 128 return authority; 129 } 130 131 /** 132 * Returns the invalidity date, as specifed in the Invalidity Date 133 * extension of this {@code CertificateRevokedException}. The 134 * invalidity date is the date on which it is known or suspected that the 135 * private key was compromised or that the certificate otherwise became 136 * invalid. This implementation calls {@code getExtensions()} and 137 * checks the returned map for an entry for the Invalidity Date extension 138 * OID ("2.5.29.24"). If found, it returns the invalidity date in the 139 * extension; otherwise null. A new Date object is returned each time the 140 * method is invoked to protect against subsequent modification. 141 * 142 * @return the invalidity date, or {@code null} if not specified 143 */ 144 public Date getInvalidityDate() { 145 Extension ext = getExtensions().get("2.5.29.24"); 146 if (ext == null) { 147 return null; 148 } else { 149 try { 150 Date invalidity = InvalidityDateExtension.toImpl(ext).get("DATE"); 151 return new Date(invalidity.getTime()); 152 } catch (IOException ioe) { 153 return null; 154 } 155 } 156 } 157 158 /** 159 * Returns a map of X.509 extensions containing additional information 160 * about the revoked certificate, such as the Invalidity Date 161 * Extension. Each key is an OID String that maps to the corresponding 162 * Extension. 163 * 164 * @return an unmodifiable map of X.509 extensions, or an empty map 165 * if there are no extensions 166 */ 167 public Map<String, Extension> getExtensions() { 168 return Collections.unmodifiableMap(extensions); 169 } 170 171 @Override 172 public String getMessage() { 173 return "Certificate has been revoked, reason: " 174 + reason + ", revocation date: " + revocationDate 175 + ", authority: " + authority + ", extensions: " + extensions; 176 } 177 178 /** 179 * Serialize this {@code CertificateRevokedException} instance. 180 * 181 * @serialData the size of the extensions map (int), followed by all of 182 * the extensions in the map, in no particular order. For each extension, 183 * the following data is emitted: the OID String (Object), the criticality 184 * flag (boolean), the length of the encoded extension value byte array 185 * (int), and the encoded extension value bytes. 186 */ 187 private void writeObject(ObjectOutputStream oos) throws IOException { 188 // Write out the non-transient fields 189 // (revocationDate, reason, authority) 190 oos.defaultWriteObject(); 191 192 // Write out the size (number of mappings) of the extensions map 193 oos.writeInt(extensions.size()); 194 195 // For each extension in the map, the following are emitted (in order): 196 // the OID String (Object), the criticality flag (boolean), the length 197 // of the encoded extension value byte array (int), and the encoded 198 // extension value byte array. The extensions themselves are emitted 199 // in no particular order. 200 for (Map.Entry<String, Extension> entry : extensions.entrySet()) { 201 Extension ext = entry.getValue(); 202 oos.writeObject(ext.getId()); 203 oos.writeBoolean(ext.isCritical()); 204 byte[] extVal = ext.getValue(); 205 oos.writeInt(extVal.length); 206 oos.write(extVal); 207 } 208 } 209 210 /** 211 * Deserialize the {@code CertificateRevokedException} instance. 212 */ 213 private void readObject(ObjectInputStream ois) 214 throws IOException, ClassNotFoundException { 215 // Read in the non-transient fields 216 // (revocationDate, reason, authority) 217 ois.defaultReadObject(); 218 219 // Defensively copy the revocation date 220 revocationDate = new Date(revocationDate.getTime()); 221 222 // Read in the size (number of mappings) of the extensions map 223 // and create the extensions map 224 int size = ois.readInt(); 225 if (size == 0) { 226 extensions = Collections.emptyMap(); 227 } else { 228 extensions = new HashMap<String, Extension>(size); 229 } 230 231 // Read in the extensions and put the mappings in the extensions map |