SSLSocketFactory.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.security.keystore;
import java.io.Serializable;
import java.util.HashMap;
import javax.net.ssl.SSLContext;
import org.apache.commons.lang.StringUtils;
import org.openspcoop2.protocol.sdk.state.RequestInfo;
import org.openspcoop2.security.SecurityException;
import org.openspcoop2.security.keystore.cache.GestoreKeystoreCache;
import org.openspcoop2.security.keystore.cache.GestoreOCSPResource;
import org.openspcoop2.security.keystore.cache.GestoreOCSPValidator;
import org.openspcoop2.utils.certificate.KeyStore;
import org.openspcoop2.utils.certificate.byok.BYOKProvider;
import org.openspcoop2.utils.certificate.byok.BYOKRequestParams;
import org.openspcoop2.utils.transport.http.IBYOKUnwrapManager;
import org.openspcoop2.utils.transport.http.IOCSPValidator;
import org.openspcoop2.utils.transport.http.SSLConfig;
import org.openspcoop2.utils.transport.http.SSLUtilities;
/**
* SSLSocketFactory
*
* @author Andrea Poli (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class SSLSocketFactory implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private SSLConfig sslConfig;
private transient javax.net.ssl.SSLSocketFactory sslSocketFactoryObject;
@Override
public String toString() {
StringBuilder bf = new StringBuilder();
bf.append("SSLContextFactory (").append(this.sslConfig).append(") ");
return bf.toString();
}
public SSLSocketFactory(RequestInfo requestInfo, SSLConfig sslConfig) throws SecurityException{
this.sslConfig = sslConfig;
this.initFactory(requestInfo);
}
private void checkInit(RequestInfo requestInfo) throws SecurityException{
if(this.sslSocketFactoryObject==null) {
this.initFactory(requestInfo);
}
}
private String getErrorMessage(String location, Exception e, boolean keystore) {
return "Lettura "+(keystore?"keystore":"truststore")+" '"+location+"' dalla cache fallita: "+e.getMessage();
}
private synchronized void initFactory(RequestInfo requestInfo) throws SecurityException{
if(this.sslSocketFactoryObject==null) {
try{
// Gestione https
if(this.sslConfig!=null){
// provo a leggere i keystore dalla cache
IBYOKUnwrapManager byokManager = null;
if(this.sslConfig.getKeyStoreLocation()!=null) {
BYOKRequestParams byokParams = null;
if(BYOKProvider.isPolicyDefined(this.sslConfig.getKeyStoreBYOKPolicy())){
byokParams = BYOKProvider.getBYOKRequestParamsByUnwrapBYOKPolicy(this.sslConfig.getKeyStoreBYOKPolicy(),
this.sslConfig.getDynamicMap()!=null ? this.sslConfig.getDynamicMap() : new HashMap<>() );
}
try {
KeyStore keystore = GestoreKeystoreCache.getMerlinKeystore(requestInfo, this.sslConfig.getKeyStoreLocation(),
this.sslConfig.getKeyStoreType(), this.sslConfig.getKeyStorePassword(),
byokParams).getKeyStore();
this.sslConfig.setKeyStore(keystore.getKeystore(), keystore.isKeystoreHsm());
}catch(Exception e) {
String msgError = getErrorMessage(this.sslConfig.getKeyStoreLocation(),e,true);
this.sslConfig.getLoggerBuffer().error(msgError, e);
}
if(this.sslConfig.getKeyStore()==null && byokParams!=null) {
// operazione precedente non riuscita
byokManager = new BYOKUnwrapManager(this.sslConfig.getKeyStoreBYOKPolicy(), byokParams);
}
}
if(this.sslConfig.getTrustStoreLocation()!=null) {
try {
KeyStore truststore = GestoreKeystoreCache.getMerlinTruststore(requestInfo, this.sslConfig.getTrustStoreLocation(),
this.sslConfig.getTrustStoreType(), this.sslConfig.getTrustStorePassword()).getTrustStore();
this.sslConfig.setTrustStore(truststore.getKeystore(), truststore.isKeystoreHsm());
}catch(Exception e) {
String msgError = getErrorMessage(this.sslConfig.getTrustStoreLocation(),e,false);
this.sslConfig.getLoggerBuffer().error(msgError, e);
}
}
IOCSPValidator ocspValidator = null;
boolean crlByOcsp = false;
if(this.sslConfig.getTrustStoreOCSPPolicy()!=null){
String policyType = this.sslConfig.getTrustStoreOCSPPolicy();
if(policyType!=null && StringUtils.isNotEmpty(policyType)) {
GestoreOCSPResource ocspResourceReader = new GestoreOCSPResource(requestInfo);
String crlInputConfig = this.sslConfig.getTrustStoreCRLsLocation();
ocspValidator = new GestoreOCSPValidator(requestInfo, this.sslConfig.getLog4jBuffer(), crlInputConfig, policyType, ocspResourceReader);
if(ocspValidator!=null) {
GestoreOCSPValidator gOcspValidator = (GestoreOCSPValidator) ocspValidator;
if(gOcspValidator.getOcspConfig()!=null) {
crlByOcsp = gOcspValidator.getOcspConfig().isCrl();
}
}
}
}
if(this.sslConfig.getTrustStoreCRLsLocation()!=null && !crlByOcsp) {
try {
this.sslConfig.setTrustStoreCRLs(GestoreKeystoreCache.getCRLCertstore(requestInfo, this.sslConfig.getTrustStoreCRLsLocation()).getCertStore());
}catch(Exception e) {
String msgError = "Lettura CRLs '"+this.sslConfig.getTrustStoreLocation()+"' dalla cache fallita: "+e.getMessage();
this.sslConfig.getLoggerBuffer().error(msgError, e);
}
}
StringBuilder bfSSLConfig = new StringBuilder();
SSLContext sslContext = SSLUtilities.generateSSLContext(this.sslConfig, ocspValidator, byokManager, bfSSLConfig);
this.sslSocketFactoryObject = sslContext.getSocketFactory();
if(this.sslConfig.getLoggerBuffer()!=null) {
String msgDebug = bfSSLConfig.toString();
this.sslConfig.getLoggerBuffer().debug(msgDebug);
}
}
}catch(Exception e){
throw new SecurityException(e.getMessage(),e);
}
}
}
public javax.net.ssl.SSLSocketFactory getSslSocketFactory(RequestInfo requestInfo) throws SecurityException {
this.checkInit(requestInfo); // per ripristino da Serializable
return this.sslSocketFactoryObject;
}
}