package org.bouncycastle.pkix.jcajce;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.Provider;
import java.security.PublicKey;
import java.security.cert.CRL;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLSelector;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.CRLDistPoint;
import org.bouncycastle.asn1.x509.DistributionPoint;
import org.bouncycastle.asn1.x509.DistributionPointName;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.jcajce.PKIXCRLStore;
import org.bouncycastle.jcajce.PKIXExtendedParameters;
import org.bouncycastle.jcajce.util.JcaJceHelper;
import org.bouncycastle.util.CollectionStore;
import org.bouncycastle.util.Iterable;
import org.bouncycastle.util.Selector;
import org.bouncycastle.util.Store;
X.509 Certificate Revocation Checker - still lacks OCSP support and support for delta CRLs.
/**
* X.509 Certificate Revocation Checker - still lacks OCSP support and support for delta CRLs.
*/
public class X509RevocationChecker
extends PKIXCertPathChecker
{
This is the default PKIX validity model. Actually there are two variants of this: The PKIX model and the modified PKIX model. The PKIX model verifies that all involved certificates must have been valid at the current time. The modified PKIX model verifies that all involved certificates were valid at the signing time. Both are indirectly choosen with the PKIXParameters.setDate(Date)
method, so this methods sets the Date when all certificates must have been
valid.
/**
* This is the default PKIX validity model. Actually there are two variants
* of this: The PKIX model and the modified PKIX model. The PKIX model
* verifies that all involved certificates must have been valid at the
* current time. The modified PKIX model verifies that all involved
* certificates were valid at the signing time. Both are indirectly choosen
* with the {@link PKIXParameters#setDate(Date)} method, so this
* methods sets the Date when <em>all</em> certificates must have been
* valid.
*/
public static final int PKIX_VALIDITY_MODEL = 0;
This model uses the following validity model. Each certificate must have been valid at the moment where is was used. That means the end certificate must have been valid at the time the signature was done. The CA certificate which signed the end certificate must have been valid, when the end certificate was signed. The CA (or Root CA) certificate must have been valid, when the CA certificate was signed and so on. So the PKIXParameters.setDate(Date)
method sets the time, when the end certificate must have been valid. It is used e.g.
in the German signature law.
/**
* This model uses the following validity model. Each certificate must have
* been valid at the moment where is was used. That means the end
* certificate must have been valid at the time the signature was done. The
* CA certificate which signed the end certificate must have been valid,
* when the end certificate was signed. The CA (or Root CA) certificate must
* have been valid, when the CA certificate was signed and so on. So the
* {@link PKIXParameters#setDate(Date)} method sets the time, when
* the <em>end certificate</em> must have been valid. It is used e.g.
* in the German signature law.
*/
public static final int CHAIN_VALIDITY_MODEL = 1;
public static class Builder
{
private Set<TrustAnchor> trustAnchors;
private List<CertStore> crlCertStores = new ArrayList<CertStore>();
private List<Store<CRL>> crls = new ArrayList<Store<CRL>>();
private boolean isCheckEEOnly;
private int validityModel = PKIX_VALIDITY_MODEL;
private Provider provider;
private String providerName;
private boolean canSoftFail;
private long failLogMaxTime;
private long failHardMaxTime;
Base constructor.
Params: - trustAnchor – the trust anchor our chain should start with.
/**
* Base constructor.
*
* @param trustAnchor the trust anchor our chain should start with.
*/
public Builder(TrustAnchor trustAnchor)
{
this.trustAnchors = Collections.singleton(trustAnchor);
}
Base constructor.
Params: - trustAnchors – a set of potential trust anchors
/**
* Base constructor.
*
* @param trustAnchors a set of potential trust anchors
*/
public Builder(Set<TrustAnchor> trustAnchors)
{
this.trustAnchors = new HashSet<TrustAnchor>(trustAnchors);
}
Base constructor.
Params: - trustStore – a keystore of potential trust anchors
/**
* Base constructor.
*
* @param trustStore a keystore of potential trust anchors
*/
public Builder(KeyStore trustStore)
throws KeyStoreException
{
this.trustAnchors = new HashSet<TrustAnchor>();
for (Enumeration en = trustStore.aliases(); en.hasMoreElements(); )
{
String alias = (String)en.nextElement();
if (trustStore.isCertificateEntry(alias))
{
trustAnchors.add(new TrustAnchor((X509Certificate)trustStore.getCertificate(alias), null));
}
}
}
Add a collection of CRLs to the checker.
Params: - crls – CRLs to be examined.
Returns: the current builder instance.
/**
* Add a collection of CRLs to the checker.
*
* @param crls CRLs to be examined.
* @return the current builder instance.
*/
public Builder addCrls(CertStore crls)
{
this.crlCertStores.add(crls);
return this;
}
Add a collection of CRLs to the checker.
Params: - crls – CRLs to be examined.
Returns: the current builder instance.
/**
* Add a collection of CRLs to the checker.
*
* @param crls CRLs to be examined.
* @return the current builder instance.
*/
public Builder addCrls(Store<CRL> crls)
{
this.crls.add(crls);
return this;
}
Params: - isTrue – true if only end-entities should be checked, false otherwise.
Returns: the current builder instance.
/**
* @param isTrue true if only end-entities should be checked, false otherwise.
* @return the current builder instance.
*/
public Builder setCheckEndEntityOnly(boolean isTrue)
{
this.isCheckEEOnly = isTrue;
return this;
}
Configure soft failure if CRLs/OCSP not available. If maxTime is greater than zero
it represents the acceptable downtime for any responders or distribution points we
are trying to connect to, with downtime measured from the first failure. Initially
failures will log at Level.WARNING, once maxTime is exceeded any failures will be
logged as Level.SEVERE. Setting maxTime to zero will mean 1 failure will be allowed
before failures are logged as severe.
Params: - isTrue – true soft failure should be enabled, false otherwise.
- maxTime – the time that can pass between the first failure and the most recent.
Returns: the current builder instance.
/**
* Configure soft failure if CRLs/OCSP not available. If maxTime is greater than zero
* it represents the acceptable downtime for any responders or distribution points we
* are trying to connect to, with downtime measured from the first failure. Initially
* failures will log at Level.WARNING, once maxTime is exceeded any failures will be
* logged as Level.SEVERE. Setting maxTime to zero will mean 1 failure will be allowed
* before failures are logged as severe.
*
* @param isTrue true soft failure should be enabled, false otherwise.
* @param maxTime the time that can pass between the first failure and the most recent.
* @return the current builder instance.
*/
public Builder setSoftFail(boolean isTrue, long maxTime)
{
this.canSoftFail = isTrue;
this.failLogMaxTime = maxTime;
this.failHardMaxTime = -1;
return this;
}
Configure soft failure with a hard limit if CRLs/OCSP not available. If maxTime is
greater than zero it represents the acceptable downtime for any responders or
distribution points we are trying to connect to, with downtime measured from the
first failure. Initially failures will log at Level.WARNING, once 75% of maxTime is exceeded
any failures will be logged as Level.SEVERE. At maxTime any failures will be treated as hard,
setting maxTime to zero will mean 1 failure will be allowed.
Params: - isTrue – true soft failure should be enabled, false otherwise.
- maxTime – the time that can pass between the first failure and the most recent.
Returns: the current builder instance.
/**
* Configure soft failure with a hard limit if CRLs/OCSP not available. If maxTime is
* greater than zero it represents the acceptable downtime for any responders or
* distribution points we are trying to connect to, with downtime measured from the
* first failure. Initially failures will log at Level.WARNING, once 75% of maxTime is exceeded
* any failures will be logged as Level.SEVERE. At maxTime any failures will be treated as hard,
* setting maxTime to zero will mean 1 failure will be allowed.
*
* @param isTrue true soft failure should be enabled, false otherwise.
* @param maxTime the time that can pass between the first failure and the most recent.
* @return the current builder instance.
*/
public Builder setSoftFailHardLimit(boolean isTrue, long maxTime)
{
this.canSoftFail = isTrue;
this.failLogMaxTime = (maxTime * 3) / 4;
this.failHardMaxTime = maxTime;
return this;
}
Configure to use the installed provider with name ProviderName.
Params: - provider – provider to use.
Returns: the current builder instance.
/**
* Configure to use the installed provider with name ProviderName.
*
* @param provider provider to use.
* @return the current builder instance.
*/
public Builder usingProvider(Provider provider)
{
this.provider = provider;
return this;
}
Configure to use the installed provider with name ProviderName.
Params: - providerName – name of the installed provider to use.
Returns: the current builder instance.
/**
* Configure to use the installed provider with name ProviderName.
*
* @param providerName name of the installed provider to use.
* @return the current builder instance.
*/
public Builder usingProvider(String providerName)
{
this.providerName = providerName;
return this;
}
Build a revocation checker conforming to the current builder.
Returns: a new X509RevocationChecker.
/**
* Build a revocation checker conforming to the current builder.
*
* @return a new X509RevocationChecker.
*/
public X509RevocationChecker build()
{
return new X509RevocationChecker(this);
}
}
private static Logger LOG = Logger.getLogger(X509RevocationChecker.class.getName());
private static final Map<GeneralName, WeakReference<X509CRL>> crlCache = Collections.synchronizedMap(
new WeakHashMap<GeneralName, WeakReference<X509CRL>>());
private final Map<X500Principal, Long> failures = new HashMap<X500Principal, Long>();
private final Set<TrustAnchor> trustAnchors;
private final boolean isCheckEEOnly;
private final List<Store<CRL>> crls;
private final List<CertStore> crlCertStores;
private final PKIXJcaJceHelper helper;
private final boolean canSoftFail;
private final long failLogMaxTime;
private final long failHardMaxTime;
private X500Principal workingIssuerName;
private PublicKey workingPublicKey;
private X509Certificate signingCert;
private X509RevocationChecker(Builder bldr)
{
this.crls = new ArrayList<Store<CRL>>(bldr.crls);
this.crlCertStores = new ArrayList<CertStore>(bldr.crlCertStores);
this.isCheckEEOnly = bldr.isCheckEEOnly;
this.trustAnchors = bldr.trustAnchors;
this.canSoftFail = bldr.canSoftFail;
this.failLogMaxTime = bldr.failLogMaxTime;
this.failHardMaxTime = bldr.failHardMaxTime;
if (bldr.provider != null)
{
this.helper = new PKIXProviderJcaJceHelper(bldr.provider);
}
else if (bldr.providerName != null)
{
helper = new PKIXNamedJcaJceHelper(bldr.providerName);
}
else
{
helper = new PKIXDefaultJcaJceHelper();
}
}
public void init(boolean forward)
throws CertPathValidatorException
{
if (forward)
{
throw new IllegalArgumentException("forward processing not supported");
}
this.workingIssuerName = null;
}
public boolean isForwardCheckingSupported()
{
return false;
}
public Set<String> getSupportedExtensions()
{
return null;
}
public void check(Certificate certificate, Collection<String> collection)
throws CertPathValidatorException
{
X509Certificate cert = (X509Certificate)certificate;
if (isCheckEEOnly && cert.getBasicConstraints() != -1)
{
this.workingIssuerName = cert.getSubjectX500Principal();
this.workingPublicKey = cert.getPublicKey();
this.signingCert = cert;
return;
}
TrustAnchor trustAnchor = null;
if (workingIssuerName == null)
{
this.workingIssuerName = cert.getIssuerX500Principal();
for (Iterator it = trustAnchors.iterator(); it.hasNext(); )
{
TrustAnchor anchor = (TrustAnchor)it.next();
if (workingIssuerName.equals(anchor.getCA())
|| workingIssuerName.equals(anchor.getTrustedCert().getSubjectX500Principal()))
{
trustAnchor = anchor;
}
}
if (trustAnchor == null)
{
throw new CertPathValidatorException("no trust anchor found for " + workingIssuerName);
}
this.signingCert = trustAnchor.getTrustedCert();
this.workingPublicKey = signingCert.getPublicKey();
}
PKIXParameters baseParams;
List<X500Principal> issuerList = new ArrayList<X500Principal>();
try
{
baseParams = new PKIXParameters(trustAnchors);
baseParams.setRevocationEnabled(false);
baseParams.setDate(new Date());
for (int i = 0; i != crlCertStores.size(); i++)
{
if (LOG.isLoggable(Level.INFO))
{
addIssuers(issuerList, crlCertStores.get(i));
}
baseParams.addCertStore(crlCertStores.get(i));
}
}
catch (GeneralSecurityException e)
{
throw new RuntimeException("error setting up baseParams: " + e.getMessage());
}
PKIXExtendedParameters.Builder pkixParamsBldr = new PKIXExtendedParameters.Builder(baseParams);
for (int i = 0; i != crls.size(); i++)
{
if (LOG.isLoggable(Level.INFO))
{
addIssuers(issuerList, crls.get(i));
}
pkixParamsBldr.addCRLStore(new LocalCRLStore(crls.get(i)));
}
if (issuerList.isEmpty())
{
LOG.log(Level.INFO, "configured with 0 pre-loaded CRLs");
}
else
{
if (LOG.isLoggable(Level.FINE))
{
for (int i = 0; i != issuerList.size(); i++)
{
LOG.log(Level.FINE, "configuring with CRL for issuer \"" + issuerList.get(i) + "\"");
}
}
else
{
LOG.log(Level.INFO, "configured with " + issuerList.size() + " pre-loaded CRLs");
}
}
try
{
checkCRLs(pkixParamsBldr.build(), cert, baseParams.getDate(), signingCert, workingPublicKey, new ArrayList(), helper);
}
catch (AnnotatedException e)
{
throw new CertPathValidatorException(e.getMessage(), e.getCause());
}
catch (CRLNotFoundException e)
{
if (cert.getExtensionValue(Extension.cRLDistributionPoints.getId()) != null)
{
CRL crl = null;
try
{
crl = downloadCRLs(cert.getIssuerX500Principal(), baseParams.getDate(), RevocationUtilities.getExtensionValue(cert, Extension.cRLDistributionPoints), helper);
}
catch(AnnotatedException e1)
{
throw new CertPathValidatorException(e.getMessage(), e.getCause());
}
if (crl != null)
{
try
{
pkixParamsBldr.addCRLStore(new LocalCRLStore(
new CollectionStore<CRL>(Collections.singleton(crl))));
checkCRLs(pkixParamsBldr.build(), cert, new Date(), signingCert, workingPublicKey, new ArrayList(), helper);
}
catch(AnnotatedException e1)
{
throw new CertPathValidatorException(e.getMessage(), e.getCause());
}
}
else
{
if (canSoftFail)
{
X500Principal issuer = cert.getIssuerX500Principal();
Long initial = failures.get(issuer);
if (initial != null)
{
long period = System.currentTimeMillis() - initial.longValue();
if (failHardMaxTime != -1 && failHardMaxTime < period)
{
throw e;
}
if (period < failLogMaxTime)
{
LOG.log(Level.WARNING, "soft failing for issuer: \"" + issuer + "\"");
}
else
{
LOG.log(Level.SEVERE, "soft failing for issuer: \"" + issuer + "\"");
}
}
else
{
failures.put(issuer, System.currentTimeMillis());
}
}
else
{
throw e;
}
}
}
else
{
throw e;
}
}
this.signingCert = cert;
this.workingPublicKey = cert.getPublicKey();
this.workingIssuerName = cert.getSubjectX500Principal();
}
private void addIssuers(final List<X500Principal> issuerList, CertStore certStore)
throws CertStoreException
{
certStore.getCRLs(new X509CRLSelector()
{
public boolean match(CRL crl)
{
if (!(crl instanceof X509CRL))
{
return false;
}
issuerList.add(((X509CRL)crl).getIssuerX500Principal());
return false;
}
});
}
private void addIssuers(final List<X500Principal> issuerList, Store<CRL> certStore)
{
certStore.getMatches(new Selector<CRL>()
{
public boolean match(CRL crl)
{
if (!(crl instanceof X509CRL))
{
return false;
}
issuerList.add(((X509CRL)crl).getIssuerX500Principal());
return false;
}
public Object clone()
{
return this;
}
});
}
private CRL downloadCRLs(X500Principal issuer, Date currentDate, ASN1Primitive crlDpPrimitive, JcaJceHelper helper)
{
CRLDistPoint crlDp = CRLDistPoint.getInstance(crlDpPrimitive);
DistributionPoint[] points = crlDp.getDistributionPoints();
for (int i = 0; i != points.length; i++)
{
DistributionPoint dp = points[i];
DistributionPointName dpn = dp.getDistributionPoint();
if (dpn.getType() == DistributionPointName.FULL_NAME)
{
GeneralName[] names = GeneralNames.getInstance(dpn.getName()).getNames();
for (int n = 0; n != names.length; n++)
{
GeneralName name = names[n];
if (name.getTagNo() == GeneralName.uniformResourceIdentifier)
{
X509CRL crl;
WeakReference<X509CRL> crlRef = crlCache.get(name);
if (crlRef != null)
{
crl = crlRef.get();
if (crl != null
&& !currentDate.before(crl.getThisUpdate())
&& !currentDate.after(crl.getNextUpdate()))
{
return crl;
}
crlCache.remove(name); // delete expired/out-of-range entry
}
URL url = null;
try
{
url = new URL(name.getName().toString());
CertificateFactory certFact = helper.createCertificateFactory("X.509");
InputStream urlStream = url.openStream();
crl = (X509CRL)certFact.generateCRL(new BufferedInputStream(urlStream));
urlStream.close();
LOG.log(Level.INFO, "downloaded CRL from CrlDP " + url + " for issuer \"" + issuer + "\"");
crlCache.put(name, new WeakReference<X509CRL>(crl));
return crl;
}
catch (Exception e)
{
if (LOG.isLoggable(Level.FINE))
{
LOG.log(Level.FINE, "CrlDP " + url + " ignored: " + e.getMessage(), e);
}
else
{
LOG.log(Level.INFO, "CrlDP " + url + " ignored: " + e.getMessage());
}
}
}
}
}
}
return null;
}
protected static final String[] crlReasons = new String[]{
"unspecified",
"keyCompromise",
"cACompromise",
"affiliationChanged",
"superseded",
"cessationOfOperation",
"certificateHold",
"unknown",
"removeFromCRL",
"privilegeWithdrawn",
"aACompromise"};
static List<PKIXCRLStore> getAdditionalStoresFromCRLDistributionPoint(CRLDistPoint crldp, Map<GeneralName, PKIXCRLStore> namedCRLStoreMap)
throws AnnotatedException
{
if (crldp != null)
{
DistributionPoint dps[] = null;
try
{
dps = crldp.getDistributionPoints();
}
catch (Exception e)
{
throw new AnnotatedException(
"could not read distribution points could not be read", e);
}
List<PKIXCRLStore> stores = new ArrayList<PKIXCRLStore>();
for (int i = 0; i < dps.length; i++)
{
DistributionPointName dpn = dps[i].getDistributionPoint();
// look for URIs in fullName
if (dpn != null)
{
if (dpn.getType() == DistributionPointName.FULL_NAME)
{
GeneralName[] genNames = GeneralNames.getInstance(
dpn.getName()).getNames();
for (int j = 0; j < genNames.length; j++)
{
PKIXCRLStore store = namedCRLStoreMap.get(genNames[j]);
if (store != null)
{
stores.add(store);
}
}
}
}
}
return stores;
}
else
{
return Collections.EMPTY_LIST;
}
}
Checks a certificate if it is revoked.
Params: - paramsPKIX – PKIX parameters.
- cert – Certificate to check if it is revoked.
- validDate – The date when the certificate revocation status should be
checked.
- sign – The issuer certificate of the certificate
cert
. - workingPublicKey – The public key of the issuer certificate
sign
. - certPathCerts – The certificates of the certification path.
Throws: - AnnotatedException – if the certificate is revoked or the status cannot be checked
or some error occurs.
/**
* Checks a certificate if it is revoked.
*
* @param paramsPKIX PKIX parameters.
* @param cert Certificate to check if it is revoked.
* @param validDate The date when the certificate revocation status should be
* checked.
* @param sign The issuer certificate of the certificate <code>cert</code>.
* @param workingPublicKey The public key of the issuer certificate <code>sign</code>.
* @param certPathCerts The certificates of the certification path.
* @throws AnnotatedException if the certificate is revoked or the status cannot be checked
* or some error occurs.
*/
protected void checkCRLs(
PKIXExtendedParameters paramsPKIX,
X509Certificate cert,
Date validDate,
X509Certificate sign,
PublicKey workingPublicKey,
List certPathCerts,
PKIXJcaJceHelper helper)
throws AnnotatedException, CertPathValidatorException
{
AnnotatedException lastException = null;
CRLDistPoint crldp = null;
try
{
crldp = CRLDistPoint.getInstance(RevocationUtilities.getExtensionValue(cert, Extension.cRLDistributionPoints));
}
catch (Exception e)
{
throw new AnnotatedException("cannot read CRL distribution point extension", e);
}
PKIXExtendedParameters.Builder paramsBldr = new PKIXExtendedParameters.Builder(paramsPKIX);
try
{
List extras = getAdditionalStoresFromCRLDistributionPoint(crldp, paramsPKIX.getNamedCRLStoreMap());
for (Iterator it = extras.iterator(); it.hasNext(); )
{
paramsBldr.addCRLStore((PKIXCRLStore)it.next());
}
}
catch (AnnotatedException e)
{
throw new AnnotatedException(
"no additional CRL locations could be decoded from CRL distribution point extension", e);
}
CertStatus certStatus = new CertStatus();
ReasonsMask reasonsMask = new ReasonsMask();
PKIXExtendedParameters finalParams = paramsBldr.build();
boolean validCrlFound = false;
// for each distribution point
if (crldp != null)
{
DistributionPoint dps[] = null;
try
{
dps = crldp.getDistributionPoints();
}
catch (Exception e)
{
throw new AnnotatedException("cannot read distribution points", e);
}
if (dps != null)
{
for (int i = 0; i < dps.length && certStatus.getCertStatus() == CertStatus.UNREVOKED && !reasonsMask.isAllReasons(); i++)
{
try
{
RFC3280CertPathUtilities.checkCRL(dps[i], finalParams, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask, certPathCerts, helper);
validCrlFound = true;
}
catch (AnnotatedException e)
{
lastException = e;
}
}
}
}
/*
* If the revocation status has not been determined, repeat the process
* above with any available CRLs not specified in a distribution point
* but issued by the certificate issuer.
*/
if (certStatus.getCertStatus() == CertStatus.UNREVOKED && !reasonsMask.isAllReasons())
{
try
{
/*
* assume a DP with both the reasons and the cRLIssuer fields
* omitted and a distribution point name of the certificate
* issuer.
*/
X500Principal issuer = cert.getIssuerX500Principal();
DistributionPoint dp = new DistributionPoint(new DistributionPointName(0, new GeneralNames(
new GeneralName(GeneralName.directoryName, X500Name.getInstance(issuer.getEncoded())))), null, null);
PKIXExtendedParameters paramsPKIXClone = (PKIXExtendedParameters)paramsPKIX.clone();
RFC3280CertPathUtilities.checkCRL(dp, paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask,
certPathCerts, helper);
validCrlFound = true;
}
catch (AnnotatedException e)
{
lastException = e;
}
}
if (!validCrlFound)
{
if (lastException instanceof AnnotatedException)
{
throw new CRLNotFoundException("no valid CRL found", lastException);
}
throw new CRLNotFoundException("no valid CRL found");
}
if (certStatus.getCertStatus() != CertStatus.UNREVOKED)
{
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String message = "certificate [issuer=\"" + cert.getIssuerX500Principal() + "\",serialNumber="
+ cert.getSerialNumber() + ",subject=\"" + cert.getSubjectX500Principal() + "\"] revoked after " + df.format(certStatus.getRevocationDate());
message += ", reason: " + crlReasons[certStatus.getCertStatus()];
throw new AnnotatedException(message);
}
if (!reasonsMask.isAllReasons() && certStatus.getCertStatus() == CertStatus.UNREVOKED)
{
certStatus.setCertStatus(CertStatus.UNDETERMINED);
}
if (certStatus.getCertStatus() == CertStatus.UNDETERMINED)
{
throw new AnnotatedException("certificate status could not be determined");
}
}
public Object clone()
{
return this;
}
private class LocalCRLStore<T extends CRL>
implements PKIXCRLStore, Iterable<CRL>
{
private Collection<CRL> _local;
Basic constructor.
Params: - collection – - initial contents for the store, this is copied.
/**
* Basic constructor.
*
* @param collection - initial contents for the store, this is copied.
*/
public LocalCRLStore(
Store<CRL> collection)
{
_local = new ArrayList<CRL>(collection.getMatches(null));
}
Return the matches in the collection for the passed in selector.
Params: - selector – the selector to match against.
Returns: a possibly empty collection of matching objects.
/**
* Return the matches in the collection for the passed in selector.
*
* @param selector the selector to match against.
* @return a possibly empty collection of matching objects.
*/
public Collection getMatches(Selector selector)
{
if (selector == null)
{
return new ArrayList<CRL>(_local);
}
else
{
List<CRL> col = new ArrayList<CRL>();
Iterator<CRL> iter = _local.iterator();
while (iter.hasNext())
{
CRL obj = iter.next();
if (selector.match(obj))
{
col.add(obj);
}
}
return col;
}
}
public Iterator<CRL> iterator()
{
return getMatches(null).iterator();
}
}
}