AutenticazioneSsl.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.pdd.core.autenticazione.pa;
import java.security.cert.CertStore;
import java.util.ArrayList;
import java.util.List;
import org.openspcoop2.core.commons.CoreException;
import org.openspcoop2.core.config.Proprieta;
import org.openspcoop2.core.id.IDServizioApplicativo;
import org.openspcoop2.core.id.IDSoggetto;
import org.openspcoop2.core.registry.driver.DriverRegistroServiziNotFound;
import org.openspcoop2.pdd.config.ConfigurazionePdDManager;
import org.openspcoop2.pdd.config.CostantiProprieta;
import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
import org.openspcoop2.pdd.core.autenticazione.AutenticazioneException;
import org.openspcoop2.pdd.core.autenticazione.WWWAuthenticateConfig;
import org.openspcoop2.pdd.core.credenziali.Credenziali;
import org.openspcoop2.pdd.core.keystore.GestoreKeystoreCaching;
import org.openspcoop2.pdd.logger.OpenSPCoop2Logger;
import org.openspcoop2.protocol.engine.ConfigurazioneFiltroServiziApplicativi;
import org.openspcoop2.protocol.engine.constants.Costanti;
import org.openspcoop2.protocol.registry.RegistroServiziManager;
import org.openspcoop2.protocol.sdk.constants.ErroriCooperazione;
import org.openspcoop2.protocol.sdk.constants.IntegrationFunctionError;
import org.openspcoop2.protocol.sdk.state.RequestInfo;
import org.openspcoop2.security.keystore.cache.GestoreOCSPResource;
import org.openspcoop2.security.keystore.cache.GestoreOCSPValidator;
import org.openspcoop2.utils.LoggerBuffer;
import org.openspcoop2.utils.UtilsMultiException;
import org.openspcoop2.utils.certificate.CertificateInfo;
import org.openspcoop2.utils.certificate.KeyStore;
import org.openspcoop2.utils.transport.http.IOCSPValidator;
import org.openspcoop2.utils.transport.http.OCSPResponseException;
/**
* Classe che implementa una autenticazione BASIC.
*
* @author Andrea Poli (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class AutenticazioneSsl extends AbstractAutenticazioneBase {
private boolean logError = true;
@Override
public void setLogError(boolean logError) {
this.logError = logError;
}
@Override
public EsitoAutenticazionePortaApplicativa process(DatiInvocazionePortaApplicativa datiInvocazione) throws AutenticazioneException{
EsitoAutenticazionePortaApplicativa esito = new EsitoAutenticazionePortaApplicativa();
if(datiInvocazione==null) {
throw new AutenticazioneException("Param datiInvocazione is null");
}
OpenSPCoop2Properties op2Properties = OpenSPCoop2Properties.getInstance();
WWWAuthenticateConfig wwwAuthenticateConfig = op2Properties.getRealmAutenticazioneHttpsWWWAuthenticateConfig();
Credenziali credenziali = datiInvocazione.getInfoConnettoreIngresso().getCredenziali();
RequestInfo requestInfo = datiInvocazione.getRequestInfo();
String subject = credenziali.getSubject();
String issuer = credenziali.getIssuer();
CertificateInfo certificate = null;
// Controllo credenziali fornite
if( subject==null || "".equals(subject) ){
esito.setErroreCooperazione(IntegrationFunctionError.AUTHENTICATION_CREDENTIALS_NOT_FOUND, ErroriCooperazione.AUTENTICAZIONE_FALLITA_CREDENZIALI_NON_FORNITE.getErroreCooperazione());
esito.setClientAuthenticated(false);
esito.setClientIdentified(false);
if(wwwAuthenticateConfig!=null) {
esito.setWwwAuthenticateErrorHeader(wwwAuthenticateConfig.buildWWWAuthenticateHeaderValue_notFound());
}
return esito;
}
if(credenziali.getCertificate()!=null) {
certificate = credenziali.getCertificate().getCertificate();
List<Proprieta> proprieta = null;
if(datiInvocazione.getPa()!=null) {
proprieta = datiInvocazione.getPa().getProprietaList();
}
else if(datiInvocazione.getPd()!=null) {
proprieta = datiInvocazione.getPd().getProprietaList();
}
boolean checkValid = false;
boolean trustStore = false;
KeyStore trustStoreCertificatiX509 = null;
CertStore trustStoreCertificatiX509crls = null;
IOCSPValidator ocspValidator = null;
try {
checkValid = CostantiProprieta.isAutenticazioneHttpsValidityCheck(proprieta, op2Properties.isAutenticazioneHttpsPortaApplicativaValidityCheck());
trustStore = CostantiProprieta.isAutenticazioneHttpsTrustStore(proprieta, op2Properties.getAutenticazioneHttpsPortaApplicativaTruststorePath());
if(trustStore) {
String path = CostantiProprieta.getAutenticazioneHttpsTrustStorePath(proprieta, op2Properties.getAutenticazioneHttpsPortaApplicativaTruststorePath());
if(path!=null) {
try {
String password = CostantiProprieta.getAutenticazioneHttpsTrustStorePassword(proprieta, op2Properties.getAutenticazioneHttpsPortaApplicativaTruststorePassword());
String type = CostantiProprieta.getAutenticazioneHttpsTrustStoreType(proprieta, op2Properties.getAutenticazioneHttpsPortaApplicativaTruststoreType());
trustStoreCertificatiX509 = GestoreKeystoreCaching.getMerlinTruststore(requestInfo, path,
type,
password).getTrustStore();
}catch(Exception e){
throw new CoreException("Errore durante la lettura del truststore indicato ("+path+"): "+e.getMessage());
}
}
if(trustStoreCertificatiX509!=null) {
String crl = CostantiProprieta.getAutenticazioneHttpsTrustStoreCRLs(proprieta, op2Properties.getAutenticazioneHttpsPortaApplicativaTruststoreCRLs());
boolean crlByOcsp = false;
String ocspPolicy = CostantiProprieta.getAutenticazioneHttpsTrustStoreOCSPPolicy(proprieta, op2Properties.getAutenticazioneHttpsPortaApplicativaTruststoreOCSPPolicy());
if(ocspPolicy!=null) {
LoggerBuffer lb = new LoggerBuffer();
lb.setLogDebug(OpenSPCoop2Logger.getLoggerOpenSPCoopCore());
lb.setLogError(OpenSPCoop2Logger.getLoggerOpenSPCoopCore());
GestoreOCSPResource ocspResourceReader = new GestoreOCSPResource(requestInfo);
try {
ocspValidator = new GestoreOCSPValidator(requestInfo, lb,
trustStoreCertificatiX509,
crl,
ocspPolicy,
ocspResourceReader);
}catch(Exception e){
throw new CoreException("Errore durante l'inizializzazione del gestore della policy OCSP ("+ocspPolicy+"): "+e.getMessage());
}
if(ocspValidator!=null) {
GestoreOCSPValidator gOcspValidator = (GestoreOCSPValidator) ocspValidator;
if(gOcspValidator.getOcspConfig()!=null) {
crlByOcsp = gOcspValidator.getOcspConfig().isCrl();
}
}
}
if(crl!=null && !crlByOcsp) {
try {
trustStoreCertificatiX509crls = GestoreKeystoreCaching.getCRLCertstore(requestInfo, crl).getCertStore();
}catch(Exception e){
throw new CoreException("Errore durante la lettura delle CRLs ("+crl+"): "+e.getMessage());
}
}
}
}
}catch(Exception e) {
if(this.logError) {
OpenSPCoop2Logger.getLoggerOpenSPCoopCore().error("AutenticazioneSsl non riuscita",e);
}
esito.setErroreCooperazione(IntegrationFunctionError.INTERNAL_REQUEST_ERROR, ErroriCooperazione.ERRORE_GENERICO_PROCESSAMENTO_MESSAGGIO.getErroreCooperazione());
esito.setClientIdentified(false);
esito.setEccezioneProcessamento(e);
return esito;
}
if(checkValid
&&
trustStoreCertificatiX509crls==null) { // altrimenti la validita' viene verificata insieme alle CRL
try {
certificate.checkValid();
}catch(Exception e) {
esito.setErroreCooperazione(IntegrationFunctionError.AUTHENTICATION_INVALID_CREDENTIALS,
ErroriCooperazione.AUTENTICAZIONE_FALLITA_CREDENZIALI_FORNITE_NON_CORRETTE.getErroreCredenzialiForniteNonCorrette(e.getMessage()));
esito.setClientAuthenticated(false);
esito.setClientIdentified(false);
if(wwwAuthenticateConfig!=null) {
esito.setWwwAuthenticateErrorHeader(wwwAuthenticateConfig.buildWWWAuthenticateHeaderValue_invalid());
}
return esito;
}
}
if(trustStoreCertificatiX509!=null) {
try {
if(certificate.isVerified(trustStoreCertificatiX509, true)==false) {
throw new CoreException("Certificato non verificabile rispetto alle CA conosciute");
}
if(trustStoreCertificatiX509crls!=null) {
try {
certificate.checkValid(trustStoreCertificatiX509crls, trustStoreCertificatiX509);
}catch(Throwable t) {
throw new CoreException("Certificato non valido: "+t.getMessage());
}
}
}catch(Exception e) {
esito.setErroreCooperazione(IntegrationFunctionError.AUTHENTICATION_INVALID_CREDENTIALS,
ErroriCooperazione.AUTENTICAZIONE_FALLITA_CREDENZIALI_FORNITE_NON_CORRETTE.getErroreCredenzialiForniteNonCorrette(e.getMessage()));
esito.setClientAuthenticated(false);
esito.setClientIdentified(false);
if(wwwAuthenticateConfig!=null) {
esito.setWwwAuthenticateErrorHeader(wwwAuthenticateConfig.buildWWWAuthenticateHeaderValue_invalid());
}
return esito;
}
}
if(ocspValidator!=null) {
try {
ocspValidator.valid(certificate.getCertificate());
}catch(Throwable t) {
esito.setErroreCooperazione(IntegrationFunctionError.AUTHENTICATION_INVALID_CREDENTIALS,
ErroriCooperazione.AUTENTICAZIONE_FALLITA_CREDENZIALI_FORNITE_NON_CORRETTE.getErroreCredenzialiForniteNonCorrette(t.getMessage()));
esito.setClientAuthenticated(false);
esito.setClientIdentified(false);
if(!(t instanceof OCSPResponseException)) {
esito.setNoCache(true);
}
if(wwwAuthenticateConfig!=null) {
esito.setWwwAuthenticateErrorHeader(wwwAuthenticateConfig.buildWWWAuthenticateHeaderValue_invalid());
}
return esito;
}
}
}
// Essendoci l'identita' del chiamante, il client e' stato autenticato o da un frontend o dall'application server stesso
esito.setClientAuthenticated(true);
esito.setCredential(subject);
IDSoggetto idSoggetto = null;
try{
RegistroServiziManager registroServiziManager = RegistroServiziManager.getInstance(datiInvocazione.getState());
List<Throwable> notFoundExceptions = new ArrayList<>();
// NOTA: il fatto di essersi registrati come strict o come non strict è insito nella registrazione dell'applicativo
// 1. Prima si cerca per certificato strict
if(certificate!=null) {
try{
idSoggetto = registroServiziManager.getIdSoggettoByCredenzialiSsl(certificate, true, null); // all registry
}catch(DriverRegistroServiziNotFound notFound){
notFoundExceptions.add(notFound);
}
}
if(idSoggetto==null &&
// 2. Poi per certificato no strict
certificate!=null) {
try{
idSoggetto = registroServiziManager.getIdSoggettoByCredenzialiSsl(certificate, false, null); // all registry
}catch(DriverRegistroServiziNotFound notFound){
notFoundExceptions.add(notFound);
}
}
if(idSoggetto==null) {
// 3. per subject/issuer
try {
idSoggetto = registroServiziManager.getIdSoggettoByCredenzialiSsl(subject, issuer, null); // all registry
}catch(DriverRegistroServiziNotFound notFound){
notFoundExceptions.add(notFound);
}
}
if(idSoggetto==null) {
// 4. solo per subject
try {
idSoggetto = registroServiziManager.getIdSoggettoByCredenzialiSsl(subject, null, null); // all registry
}catch(DriverRegistroServiziNotFound notFound){
notFoundExceptions.add(notFound);
}
}
if(idSoggetto==null && !notFoundExceptions.isEmpty()) {
throw new UtilsMultiException(notFoundExceptions.toArray(new Throwable[1]));
}
}
catch(UtilsMultiException notFound){
if(this.logError) {
OpenSPCoop2Logger.getLoggerOpenSPCoopCore().debug("AutenticazioneSsl non ha trovato risultati",notFound);
}
}
catch(Exception e){
if(this.logError) {
OpenSPCoop2Logger.getLoggerOpenSPCoopCore().error("AutenticazioneSsl non riuscita",e);
}
esito.setErroreCooperazione(IntegrationFunctionError.INTERNAL_REQUEST_ERROR, ErroriCooperazione.ERRORE_GENERICO_PROCESSAMENTO_MESSAGGIO.getErroreCooperazione());
esito.setClientIdentified(false);
esito.setEccezioneProcessamento(e);
return esito;
}
IDServizioApplicativo idServizioApplicativo = null;
try {
if(idSoggetto==null && this.getProtocolFactory().createProtocolConfiguration().isSupportoAutenticazioneApplicativiErogazioni()
&&
!Costanti.MODIPA_PROTOCOL_NAME.equals(this.getProtocolFactory().getProtocol()) // su ModI i certificati vengono associati per le firme
) {
ConfigurazionePdDManager configurazionePdDManager = ConfigurazionePdDManager.getInstance(datiInvocazione.getState());
// NOTA: il fatto di essersi registrati come strict o come non strict è insito nella registrazione dell'applicativo
ConfigurazioneFiltroServiziApplicativi filtroHttps = ConfigurazioneFiltroServiziApplicativi.getFiltroApplicativiHttps();
// 1. Prima si cerca per certificato strict
if(certificate!=null) {
idServizioApplicativo = configurazionePdDManager.getIdServizioApplicativoByCredenzialiSsl(certificate, true,
filtroHttps.getTipiSoggetti(), filtroHttps.isIncludiApplicativiNonModI(), filtroHttps.isIncludiApplicativiModIEsterni(), filtroHttps.isIncludiApplicativiModIInterni());
}
if(idServizioApplicativo==null &&
// 2. Poi per certificato no strict
certificate!=null) {
idServizioApplicativo = configurazionePdDManager.getIdServizioApplicativoByCredenzialiSsl(certificate, false,
filtroHttps.getTipiSoggetti(), filtroHttps.isIncludiApplicativiNonModI(), filtroHttps.isIncludiApplicativiModIEsterni(), filtroHttps.isIncludiApplicativiModIInterni());
}
if(idServizioApplicativo==null) {
// 3. per subject/issuer
idServizioApplicativo = configurazionePdDManager.getIdServizioApplicativoByCredenzialiSsl(subject, issuer,
filtroHttps.getTipiSoggetti(), filtroHttps.isIncludiApplicativiNonModI(), filtroHttps.isIncludiApplicativiModIEsterni(), filtroHttps.isIncludiApplicativiModIInterni());
}
if(idServizioApplicativo==null) {
// 4. solo per subject
idServizioApplicativo = configurazionePdDManager.getIdServizioApplicativoByCredenzialiSsl(subject, null,
filtroHttps.getTipiSoggetti(), filtroHttps.isIncludiApplicativiNonModI(), filtroHttps.isIncludiApplicativiModIEsterni(), filtroHttps.isIncludiApplicativiModIInterni());
}
if(idServizioApplicativo!=null) {
if(idSoggetto==null) {
idSoggetto = idServizioApplicativo.getIdSoggettoProprietario();
}
// Non ha senso poter identificare entrambi con le stesse credenziali
// else if(idServizioApplicativo.getIdSoggettoProprietario().equals(idSoggetto)==false) {
// throw new Exception("Identificato sia un soggetto che un applicativo. Il soggetto ["+idSoggetto+
// "] identificato è differente dal proprietario dell'applicativo identificato ["+idServizioApplicativo.getIdSoggettoProprietario()+"]");
// }
}
}
}
catch(Exception e){
if(this.logError) {
OpenSPCoop2Logger.getLoggerOpenSPCoopCore().error("AutenticazioneSsl (Applicativi) non riuscita",e);
}
esito.setErroreCooperazione(IntegrationFunctionError.INTERNAL_REQUEST_ERROR, ErroriCooperazione.ERRORE_GENERICO_PROCESSAMENTO_MESSAGGIO.getErroreCooperazione());
esito.setClientAuthenticated(false);
esito.setClientIdentified(false);
esito.setEccezioneProcessamento(e);
return esito;
}
if(idSoggetto == null){
// L'identificazione in ssl non e' obbligatoria
/** esito.setErroreCooperazione(ErroriCooperazione.AUTENTICAZIONE_FALLITA_CREDENZIALI_FORNITE_NON_CORRETTE.getErroreCooperazione());*/
esito.setClientIdentified(false);
return esito;
}
else {
esito.setClientIdentified(true);
esito.setIdSoggetto(idSoggetto);
esito.setIdServizioApplicativo(idServizioApplicativo);
}
return esito;
}
}