CRLParams.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.utils.certificate.ocsp;
import java.security.cert.CertStore;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openspcoop2.utils.LoggerBuffer;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.UtilsMultiException;
import org.openspcoop2.utils.certificate.ArchiveLoader;
import org.openspcoop2.utils.certificate.AuthorityInformationAccess;
import org.openspcoop2.utils.certificate.CRLCertstore;
import org.openspcoop2.utils.certificate.CRLDistributionPoint;
import org.openspcoop2.utils.certificate.CRLDistributionPoints;
import org.openspcoop2.utils.certificate.Certificate;
import org.openspcoop2.utils.certificate.CertificateInfo;
import org.openspcoop2.utils.certificate.KeyStore;
import org.openspcoop2.utils.certificate.KeystoreType;
import org.openspcoop2.utils.transport.TransportUtils;
/**
* OCSPRequestParams
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class CRLParams {
private KeyStore crlTrustStore;
private CertStore crlCertstore;
public KeyStore getCrlTrustStore() {
return this.crlTrustStore;
}
public void setCrlTrustStore(KeyStore crlTrustStore) {
this.crlTrustStore = crlTrustStore;
}
public CertStore getCrlCertstore() {
return this.crlCertstore;
}
public void setCrlCertstore(CertStore crlCertstore) {
this.crlCertstore = crlCertstore;
}
public static CRLParams build(LoggerBuffer log, X509Certificate certificate, String crlInputConfig, KeyStore trustStore, OCSPConfig config, IOCSPResourceReader reader) throws UtilsException {
CertificateInfo cer = new CertificateInfo(certificate, "ocspVerifica");
return build(log, cer, crlInputConfig, trustStore, config, reader);
}
public static CRLParams build(LoggerBuffer log, CertificateInfo certificate, String crlInputConfig, KeyStore trustStore, OCSPConfig config, IOCSPResourceReader reader) throws UtilsException {
if(config==null) {
throw new UtilsException("Param config is null");
}
if(certificate==null) {
throw new UtilsException("Param certificate is null");
}
// comprendo path CRL
List<String> crlPaths = new ArrayList<>();
Map<String, byte[]> localResources = new HashMap<>();
if(config.getCrlSource()!=null && !config.getCrlSource().isEmpty()) {
List<Throwable> listExceptions = new ArrayList<>();
for (CertificateSource s : config.getCrlSource()) {
if(CertificateSource.CONFIG.equals(s)) {
if(crlInputConfig!=null) {
// รจ possibile fornire un'unica indicazione di una risorsa remota o in alternativa N file crl
if(TransportUtils.isRemoteResource(crlInputConfig)){
readCrlPath(crlInputConfig.trim(),
crlPaths, localResources,
listExceptions,
reader,
log);
}
else {
List<String> l = CRLCertstore.readCrlPaths(crlInputConfig);
if(l!=null && !l.isEmpty()) {
for (String crlPath : l) {
String p = crlPath.trim();
if(!crlPaths.contains(p)) {
crlPaths.add(p);
log.debug("OCSP-CRL: add config path '"+p+"'");
}
}
}
}
}
if(!crlPaths.isEmpty()) {
break;
}
}
else if(CertificateSource.ALTERNATIVE_CONFIG.equals(s)) {
List<String> l = null;
if(config.getCrlAlternative()!=null) {
l = config.getCrlAlternative();
}
if(l!=null && !l.isEmpty()) {
for (String crlPath : l) {
String p = crlPath.trim();
if(!crlPaths.contains(p)) {
crlPaths.add(p);
log.debug("OCSP-CRL: add alternative config path '"+p+"'");
}
}
}
if(!crlPaths.isEmpty()) {
break;
}
}
else if(CertificateSource.AUTHORITY_INFORMATION_ACCESS.equals(s)) {
try {
CRLDistributionPoints crls = certificate.getCRLDistributionPoints();
if(crls!=null) {
List<CRLDistributionPoint> crlsList = crls.getCRLDistributionPoints();
if(crlsList!=null && !crlsList.isEmpty()) {
for (CRLDistributionPoint crlDP : crlsList) {
List<String> l = crlDP.getDistributionPointNames();
if(l!=null) {
for (String crlPath : l) {
readCrlPath(crlPath,
crlPaths, localResources,
listExceptions,
reader,
log);
}
}
}
}
}
}catch(Exception t) {
throw new UtilsException(t.getMessage(),t);
}
if(!crlPaths.isEmpty()) {
break;
}
}
}
if(crlPaths.isEmpty()) {
boolean reject = false;
boolean isCA = false;
try {
isCA = certificate.isCA();
}catch(Exception t) {
throw new UtilsException(t.getMessage(),t);
}
if(isCA) {
reject = config.isRejectsCAWithoutCRL();
}
else {
reject = config.isRejectsCertificateWithoutCRL();
}
if(reject) {
if(!listExceptions.isEmpty()) {
if(listExceptions.size()==1) {
Throwable t = listExceptions.get(0);
if(t!=null) {
throw new UtilsException("Crl retrieve failed; "+t.getMessage(),t);
}
}
UtilsMultiException multi = new UtilsMultiException("Crl retrieve failed", listExceptions.toArray(new Throwable[1]));
throw new UtilsException("Crl retrieve failed;\n"+multi.getMultiMessage(),multi);
}
else {
throw new UtilsException("Crl retrieve failed");
}
}
}
}
KeyStore crlTrustStore = null;
if(!crlPaths.isEmpty() &&
// comprendo issuer del certificato da validare
config.getCrlTrustStoreSource()!=null && !config.getCrlTrustStoreSource().isEmpty()) {
for (CertificateSource s : config.getCrlTrustStoreSource()) {
if(CertificateSource.CONFIG.equals(s)) {
if(trustStore!=null) {
try {
if(crlTrustStore==null) {
java.security.KeyStore ks = java.security.KeyStore.getInstance(KeystoreType.JKS.getNome());
ks.load(null, null);
crlTrustStore = new KeyStore(ks);
}
}catch(Exception t) {
String msgError = "OCSP-CRL [crlssuer: CONFIG] retrieve failed: "+t.getMessage();
log.debug(msgError,t);
}
if(crlTrustStore!=null) {
crlTrustStore.putAllCertificate(trustStore, false);
}
log.debug("OCSP-CRL: add certificate in truststore config");
}
}
else if(CertificateSource.ALTERNATIVE_CONFIG.equals(s)) {
KeyStore alternativeTrustStore = null;
if(config.getAlternativeTrustStoreCRLPath()!=null) {
alternativeTrustStore = reader.getCrlAlternativeTrustStore();
}
if(alternativeTrustStore!=null) {
try {
if(crlTrustStore==null) {
java.security.KeyStore ks = java.security.KeyStore.getInstance(KeystoreType.JKS.getNome());
ks.load(null, null);
crlTrustStore = new KeyStore(ks);
}
}catch(Exception t) {
String msgError = "OCSP-CRL [crlssuer: ALTERNATIVE_CONFIG] retrieve failed: "+t.getMessage();
log.debug(msgError,t);
}
if(crlTrustStore!=null) {
crlTrustStore.putAllCertificate(alternativeTrustStore, false);
}
log.debug("OCSP-CRL: add certificate in alternative truststore config");
}
}
else if(CertificateSource.AUTHORITY_INFORMATION_ACCESS.equals(s)) {
try {
CRLDistributionPoints crls = certificate.getCRLDistributionPoints();
if(crls!=null) {
List<CRLDistributionPoint> crlsList = crls.getCRLDistributionPoints();
int indexCrl = 0;
if(crlsList!=null && !crlsList.isEmpty()) {
for (CRLDistributionPoint crlDP : crlsList) {
List<String> l = crlDP.getCRLIssuers();
if(l!=null) {
for (String crlPath : l) {
if(!crlPaths.contains(crlPath)) {
try {
Map<String, byte[]> map = new HashMap<>();
reader.readExternalResource(crlPath, map);
byte [] issuer = null;
if(!map.isEmpty()) {
issuer = map.get(crlPath);
}
if(issuer==null || issuer.length<=0) {
throw new UtilsException("empty resource");
}
Certificate cer = ArchiveLoader.load(issuer);
if(cer!=null && cer.getCertificate()!=null) {
if(crlTrustStore==null) {
java.security.KeyStore ks = java.security.KeyStore.getInstance(KeystoreType.JKS.getNome());
ks.load(null, null);
crlTrustStore = new KeyStore(ks);
}
crlTrustStore.putCertificate("crlIssuerCert-"+indexCrl, cer.getCertificate().getCertificate(), false);
indexCrl++;
log.debug("OCSP-CRL: add certificate retrieved from '"+crlPath+"'");
}
}catch(Exception t) {
String msgError = "OCSP-CRL [crlssuer: "+crlPath+"] retrieve failed: "+t.getMessage();
log.debug(msgError,t);
}
}
}
}
}
}
}
}catch(Exception t) {
throw new UtilsException(t.getMessage(),t);
}
try {
AuthorityInformationAccess aia = certificate.getAuthorityInformationAccess();
if(aia!=null) {
List<String> issuer = aia.getCAIssuers();
int indexAia = 0;
if(issuer!=null && !issuer.isEmpty()) {
for (String urlIssuer : issuer) {
Map<String, byte[]> map = new HashMap<>();
reader.readExternalResource(urlIssuer, map);
if(!map.isEmpty()) {
byte [] issCert = map.get(urlIssuer);
if(issCert!=null) {
Certificate cer = ArchiveLoader.load(issCert);
if(cer!=null && cer.getCertificate()!=null) {
if(crlTrustStore==null) {
java.security.KeyStore ks = java.security.KeyStore.getInstance(KeystoreType.JKS.getNome());
ks.load(null, null);
crlTrustStore = new KeyStore(ks);
}
crlTrustStore.putCertificate("aiaIssuerCert-"+indexAia, cer.getCertificate().getCertificate(), false);
indexAia++;
log.debug("OCSP-CRL-AIA: add certificate retrieved from '"+urlIssuer+"'");
}
}
}
}
}
}
}catch(Exception t) {
throw new UtilsException(t.getMessage(),t);
}
}
}
}
CRLParams params = new CRLParams();
if(!crlPaths.isEmpty()) {
params.crlCertstore = reader.readCRL(crlPaths, localResources).getCertStore();
/** boolean newTrustStore = false;
// if(crlTrustStore==null) {
// try {
// java.security.KeyStore ks = java.security.KeyStore.getInstance(KeystoreType.JKS.getNome());
// ks.load(null, null);
// crlTrustStore = new KeyStore(ks);
// newTrustStore = true;
// }catch(Throwable t) {
// throw new UtilsException(t.getMessage(),t);
// }
// }
//
// try {
// if(certificate.isCA()) {
// if(newTrustStore || (!params.crlTrustStore.existsCertificateBySubject(certificate.getCertificate().getSubjectX500Principal()))) {
// crlTrustStore.putCertificate("ca", certificate.getCertificate(), false);
// }
// }
// }catch(Throwable t) {
// throw new UtilsException(t.getMessage(),t);
// }*/
params.crlTrustStore = crlTrustStore;
}
return params;
}
private static void readCrlPath(String crlPath,
List<String> crlPaths,Map<String, byte[]> localResources,
List<Throwable> listExceptions,
IOCSPResourceReader reader,
LoggerBuffer log) {
if(!crlPaths.contains(crlPath)) {
try {
Map<String, byte[]> map = new HashMap<>();
reader.readExternalResource(crlPath, map);
byte [] crl = null;
if(!map.isEmpty()) {
crl = map.get(crlPath);
}
if(crl==null || crl.length<=0) {
throw new UtilsException("empty resource");
}
localResources.put(crlPath, crl);
crlPaths.add(crlPath);
log.debug("OCSP-CRL: add external resource '"+crlPath+"'");
}catch(Exception t) {
String msgError = "[crl: "+crlPath+"] retrieve failed: "+t.getMessage();
log.debug("OCSP-CRL "+msgError,t);
listExceptions.add(new Exception(msgError,t));
}
}
}
}