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 dk.certifikat.ocsp.client.OcspCertificateResponse;
Jacob Lund Mogensen
committed
import dk.certifikat.ocsp.client.OcspCertificateResponse.OcspCertificateStatus;
import dk.certifikat.ocsp.client.OcspClient;
import dk.certifikat.ocsp.client.OcspRegistry;
import dk.certifikat.ocsp.client.OcspSystemException;
import dk.gov.oiosi.common.OutVariable;
Jacob Lund Mogensen
committed
import dk.gov.oiosi.configuration.CacheConfig;
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.RevocationException;
Jacob Lund Mogensen
committed
import dk.gov.oiosi.security.revocation.RevocationResponse;
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 javax.security.auth.x500.X500Principal;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
/**
* 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 List<X509Certificate> rootcertList = null;
//private X509Certificate rootcert = null;
// Set cache time to one hour
Jacob Lund Mogensen
committed
private static final ICache<X500Principal, RevocationResponse> ocspCache = createCache();
/**
* 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;
rootcertList = new ArrayList<X509Certificate>();
rootcertList.add(defaultRootCertificate);
}
/**
* Creates a new OcspLookup class
*
* @param conf The configuration to use in this lookup
* @param defaultRootCertificateList The root certificate
*/
public OcspLookup(OcspConfig conf, ArrayList<X509Certificate> defaultRootCertificateList) {
configuration = conf;
rootcertList = defaultRootCertificateList;
}
/**
* 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());
}
}
Jacob Lund Mogensen
committed
private static ICache<X500Principal, RevocationResponse> createCache()
{
CacheConfig cacheConfig = ConfigurationHandler.getInstance().getCacheConfig();
Jacob Lund Mogensen
committed
return cacheConfig.getOcspLookupCache() ;
/**
* 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();
}
// The response was not in the cache - we must validete the certificate our self
RevocationResponse response = new RevocationResponse();
// default to false
response.setIsValid(false);
String serverUrl;
try {
log.debug("Setting up OCSP client:");
if (rootcertList == null) {
// get the rootcert(s) from configurationsettings
rootcertList = configuration.getDefaultOcesRootCertificateCollectionFromStore() ;
// .getDefaultOcesRootCertificateFromStore();
}
if(rootcertList.size() <= 0 )
{
// no root certificate is defined
// we can't proceed
throw new RevocationException("No root certificate has been defined.");
}
if (configuration.getServerUrl() == null) {
// Use OCSP server specified in certificate
serverUrl = GetServerUriFromCertificate(certificate);
} else {
// Use OCSP server specified in configuration
serverUrl = configuration.getServerUrl();
}
}
catch (RevocationException e)
{
throw e;
}
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);
}
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
OcspCertificateResponse ocspCertificateResponse = null;
OcspClient client = null;
boolean validationNotFinish = true;
int rootCertificateIndex = 0;
while(validationNotFinish == true && rootCertificateIndex < rootcertList.size())
{
try
{
log.debug("start validation certificate");
client = OcspRegistry.getOcspClient();
client.setResponderUrl(serverUrl);
client.setCaCert(rootcertList.get(rootCertificateIndex));
// Try validation if this is the correct root certificate
/*****/
BigInteger[] serNos = { certificate.getSerialNumber() };
log.debug("Getting certificate status for:" + serNos[0]);
ocspCertificateResponse = client.getCertificateStatus(serNos);
log.trace("Validating certificate...");
client.validateCerts(ocspCertificateResponse);
if (ocspCertificateResponse.isOk())
{
OcspCertificateStatus status = ocspCertificateResponse.getCertificateStatus(serNos[0]);
if ("Good".equals(status.toString()))
{
log.debug("Status of cert " + certificate.getSubjectDN() + " : [" + status + "]");
response.setIsValid(true);
response.setNextUpdate(ocspCertificateResponse.getNextUpdate());
// all okay, do not check other root certificate
validationNotFinish = false;
}
else
{
// The used root certificate is not valid, check the next one
// The rootCertificateIndex is increased at the buttom of this try-catch
log.warn("Certificate validation failed " + serNos[0] + " : [" + status + "]");
}
}
else
{
// The certificateResponse is invalid
log.error("Response returned an error: " + ocspCertificateResponse.getError());
throw new RevocationException("Response returned an error: " + ocspCertificateResponse.getError());
}
}
catch (RevocationException e)
{
throw e;
}
catch (OcspSystemException e)
{
log.debug("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);
}
catch (Exception e)
{
log.error("Error validator certificate : " + e.getMessage(), e);
throw new RevocationException(e);
}
rootCertificateIndex++;
}
log.debug("Validating X509 certificate finished.");
// add the result to cache
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);
}
}