Java tutorial
/* * Copyright (c) 2008-2012, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Eclipse Public License, * tyrex license, freemarker license, dom4j license, mx4j license, * Spice Software License, Common Development and Distribution License * (CDDL), Common Public License (CPL) the licensors of this Program grant * you additional permission to convey the resulting work. */ package mitm.application.djigzo.ws.impl; import java.security.cert.CertPath; import java.security.cert.CertPathBuilderException; import java.security.cert.CertPathBuilderResult; import java.security.cert.CertStoreException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.PKIXCertPathBuilderResult; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.util.List; import mitm.application.djigzo.ws.CertificateStore; import mitm.application.djigzo.ws.CertificateValidatorResult; import mitm.application.djigzo.ws.CertificateValidatorWS; import mitm.application.djigzo.ws.WSExceptionUtils; import mitm.application.djigzo.ws.X509CertificateDTO; import mitm.application.djigzo.ws.X509CertificateDTOBuilder; import mitm.common.hibernate.annotations.StartTransaction; import mitm.common.security.PKISecurityServices; import mitm.common.security.certificate.validator.CertificateValidator; import mitm.common.security.certificate.validator.IsValidForSMIMEEncryption; import mitm.common.security.certificate.validator.IsValidForSMIMESigning; import mitm.common.security.certificate.validator.PKITrustCheckCertificateValidator; import mitm.common.security.certpath.CertificatePathBuilder; import mitm.common.security.certstore.X509CertStoreEntry; import mitm.common.security.certstore.X509CertStoreExt; import mitm.common.util.Check; import mitm.common.util.CollectionUtils; import mitm.common.ws.WebServiceCheckedException; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CertificateValidatorWSImpl implements CertificateValidatorWS { private final static Logger logger = LoggerFactory.getLogger(CertificateValidatorWSImpl.class); /* * Gives access to all the PKI services */ private final PKISecurityServices pKISecurityServices; /* * For building X509 Certificate DTOs */ private final X509CertificateDTOBuilder certificateDTOBuilder; public CertificateValidatorWSImpl(PKISecurityServices pKISecurityServices, X509CertificateDTOBuilder certificateDTOBuilder) { Check.notNull(pKISecurityServices, "pKISecurityServices"); Check.notNull(certificateDTOBuilder, "certificateDTOBuilder"); this.pKISecurityServices = pKISecurityServices; this.certificateDTOBuilder = certificateDTOBuilder; } @Override @StartTransaction public CertificateValidatorResult checkValidityForSigning(CertificateStore store, String thumbprint) throws WebServiceCheckedException { try { X509Certificate certificate = getCertificate(store, thumbprint); CertificateValidatorResult validatorResult = checkValidity(certificate); if (validatorResult.isValid()) { /* * Certificate is trusted etc. now check if it can be used for * S/MIME signatures */ CertificateValidator validator = new IsValidForSMIMESigning(); if (!validator.isValid(certificate)) { validatorResult = new CertificateValidatorResult(false /* not valid */, validatorResult.isTrusted(), validatorResult.isRevoked(), validatorResult.isBlackListed(), validatorResult.isWhiteListed(), "Certificate cannot be used for S/MIME signatures. " + ObjectUtils.toString(validator.getFailureMessage())); } } return validatorResult; } catch (WebServiceCheckedException e) { logger.error("checkValidityForSigning failed.", e); throw new WebServiceCheckedException(WSExceptionUtils.getExceptionMessage(e)); } catch (CertificateException e) { logger.error("checkValidityForSigning failed.", e); throw new WebServiceCheckedException(WSExceptionUtils.getExceptionMessage(e)); } catch (RuntimeException e) { logger.error("checkValidityForSigning failed.", e); throw new WebServiceCheckedException(WSExceptionUtils.getExceptionMessage(e)); } } @Override @StartTransaction public CertificateValidatorResult checkValidityForEncryption(CertificateStore store, String thumbprint) throws WebServiceCheckedException { try { X509Certificate certificate = getCertificate(store, thumbprint); CertificateValidatorResult validatorResult = checkValidity(certificate); if (validatorResult.isValid()) { /* * Certificate is trusted etc. now check if it can be used for * S/MIME encryption */ CertificateValidator validator = new IsValidForSMIMEEncryption(); if (!validator.isValid(certificate)) { validatorResult = new CertificateValidatorResult(false /* not valid */, validatorResult.isTrusted(), validatorResult.isRevoked(), validatorResult.isBlackListed(), validatorResult.isWhiteListed(), "Certificate cannot be used for S/MIME encryption. " + ObjectUtils.toString(validator.getFailureMessage())); } } return validatorResult; } catch (WebServiceCheckedException e) { logger.error("checkValidityForEncryption failed.", e); throw new WebServiceCheckedException(WSExceptionUtils.getExceptionMessage(e)); } catch (CertificateException e) { logger.error("checkValidityForEncryption failed.", e); throw new WebServiceCheckedException(WSExceptionUtils.getExceptionMessage(e)); } catch (RuntimeException e) { logger.error("checkValidityForEncryption failed.", e); throw new WebServiceCheckedException(WSExceptionUtils.getExceptionMessage(e)); } } @Override @StartTransaction public CertificateValidatorResult checkValidity(CertificateStore store, String thumbprint) throws WebServiceCheckedException { try { X509Certificate certificate = getCertificate(store, thumbprint); return checkValidity(certificate); } catch (WebServiceCheckedException e) { logger.error("checkValidity failed.", e); throw new WebServiceCheckedException(WSExceptionUtils.getExceptionMessage(e)); } catch (RuntimeException e) { logger.error("checkValidity failed.", e); throw new WebServiceCheckedException(WSExceptionUtils.getExceptionMessage(e)); } } private X509Certificate getCertificate(CertificateStore store, String thumbprint) throws WebServiceCheckedException { try { X509CertStoreExt certStore = null; switch (store) { case CERTIFICATES: certStore = pKISecurityServices.getKeyAndCertStore(); break; case ROOTS: certStore = pKISecurityServices.getRootStore(); break; default: throw new IllegalArgumentException("Unknown CertificateStore."); } X509CertStoreEntry entry = certStore.getByThumbprint(thumbprint); X509Certificate certificate = null; if (entry != null) { certificate = entry.getCertificate(); } return certificate; } catch (CertStoreException e) { throw new WebServiceCheckedException(e); } } private CertificateValidatorResult checkValidity(X509Certificate certificate) { if (certificate == null) { String message = "Certificate not found."; logger.warn(message); return new CertificateValidatorResult(false /* not valid */, false /* not trusted */, true /* revoked */, false /* not blacklisted */, false /* not whitelisted */, message); } PKITrustCheckCertificateValidator validator = pKISecurityServices .getPKITrustCheckCertificateValidatorFactory().createValidator(null); CertificateValidatorResult result = null; try { validator.isValid(certificate); result = new CertificateValidatorResult(validator.isValid(), validator.isTrusted(), validator.isRevoked(), validator.isBlackListed(), validator.isWhiteListed(), validator.getFailureMessage()); } catch (CertificateException e) { logger.error("Error while validating the certificate.", e); result = new CertificateValidatorResult(false /* not valid */, false /* not trusted */, true /* revoked */, false /* not blacklisted */, false /* not whitelisted */, "Error while validating the certificate: " + ExceptionUtils.getRootCauseMessage(e)); } return result; } @Override @StartTransaction public X509CertificateDTO getIssuerCertificate(CertificateStore store, String thumbprint) throws WebServiceCheckedException { X509Certificate certificate = getCertificate(store, thumbprint); if (certificate == null) { throw new WebServiceCheckedException("Certificate not found"); } X509CertificateDTO issuerDTO = null; try { CertificatePathBuilder pathBuilder = pKISecurityServices.getCertificatePathBuilderFactory() .createCertificatePathBuilder(); CertPathBuilderResult pathBuilderResult = pathBuilder.buildPath(certificate); CertPath certPath = pathBuilderResult.getCertPath(); if (certPath != null) { X509Certificate issuer = null; CertificateStore issuerStore = null; List<? extends Certificate> path = certPath.getCertificates(); if (CollectionUtils.isNotEmpty(path)) { if (CollectionUtils.getSize(path) == 1) { /* * Since there is only one certificate (the certificate itself) we need * to check whether there is a root in the path */ if (pathBuilderResult instanceof PKIXCertPathBuilderResult) { TrustAnchor trustAnchor = ((PKIXCertPathBuilderResult) pathBuilderResult) .getTrustAnchor(); if (trustAnchor != null) { issuer = trustAnchor.getTrustedCert(); issuerStore = CertificateStore.ROOTS; } } } else { issuer = (X509Certificate) path.get(1); issuerStore = CertificateStore.CERTIFICATES; } } if (issuer != null) { issuerDTO = certificateDTOBuilder.buildCertificateDTO(issuer, null); issuerDTO.setCertificateStore(issuerStore); } } } catch (CertPathBuilderException e) { /* * Log on debug level because CertPathBuilderException is for example thrown * when trying to get the issuer of a root for example */ logger.debug("getIssuer failed.", e); } return issuerDTO; } }