Newer
Older
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this
* file except in compliance with the License. You may obtain
* a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* The Original Code is Java RASP toolkit.
*
* The Initial Developer of the Original Code is Lenio. Portions
* created by Lenio are Copyright (C) 2007 Danish National IT and
* Telecom Agency (http://www.itst.dk). All Rights Reserved.
* Tommy Dejbjerg Pedersen, Lenio
* Martin Bentzen, Accenture
* Jesper Jensen, Avanade
* Ramzi Fadel, Avanade
* Christian Pedersen, Accenture
* Morten Hougesen, Accenture
* Mikkel Hippe Brun, ITST
* Finn Hartmann Jordal, ITST
* Christian Lanng, ITST
package dk.gov.oiosi.security.revocation.ocsp;
import java.net.URISyntaxException;
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.x509.AccessDescription;
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.ocsp.OCSPException;
import dk.certifikat.ocsp.client.OcspCertificateResponse;
import dk.certifikat.ocsp.client.OcspClient;
import dk.certifikat.ocsp.client.OcspRegistry;
import dk.certifikat.ocsp.client.OcspSystemException;
import dk.certifikat.ocsp.client.OcspCertificateResponse.OcspCertificateStatus;
import dk.gov.oiosi.common.OutVariable;
import dk.gov.oiosi.common.cache.ICache;
import dk.gov.oiosi.common.cache.TimedCache;
import dk.gov.oiosi.configuration.ConfigurationException;
import dk.gov.oiosi.configuration.ConfigurationHandler;
import dk.gov.oiosi.security.CertificateHandlingException;
import dk.gov.oiosi.security.revocation.IRevocationLookup;
import dk.gov.oiosi.security.revocation.RevocationResponse;
import dk.gov.oiosi.security.revocation.RevocationException;
/**
* Class for checking certificate revocation status against an OCSP server.
*/
public class OcspLookup implements IRevocationLookup {
/**
* local log.
*/
private Log log = LogFactory.getLog(OcspLookup.class);
/**
* OCSP configuration.
*/
private OcspConfig configuration;
/**
* Root certificate
*/
private X509Certificate rootcert = null;
private static final ICache<X500Principal, RevocationResponse> ocspCache = new TimedCache<X500Principal, RevocationResponse>(60 * 60 * 1000);
/**
* Gets the configuration of the lookup client.
*
* @return OCSP configuration
*/
public OcspConfig getConfiguration() {
return configuration;
}
/**
* Instantiates OcspLookup and loads the OCES default root certificate.
*
*/
configuration = conf;
}
/**
*
* @param conf The configuration to use in this lookup
* @param defaultRootCertificate The root certificate
*/
public OcspLookup(OcspConfig conf, X509Certificate defaultRootCertificate) {
configuration = conf;
rootcert = defaultRootCertificate;
}
/**
* Default constructor. Attempts to load configuration from configuration
* file.
*
* @throws ConfigurationException
*/
public OcspLookup() throws ConfigurationException {
try {
configuration = ConfigurationHandler.getInstance().getOcspConfig();
} catch (URISyntaxException e) {
throw new ConfigurationException(e.getMessage());
}
}
/**
* Checks a certificate status on a ocsp server.
*
* @param certificate
* The certificate to check
* @return The RevocationResponse object that contains the result
* @throws RevocationException
*/
public RevocationResponse checkCertificate(X509Certificate certificate)
throws RevocationException {
OutVariable<RevocationResponse> value = new OutVariable<RevocationResponse>();
if (ocspCache.tryGetValue(certificate.getSubjectX500Principal(), value)) {
return value.getVariable();
}
RevocationResponse response = new RevocationResponse();
OcspCertificateResponse r = null;
OcspClient client = null;
try {
if (rootcert == null) {
// get the rootcert from configurationsettings
rootcert = configuration
.getDefaultOcesRootCertificateFromStore();
}
log.debug("Setting up OCSP client:");
client = OcspRegistry.getOcspClient();
String serverUrl;
if (configuration.getServerUrl() == null) {
// Use OCSP server specified in certificate
serverUrl = GetServerUriFromCertificate(certificate);
} else {
// Use OCSP server specified in configuration
serverUrl = configuration.getServerUrl();
}
client.setResponderUrl(serverUrl);
client.setCaCert(rootcert);
} catch (CertificateHandlingException e) {
log.error("Error handling the certificate" + e.getMessage());
throw new RevocationException(e);
} catch (Exception e) {
log
.error("Error initailizing validator : "
+ e.getMessage(), e);
throw new RevocationException(e);
}
BigInteger[] serNos = { certificate.getSerialNumber() };
try {
log.debug("Getting certificate status for:" + serNos[0]);
r = client.getCertificateStatus(serNos);
client.validateCerts(r);
} catch (OcspSystemException e) {
log
.error("Error validating certificate : "
+ e.getMessage(), e);
throw new RevocationException(e);
} catch (OCSPException e) {
log
.error("Error validating certificate : "
+ e.getMessage(), e);
throw new RevocationException(e);
}
if (r.isOk()) {
OcspCertificateStatus status = r
.getCertificateStatus(serNos[0]);
if ("Good".equals(status.toString())) {
log.debug("Status of cert " + certificate.getSubjectDN()
+ " : [" + status + "]");
response.setIsValid(true);
response.setNextUpdate(r.getNextUpdate());
} else {
log.warn("Certificate validation failed " + serNos[0]
+ " : [" + status + "]");
response.setIsValid(false);
}
} else {
log.error("Response returned an error: " + r.getError());
throw new RevocationException("Response returned an error: "
+ r.getError());
}
log.debug("Validating X509 certificate finished.");
ocspCache.set(certificate.getSubjectX500Principal(), response);
return response;
}
public String GetServerUriFromCertificate(X509Certificate certificate)
throws RevocationException {
try {
byte[] ext = certificate
.getExtensionValue(X509Extensions.AuthorityInfoAccess
.getId());
ASN1InputStream aIn = new ASN1InputStream(ext);
aIn = new ASN1InputStream(((ASN1OctetString) aIn.readObject())
.getOctets());
ASN1Encodable object = (ASN1Encodable) aIn.readObject();
AuthorityInformationAccess auth = AuthorityInformationAccess
.getInstance(object);
AccessDescription[] acc = auth.getAccessDescriptions();
return acc[0].getAccessLocation().toString().substring(3);
} catch (IOException e) {
throw new RevocationException(e);
}
}