X509CRLEntryObject.java revision a198e1ecc615e26a167d0f2dca9fa7e5fc62de10
1package org.bouncycastle.jcajce.provider.asymmetric.x509;
2
3import java.io.IOException;
4import java.math.BigInteger;
5import java.security.cert.CRLException;
6import java.security.cert.X509CRLEntry;
7import java.util.Date;
8import java.util.Enumeration;
9import java.util.HashSet;
10import java.util.Set;
11
12import javax.security.auth.x500.X500Principal;
13
14import org.bouncycastle.asn1.ASN1Encoding;
15import org.bouncycastle.asn1.ASN1Enumerated;
16import org.bouncycastle.asn1.ASN1InputStream;
17import org.bouncycastle.asn1.ASN1ObjectIdentifier;
18import org.bouncycastle.asn1.util.ASN1Dump;
19import org.bouncycastle.asn1.x500.X500Name;
20import org.bouncycastle.asn1.x509.CRLReason;
21import org.bouncycastle.asn1.x509.Extension;
22import org.bouncycastle.asn1.x509.Extensions;
23import org.bouncycastle.asn1.x509.GeneralName;
24import org.bouncycastle.asn1.x509.GeneralNames;
25import org.bouncycastle.asn1.x509.TBSCertList;
26import org.bouncycastle.asn1.x509.X509Extension;
27
28/**
29 * The following extensions are listed in RFC 2459 as relevant to CRL Entries
30 *
31 * ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
32 * (critical)
33 */
34class X509CRLEntryObject extends X509CRLEntry
35{
36    private TBSCertList.CRLEntry c;
37
38    private X500Name certificateIssuer;
39    private int           hashValue;
40    private boolean       isHashValueSet;
41
42    public X509CRLEntryObject(TBSCertList.CRLEntry c)
43    {
44        this.c = c;
45        this.certificateIssuer = null;
46    }
47
48    /**
49     * Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code>
50     * is <code>false</code> {@link #getCertificateIssuer()} will always
51     * return <code>null</code>, <code>previousCertificateIssuer</code> is
52     * ignored. If this <code>isIndirect</code> is specified and this CRLEntry
53     * has no certificate issuer CRL entry extension
54     * <code>previousCertificateIssuer</code> is returned by
55     * {@link #getCertificateIssuer()}.
56     *
57     * @param c
58     *            TBSCertList.CRLEntry object.
59     * @param isIndirect
60     *            <code>true</code> if the corresponding CRL is a indirect
61     *            CRL.
62     * @param previousCertificateIssuer
63     *            Certificate issuer of the previous CRLEntry.
64     */
65    public X509CRLEntryObject(
66        TBSCertList.CRLEntry c,
67        boolean isIndirect,
68        X500Name previousCertificateIssuer)
69    {
70        this.c = c;
71        this.certificateIssuer = loadCertificateIssuer(isIndirect, previousCertificateIssuer);
72    }
73
74    /**
75     * Will return true if any extensions are present and marked as critical as
76     * we currently don't handle any extensions!
77     */
78    public boolean hasUnsupportedCriticalExtension()
79    {
80        Set extns = getCriticalExtensionOIDs();
81
82        return extns != null && !extns.isEmpty();
83    }
84
85    private X500Name loadCertificateIssuer(boolean isIndirect, X500Name previousCertificateIssuer)
86    {
87        if (!isIndirect)
88        {
89            return null;
90        }
91
92        Extension ext = getExtension(Extension.certificateIssuer);
93        if (ext == null)
94        {
95            return previousCertificateIssuer;
96        }
97
98        try
99        {
100            GeneralName[] names = GeneralNames.getInstance(ext.getParsedValue()).getNames();
101            for (int i = 0; i < names.length; i++)
102            {
103                if (names[i].getTagNo() == GeneralName.directoryName)
104                {
105                    return X500Name.getInstance(names[i].getName());
106                }
107            }
108            return null;
109        }
110        catch (Exception e)
111        {
112            return null;
113        }
114    }
115
116    public X500Principal getCertificateIssuer()
117    {
118        if (certificateIssuer == null)
119        {
120            return null;
121        }
122        try
123        {
124            return new X500Principal(certificateIssuer.getEncoded());
125        }
126        catch (IOException e)
127        {
128            return null;
129        }
130    }
131
132    private Set getExtensionOIDs(boolean critical)
133    {
134        Extensions extensions = c.getExtensions();
135
136        if (extensions != null)
137        {
138            Set set = new HashSet();
139            Enumeration e = extensions.oids();
140
141            while (e.hasMoreElements())
142            {
143                ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) e.nextElement();
144                Extension ext = extensions.getExtension(oid);
145
146                if (critical == ext.isCritical())
147                {
148                    set.add(oid.getId());
149                }
150            }
151
152            return set;
153        }
154
155        return null;
156    }
157
158    public Set getCriticalExtensionOIDs()
159    {
160        return getExtensionOIDs(true);
161    }
162
163    public Set getNonCriticalExtensionOIDs()
164    {
165        return getExtensionOIDs(false);
166    }
167
168    private Extension getExtension(ASN1ObjectIdentifier oid)
169    {
170        Extensions exts = c.getExtensions();
171
172        if (exts != null)
173        {
174            return exts.getExtension(oid);
175        }
176
177        return null;
178    }
179
180    public byte[] getExtensionValue(String oid)
181    {
182        Extension ext = getExtension(new ASN1ObjectIdentifier(oid));
183
184        if (ext != null)
185        {
186            try
187            {
188                return ext.getExtnValue().getEncoded();
189            }
190            catch (Exception e)
191            {
192                throw new RuntimeException("error encoding " + e.toString());
193            }
194        }
195
196        return null;
197    }
198
199    /**
200     * Cache the hashCode value - calculating it with the standard method.
201     * @return  calculated hashCode.
202     */
203    public int hashCode()
204    {
205        if (!isHashValueSet)
206        {
207            hashValue = super.hashCode();
208            isHashValueSet = true;
209        }
210
211        return hashValue;
212    }
213
214    public byte[] getEncoded()
215        throws CRLException
216    {
217        try
218        {
219            return c.getEncoded(ASN1Encoding.DER);
220        }
221        catch (IOException e)
222        {
223            throw new CRLException(e.toString());
224        }
225    }
226
227    public BigInteger getSerialNumber()
228    {
229        return c.getUserCertificate().getValue();
230    }
231
232    public Date getRevocationDate()
233    {
234        return c.getRevocationDate().getDate();
235    }
236
237    public boolean hasExtensions()
238    {
239        return c.getExtensions() != null;
240    }
241
242    public String toString()
243    {
244        StringBuffer buf = new StringBuffer();
245        String nl = System.getProperty("line.separator");
246
247        buf.append("      userCertificate: ").append(this.getSerialNumber()).append(nl);
248        buf.append("       revocationDate: ").append(this.getRevocationDate()).append(nl);
249        buf.append("       certificateIssuer: ").append(this.getCertificateIssuer()).append(nl);
250
251        Extensions extensions = c.getExtensions();
252
253        if (extensions != null)
254        {
255            Enumeration e = extensions.oids();
256            if (e.hasMoreElements())
257            {
258                buf.append("   crlEntryExtensions:").append(nl);
259
260                while (e.hasMoreElements())
261                {
262                    ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
263                    Extension ext = extensions.getExtension(oid);
264                    if (ext.getExtnValue() != null)
265                    {
266                        byte[]                  octs = ext.getExtnValue().getOctets();
267                        ASN1InputStream dIn = new ASN1InputStream(octs);
268                        buf.append("                       critical(").append(ext.isCritical()).append(") ");
269                        try
270                        {
271                            if (oid.equals(X509Extension.reasonCode))
272                            {
273                                buf.append(CRLReason.getInstance(ASN1Enumerated.getInstance(dIn.readObject()))).append(nl);
274                            }
275                            else if (oid.equals(X509Extension.certificateIssuer))
276                            {
277                                buf.append("Certificate issuer: ").append(GeneralNames.getInstance(dIn.readObject())).append(nl);
278                            }
279                            else
280                            {
281                                buf.append(oid.getId());
282                                buf.append(" value = ").append(ASN1Dump.dumpAsString(dIn.readObject())).append(nl);
283                            }
284                        }
285                        catch (Exception ex)
286                        {
287                            buf.append(oid.getId());
288                            buf.append(" value = ").append("*****").append(nl);
289                        }
290                    }
291                    else
292                    {
293                        buf.append(nl);
294                    }
295                }
296            }
297        }
298
299        return buf.toString();
300    }
301}
302