001: package org.bouncycastle.jce.provider;
002:
003: import org.bouncycastle.asn1.ASN1InputStream;
004: import org.bouncycastle.asn1.ASN1Sequence;
005: import org.bouncycastle.asn1.DEREnumerated;
006: import org.bouncycastle.asn1.DERObjectIdentifier;
007: import org.bouncycastle.asn1.DEROutputStream;
008: import org.bouncycastle.asn1.util.ASN1Dump;
009: import org.bouncycastle.asn1.x509.CRLReason;
010: import org.bouncycastle.asn1.x509.GeneralName;
011: import org.bouncycastle.asn1.x509.GeneralNames;
012: import org.bouncycastle.asn1.x509.TBSCertList;
013: import org.bouncycastle.asn1.x509.X509Extension;
014: import org.bouncycastle.asn1.x509.X509Extensions;
015: import org.bouncycastle.x509.extension.X509ExtensionUtil;
016:
017: import javax.security.auth.x500.X500Principal;
018: import java.io.ByteArrayOutputStream;
019: import java.io.IOException;
020: import java.math.BigInteger;
021: import java.security.cert.CRLException;
022: import java.security.cert.X509CRLEntry;
023: import java.util.Date;
024: import java.util.Enumeration;
025: import java.util.HashSet;
026: import java.util.Set;
027:
028: /**
029: * The following extensions are listed in RFC 2459 as relevant to CRL Entries
030: *
031: * ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
032: * (critical)
033: */
034: public class X509CRLEntryObject extends X509CRLEntry {
035: private TBSCertList.CRLEntry c;
036:
037: private boolean isIndirect;
038:
039: private X500Principal previousCertificateIssuer;
040: private X500Principal certificateIssuer;
041:
042: public X509CRLEntryObject(TBSCertList.CRLEntry c) {
043: this .c = c;
044: this .certificateIssuer = loadCertificateIssuer();
045: }
046:
047: /**
048: * Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code>
049: * is <code>false</code> {@link #getCertificateIssuer()} will always
050: * return <code>null</code>, <code>previousCertificateIssuer</code> is
051: * ignored. If this <code>isIndirect</code> is specified and this CRLEntry
052: * has no certificate issuer CRL entry extension
053: * <code>previousCertificateIssuer</code> is returned by
054: * {@link #getCertificateIssuer()}.
055: *
056: * @param c
057: * TBSCertList.CRLEntry object.
058: * @param isIndirect
059: * <code>true</code> if the corresponding CRL is a indirect
060: * CRL.
061: * @param previousCertificateIssuer
062: * Certificate issuer of the previous CRLEntry.
063: */
064: public X509CRLEntryObject(TBSCertList.CRLEntry c,
065: boolean isIndirect, X500Principal previousCertificateIssuer) {
066: this .c = c;
067: this .isIndirect = isIndirect;
068: this .previousCertificateIssuer = previousCertificateIssuer;
069: this .certificateIssuer = loadCertificateIssuer();
070: }
071:
072: /**
073: * Will return true if any extensions are present and marked as critical as
074: * we currently dont handle any extensions!
075: */
076: public boolean hasUnsupportedCriticalExtension() {
077: Set extns = getCriticalExtensionOIDs();
078:
079: return extns != null && !extns.isEmpty();
080: }
081:
082: private X500Principal loadCertificateIssuer() {
083: if (!isIndirect) {
084: return null;
085: }
086:
087: byte[] ext = getExtensionValue(X509Extensions.CertificateIssuer
088: .getId());
089: if (ext == null) {
090: return previousCertificateIssuer;
091: }
092:
093: try {
094: GeneralName[] names = GeneralNames.getInstance(
095: X509ExtensionUtil.fromExtensionValue(ext))
096: .getNames();
097: for (int i = 0; i < names.length; i++) {
098: if (names[i].getTagNo() == GeneralName.directoryName) {
099: return new X500Principal(names[i].getName()
100: .getDERObject().getDEREncoded());
101: }
102: }
103: return null;
104: } catch (IOException e) {
105: return null;
106: }
107: }
108:
109: public X500Principal getCertificateIssuer() {
110: return certificateIssuer;
111: }
112:
113: private Set getExtensionOIDs(boolean critical) {
114: X509Extensions extensions = c.getExtensions();
115:
116: if (extensions != null) {
117: Set set = new HashSet();
118: Enumeration e = extensions.oids();
119:
120: while (e.hasMoreElements()) {
121: DERObjectIdentifier oid = (DERObjectIdentifier) e
122: .nextElement();
123: X509Extension ext = extensions.getExtension(oid);
124:
125: if (critical == ext.isCritical()) {
126: set.add(oid.getId());
127: }
128: }
129:
130: return set;
131: }
132:
133: return null;
134: }
135:
136: public Set getCriticalExtensionOIDs() {
137: return getExtensionOIDs(true);
138: }
139:
140: public Set getNonCriticalExtensionOIDs() {
141: return getExtensionOIDs(false);
142: }
143:
144: public byte[] getExtensionValue(String oid) {
145: X509Extensions exts = c.getExtensions();
146:
147: if (exts != null) {
148: X509Extension ext = exts
149: .getExtension(new DERObjectIdentifier(oid));
150:
151: if (ext != null) {
152: try {
153: return ext.getValue().getEncoded();
154: } catch (Exception e) {
155: throw new RuntimeException("error encoding "
156: + e.toString());
157: }
158: }
159: }
160:
161: return null;
162: }
163:
164: public byte[] getEncoded() throws CRLException {
165: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
166: DEROutputStream dOut = new DEROutputStream(bOut);
167:
168: try {
169: dOut.writeObject(c);
170:
171: return bOut.toByteArray();
172: } catch (IOException e) {
173: throw new CRLException(e.toString());
174: }
175: }
176:
177: public BigInteger getSerialNumber() {
178: return c.getUserCertificate().getValue();
179: }
180:
181: public Date getRevocationDate() {
182: return c.getRevocationDate().getDate();
183: }
184:
185: public boolean hasExtensions() {
186: return c.getExtensions() != null;
187: }
188:
189: public String toString() {
190: StringBuffer buf = new StringBuffer();
191: String nl = System.getProperty("line.separator");
192:
193: buf.append(" userCertificate: ").append(
194: this .getSerialNumber()).append(nl);
195: buf.append(" revocationDate: ").append(
196: this .getRevocationDate()).append(nl);
197: buf.append(" certificateIssuer: ").append(
198: this .getCertificateIssuer()).append(nl);
199:
200: X509Extensions extensions = c.getExtensions();
201:
202: if (extensions != null) {
203: Enumeration e = extensions.oids();
204: if (e.hasMoreElements()) {
205: buf.append(" crlEntryExtensions:").append(nl);
206:
207: while (e.hasMoreElements()) {
208: DERObjectIdentifier oid = (DERObjectIdentifier) e
209: .nextElement();
210: X509Extension ext = extensions.getExtension(oid);
211: if (ext.getValue() != null) {
212: byte[] octs = ext.getValue().getOctets();
213: ASN1InputStream dIn = new ASN1InputStream(octs);
214: buf.append(" critical(")
215: .append(ext.isCritical()).append(") ");
216: try {
217: if (oid.equals(X509Extensions.ReasonCode)) {
218: buf
219: .append(
220: new CRLReason(
221: DEREnumerated
222: .getInstance(dIn
223: .readObject())))
224: .append(nl);
225: } else if (oid
226: .equals(X509Extensions.CertificateIssuer)) {
227: buf
228: .append("Certificate issuer: ")
229: .append(
230: new GeneralNames(
231: (ASN1Sequence) dIn
232: .readObject()))
233: .append(nl);
234: } else {
235: buf.append(oid.getId());
236: buf.append(" value = ").append(
237: ASN1Dump.dumpAsString(dIn
238: .readObject())).append(
239: nl);
240: }
241: } catch (Exception ex) {
242: buf.append(oid.getId());
243: buf.append(" value = ").append("*****")
244: .append(nl);
245: }
246: } else {
247: buf.append(nl);
248: }
249: }
250: }
251: }
252:
253: return buf.toString();
254: }
255: }
|