ModIValidazioneSemantica.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.protocol.modipa.validator;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.openspcoop2.core.config.PortaApplicativa;
import org.openspcoop2.core.config.PortaApplicativaAutorizzazioneServizioApplicativo;
import org.openspcoop2.core.config.ServizioApplicativo;
import org.openspcoop2.core.config.constants.RuoloTipologia;
import org.openspcoop2.core.config.constants.StatoFunzionalita;
import org.openspcoop2.core.constants.Costanti;
import org.openspcoop2.core.constants.CostantiDB;
import org.openspcoop2.core.constants.CostantiLabel;
import org.openspcoop2.core.constants.TipoPdD;
import org.openspcoop2.core.id.IDPortaApplicativa;
import org.openspcoop2.core.id.IDServizioApplicativo;
import org.openspcoop2.core.id.IDSoggetto;
import org.openspcoop2.message.OpenSPCoop2Message;
import org.openspcoop2.message.constants.ServiceBinding;
import org.openspcoop2.pdd.config.ConfigurazionePdDReader;
import org.openspcoop2.pdd.config.OpenSPCoop2Properties;
import org.openspcoop2.pdd.config.PDNDResolver;
import org.openspcoop2.pdd.core.CostantiPdD;
import org.openspcoop2.pdd.core.token.InformazioniToken;
import org.openspcoop2.pdd.core.token.TokenUtilities;
import org.openspcoop2.pdd.core.token.parser.Claims;
import org.openspcoop2.pdd.logger.MsgDiagnosticiProperties;
import org.openspcoop2.pdd.logger.MsgDiagnostico;
import org.openspcoop2.protocol.basic.validator.ValidazioneSemantica;
import org.openspcoop2.protocol.engine.SecurityTokenUtilities;
import org.openspcoop2.protocol.modipa.config.ModIProperties;
import org.openspcoop2.protocol.modipa.constants.ModICostanti;
import org.openspcoop2.protocol.modipa.utils.ModISecurityConfig;
import org.openspcoop2.protocol.modipa.utils.ModIUtilities;
import org.openspcoop2.protocol.registry.RegistroServiziManager;
import org.openspcoop2.protocol.sdk.Busta;
import org.openspcoop2.protocol.sdk.Eccezione;
import org.openspcoop2.protocol.sdk.IProtocolFactory;
import org.openspcoop2.protocol.sdk.ProtocolException;
import org.openspcoop2.protocol.sdk.RestMessageSecurityToken;
import org.openspcoop2.protocol.sdk.SecurityToken;
import org.openspcoop2.protocol.sdk.constants.CodiceErroreCooperazione;
import org.openspcoop2.protocol.sdk.constants.RuoloBusta;
import org.openspcoop2.protocol.sdk.registry.IRegistryReader;
import org.openspcoop2.protocol.sdk.state.IState;
import org.openspcoop2.protocol.sdk.state.RequestInfo;
import org.openspcoop2.protocol.sdk.validator.ProprietaValidazione;
import org.openspcoop2.protocol.sdk.validator.ValidazioneSemanticaResult;
import org.openspcoop2.protocol.sdk.validator.ValidazioneUtils;
import org.openspcoop2.protocol.utils.ModIUtils;
import org.openspcoop2.protocol.utils.ModIValidazioneSemanticaProfiloSicurezza;
import org.openspcoop2.utils.SortedMap;
import org.openspcoop2.utils.certificate.remote.RemoteStoreConfig;
import org.openspcoop2.utils.date.DateManager;
import org.openspcoop2.utils.date.DateUtils;
import org.openspcoop2.utils.digest.DigestEncoding;
import org.openspcoop2.utils.properties.PropertiesUtilities;
import org.openspcoop2.utils.transport.http.HttpConstants;
/**
* Classe che implementa, in base al protocollo SdI, l'interfaccia {@link org.openspcoop2.protocol.sdk.validator.IValidazioneSemantica}
*
* @author Poli Andrea (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class ModIValidazioneSemantica extends ValidazioneSemantica {
/** ValidazioneUtils */
protected ValidazioneUtils validazioneUtils;
/** Properties */
protected ModIProperties modiProperties;
/** Errori di validazione riscontrati sulla busta */
protected java.util.List<Eccezione> erroriValidazione = new ArrayList<>();
/** Errori di processamento riscontrati sulla busta */
protected java.util.List<Eccezione> erroriProcessamento = new ArrayList<>();
public ModIValidazioneSemantica(IProtocolFactory<?> factory, IState state) throws ProtocolException {
super(factory, state);
this.modiProperties = ModIProperties.getInstance();
this.validazioneUtils = new ValidazioneUtils(factory);
}
private static final String DIAGNOSTIC_VALIDATE = "validazioneSemantica";
private static final String DIAGNOSTIC_IN_CORSO = "inCorso";
private static final String DIAGNOSTIC_COMPLETATA = "completata";
private static final String DIAGNOSTIC_FALLITA = "fallita";
private String getErroreClaimNonValido(String claim) {
return "Token contenente un claim '"+claim+"' non valido";
}
private String getErroreClaimNonPresente(String claim) {
return "Token non contiene il claim '"+claim+"'";
}
private Eccezione getErroreMittenteNonAutorizzato(Busta busta, String msgErrore) throws ProtocolException {
String idApp = busta.getServizioApplicativoFruitore() + " (Soggetto: "+busta.getMittente()+")";
return this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.SICUREZZA_AUTORIZZAZIONE_FALLITA,
"Applicativo Mittente "+idApp+" non autorizzato"+(msgErrore!=null ? "; "+msgErrore: ""));
}
private void addErroreMittenteNonAutorizzato(Busta busta, String msgErrore) throws ProtocolException {
this.erroriValidazione.add(getErroreMittenteNonAutorizzato(busta, msgErrore));
}
private static final String MSG_ERRORE_NON_PRESENTE = "non presente";
private String getPrefixHeader(String hdr) {
return "[Header '"+hdr+"'] ";
}
@Override
public ValidazioneSemanticaResult valida(OpenSPCoop2Message msg, Busta busta,
ProprietaValidazione proprietaValidazione,
RuoloBusta tipoBusta) throws ProtocolException{
this.valida(msg,busta,tipoBusta, this.protocolFactory, this.state);
java.util.List<Eccezione> erroriValidazioneList = null;
if(!this.erroriValidazione.isEmpty()){
erroriValidazioneList = this.erroriValidazione;
if(this.context!=null) {
this.context.addObject(Costanti.ERRORE_VALIDAZIONE_PROTOCOLLO, Costanti.ERRORE_TRUE);
}
}
java.util.List<Eccezione> erroriProcessamentoList = null;
if(!this.erroriProcessamento.isEmpty()){
erroriValidazioneList = this.erroriProcessamento;
}
return new ValidazioneSemanticaResult(erroriValidazioneList, erroriProcessamentoList, null, null, null, null);
}
private void valida(OpenSPCoop2Message msg,Busta busta, RuoloBusta tipoBusta, IProtocolFactory<?> factory, IState state) throws ProtocolException{
MsgDiagnostico msgDiag = null;
String tipoDiagnostico = null;
boolean verifica = false;
boolean autorizzazione = false;
int sizeListaErroriValidazionePrimaAutorizzazione = -1;
int sizeListaProcessamentoValidazionePrimaAutorizzazione = -1;
try{
String prefixIntegrity = getPrefixHeader(this.modiProperties.getRestSecurityTokenHeaderModI());
RequestInfo requestInfo = null;
if(this.context!=null && this.context.containsKey(org.openspcoop2.core.constants.Costanti.REQUEST_INFO)) {
requestInfo = (RequestInfo) this.context.getObject(org.openspcoop2.core.constants.Costanti.REQUEST_INFO);
}
boolean isRichiesta = RuoloBusta.RICHIESTA.equals(tipoBusta);
boolean rest = msg!=null && ServiceBinding.REST.equals(msg.getServiceBinding());
if(busta==null) {
throw new ProtocolException("Busta undefined");
}
TipoPdD tipoPdD = isRichiesta ? TipoPdD.APPLICATIVA : TipoPdD.DELEGATA;
IDSoggetto idSoggetto = TipoPdD.DELEGATA.equals(tipoPdD) ?
new IDSoggetto(busta.getTipoMittente(),busta.getMittente()) :
new IDSoggetto(busta.getTipoDestinatario(),busta.getDestinatario());
if(idSoggetto==null || idSoggetto.getTipo()==null || idSoggetto.getNome()==null) {
idSoggetto = OpenSPCoop2Properties.getInstance().getIdentitaPortaDefault(this.protocolFactory.getProtocol(), requestInfo);
}
else {
IRegistryReader registryReader = this.getProtocolFactory().getCachedRegistryReader(this.state, requestInfo);
idSoggetto.setCodicePorta(registryReader.getDominio(idSoggetto));
}
msgDiag = MsgDiagnostico.newInstance(TipoPdD.DELEGATA,
idSoggetto,
"ModI", requestInfo!=null && requestInfo.getProtocolContext()!=null ? requestInfo.getProtocolContext().getInterfaceName() : null,
requestInfo,
this.state);
if(TipoPdD.DELEGATA.equals(tipoPdD)){
msgDiag.setPrefixMsgPersonalizzati(MsgDiagnosticiProperties.MSG_DIAG_RICEZIONE_CONTENUTI_APPLICATIVI);
}
else {
msgDiag.setPrefixMsgPersonalizzati(MsgDiagnosticiProperties.MSG_DIAG_RICEZIONE_BUSTE);
}
msgDiag.setPddContext(this.context, this.protocolFactory);
tipoDiagnostico = isRichiesta ? ".richiesta." : ".risposta.";
Date now = DateManager.getDate();
ModIValidazioneSemanticaProfiloSicurezza modIValidazioneSemanticaProfiloSicurezza = new ModIValidazioneSemanticaProfiloSicurezza(busta, isRichiesta);
boolean sicurezzaTokenOauth = modIValidazioneSemanticaProfiloSicurezza.isSicurezzaTokenOauth();
String securityMessageProfileSorgenteTokenIdAuth = modIValidazioneSemanticaProfiloSicurezza.getSecurityMessageProfileSorgenteTokenIdAuth();
boolean sicurezzaMessaggio = modIValidazioneSemanticaProfiloSicurezza.isSicurezzaMessaggio();
boolean sicurezzaMessaggioIDAR04 = modIValidazioneSemanticaProfiloSicurezza.isSicurezzaMessaggioIDAR04();
boolean sicurezzaAudit = modIValidazioneSemanticaProfiloSicurezza.isSicurezzaAudit();
String securityAuditPattern = modIValidazioneSemanticaProfiloSicurezza.getSecurityAuditPattern();
if(sicurezzaMessaggio || sicurezzaAudit) {
msgDiag.logPersonalizzato(DIAGNOSTIC_VALIDATE+tipoDiagnostico+DIAGNOSTIC_IN_CORSO);
verifica=true;
}
PortaApplicativa pa = null;
RemoteStoreConfig rsc = null;
if(isRichiesta && sicurezzaTokenOauth) {
String prefixAuthorization = getPrefixHeader(HttpConstants.AUTHORIZATION);
boolean sicurezzaToken = this.context.containsKey(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_TOKEN_INFORMAZIONI_NORMALIZZATE);
if(!sicurezzaToken) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_PRESENTE,
prefixAuthorization+MSG_ERRORE_NON_PRESENTE));
}
else {
validateTokenAuthorizationId(msg,
prefixAuthorization,
modIValidazioneSemanticaProfiloSicurezza);
boolean checkAudienceByModIConfig = sicurezzaMessaggio || sicurezzaAudit;
pa = validateTokenAuthorizationAudience(msg, factory, state, requestInfo,
isRichiesta, prefixAuthorization,
checkAudienceByModIConfig);
PDNDResolver pdndResolver = new PDNDResolver(this.context, this.modiProperties.getRemoteStoreConfig());
rsc = pdndResolver.enrichTokenInfo(requestInfo, sicurezzaMessaggio, sicurezzaAudit, idSoggetto);
}
}
if(sicurezzaMessaggio) {
if(isRichiesta && sicurezzaTokenOauth) {
String id = busta.getProperty(CostantiDB.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_ID);
if( id==null || StringUtils.isEmpty(id) ) {
// non c'era un token di integrita nonostante ne sia stato configurato (es. per GET) e sia stato indicato di utilizzarlo come identificativo messaggio.
// per questo motivo in ricezione buste il metodo 'ModIUtils.replaceBustaIdWithJtiTokenId' non è stato invocato
// Utilizzo come identificativo del messaggio quello presente nel voucher.
String jti = TokenUtilities.readJtiFromInformazioniToken(this.context);
if(jti!=null && StringUtils.isNotEmpty(jti)) {
ModIUtils.replaceBustaIdWithJtiTokenId(modIValidazioneSemanticaProfiloSicurezza, jti);
msgDiag.updateKeywordIdMessaggioRichiesta(busta.getID());
if(this.context!=null) {
this.context.put(Costanti.MODI_JTI_REQUEST_ID_UPDATE_DIAGNOSTIC, busta.getID());
}
}
}
}
String exp = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_EXP);
if(exp!=null) {
checkExp(exp, now, rest, "");
}
String expIntegrity = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_REST_INTEGRITY_EXP);
if(expIntegrity!=null) {
checkExp(expIntegrity, now, rest, prefixIntegrity);
}
String nbf = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_NBF);
if(nbf!=null) {
checkNbf(nbf, now, "");
}
String nbfIntegrity = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_REST_INTEGRITY_NBF);
if(nbfIntegrity!=null) {
checkNbf(nbfIntegrity, now, prefixIntegrity);
}
String iat = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_IAT);
if(iat!=null) {
checkIat(iat, msg, rest, "");
}
String iatIntegrity = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_REST_INTEGRITY_IAT);
if(iatIntegrity!=null) {
checkIat(iatIntegrity, msg, rest, prefixIntegrity);
}
String audienceBusta = busta.getProperty(rest ?
ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_REST_AUDIENCE :
ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_SOAP_WSA_TO );
List<String> listAudienceBusta = null;
if(rest && this.modiProperties.isRestSecurityTokenAudienceProcessArrayModeEnabled()) {
listAudienceBusta = ModIUtilities.getArrayStringAsList(audienceBusta, true);
}
Object audienceAttesoObject = null;
if(msg!=null) {
audienceAttesoObject = msg.getContextProperty(ModICostanti.MODIPA_OPENSPCOOP2_MSG_CONTEXT_AUDIENCE_CHECK);
}
String audienceAtteso = null;
if(audienceAttesoObject!=null) {
audienceAtteso = (String) audienceAttesoObject;
}
Object audienceAttesoOAuthObject = null;
if(msg!=null) {
audienceAttesoOAuthObject = msg.getContextProperty(ModICostanti.MODIPA_OPENSPCOOP2_MSG_CONTEXT_AUDIENCE_CHECK_OAUTH);
}
String audienceOAuthAtteso = null;
if(audienceAttesoOAuthObject!=null) {
audienceOAuthAtteso = (String) audienceAttesoOAuthObject;
}
if(audienceAtteso!=null || audienceOAuthAtteso!=null) {
boolean checkAudience = isAudienceValid(audienceAtteso, audienceBusta, listAudienceBusta);
boolean checkAudienceOAuth = isAudienceValid(audienceOAuthAtteso, audienceBusta, listAudienceBusta);
if(!checkAudience && !checkAudienceOAuth) {
boolean buildSecurityTokenInRequest = true;
Object buildSecurityTokenInRequestObject = msg.getContextProperty(ModICostanti.MODIPA_OPENSPCOOP2_MSG_CONTEXT_BUILD_SECURITY_REQUEST_TOKEN);
if(buildSecurityTokenInRequestObject instanceof Boolean) {
buildSecurityTokenInRequest = (Boolean) buildSecurityTokenInRequestObject;
}
if(isRichiesta || buildSecurityTokenInRequest) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
isRichiesta ? CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_EROGATORE_NON_VALIDO :
CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_FRUITORE_NON_VALIDO,
getErroreClaimNonValido(Claims.JSON_WEB_TOKEN_RFC_7519_AUDIENCE)));
}
}
}
if(rest) {
Object audienceIntegrityAttesoObject = null;
if(msg!=null) {
audienceIntegrityAttesoObject = msg.getContextProperty(ModICostanti.MODIPA_OPENSPCOOP2_MSG_CONTEXT_AUDIENCE_INTEGRITY_CHECK);
}
String audienceIntegrityAtteso = null;
if(audienceIntegrityAttesoObject!=null) {
audienceIntegrityAtteso = (String) audienceIntegrityAttesoObject;
}
Object audienceIntegrityAttesoOAuthObject = null;
if(msg!=null) {
audienceIntegrityAttesoOAuthObject = msg.getContextProperty(ModICostanti.MODIPA_OPENSPCOOP2_MSG_CONTEXT_AUDIENCE_INTEGRITY_CHECK_OAUTH);
}
String audienceIntegrityOAuthAtteso = null;
if(audienceIntegrityAttesoOAuthObject!=null) {
audienceIntegrityOAuthAtteso = (String) audienceIntegrityAttesoOAuthObject;
}
if(audienceIntegrityAtteso!=null || audienceIntegrityOAuthAtteso!=null) {
String audienceIntegrityBusta = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_REST_INTEGRITY_AUDIENCE);
if(audienceIntegrityBusta==null) {
// significa che l'audience tra i due token ricevuto e' identico
audienceIntegrityBusta = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_REST_AUDIENCE);
}
List<String> listAudienceIntegrityBusta = null;
if(audienceIntegrityBusta!=null && rest && this.modiProperties.isRestSecurityTokenAudienceProcessArrayModeEnabled()) {
listAudienceIntegrityBusta = ModIUtilities.getArrayStringAsList(audienceIntegrityBusta, true);
}
boolean checkAudience = isAudienceValid(audienceIntegrityAtteso, audienceIntegrityBusta, listAudienceIntegrityBusta);
boolean checkAudienceOAuth = isAudienceValid(audienceIntegrityOAuthAtteso, audienceIntegrityBusta, listAudienceIntegrityBusta);
if(!checkAudience && !checkAudienceOAuth) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
isRichiesta ? CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_EROGATORE_NON_VALIDO :
CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_FRUITORE_NON_VALIDO,
prefixIntegrity+getErroreClaimNonValido(Claims.JSON_WEB_TOKEN_RFC_7519_AUDIENCE)));
}
}
}
}
if(sicurezzaAudit) {
String prefixAudit = getPrefixHeader(this.modiProperties.getSecurityTokenHeaderModIAudit());
boolean audit02 = CostantiDB.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_PATTERN_AUDIT_REST_02.equals(securityAuditPattern);
String exp = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_AUDIT_EXP);
if(exp!=null) {
checkExp(exp, now, rest, prefixAudit);
}
String nbf = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_AUDIT_NBF);
if(nbf!=null) {
checkNbf(nbf, now, prefixAudit);
}
String iat = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_AUDIT_IAT);
if(iat!=null) {
checkIat(iat, msg, rest, prefixAudit);
}
Object audienceAuditAttesoObject = null;
if(msg!=null) {
audienceAuditAttesoObject = msg.getContextProperty(ModICostanti.MODIPA_OPENSPCOOP2_MSG_CONTEXT_AUDIENCE_AUDIT_CHECK);
}
if(audienceAuditAttesoObject!=null) {
String audienceAuditAtteso = (String) audienceAuditAttesoObject;
String audienceAuditBusta = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_AUDIT_AUDIENCE);
if(audienceAuditBusta==null) {
// significa che l'audience tra i due token ricevuto e' identico
audienceAuditBusta = busta.getProperty(ModICostanti.MODIPA_BUSTA_EXT_PROFILO_SICUREZZA_MESSAGGIO_REST_AUDIENCE);
}
List<String> listAudienceAuditBusta = null;
if(audienceAuditBusta!=null && this.modiProperties.isSecurityTokenAuditProcessArrayModeEnabled()) {
listAudienceAuditBusta = ModIUtilities.getArrayStringAsList(audienceAuditBusta, true);
}
boolean checkAudienceAudit = isAudienceValid(audienceAuditAtteso, audienceAuditBusta, listAudienceAuditBusta);
if(!checkAudienceAudit) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
isRichiesta ? CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_EROGATORE_NON_VALIDO :
CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_FRUITORE_NON_VALIDO,
prefixAudit+getErroreClaimNonValido(Claims.JSON_WEB_TOKEN_RFC_7519_AUDIENCE)));
}
}
if(rsc!=null) {
validatePurposeId(rsc, prefixAudit, securityAuditPattern);
}
if(audit02) {
validateAudit02(securityMessageProfileSorgenteTokenIdAuth, rest, prefixAudit);
}
}
if(verifica) {
if(this.erroriValidazione.isEmpty() && this.erroriProcessamento.isEmpty()) {
msgDiag.logPersonalizzato(DIAGNOSTIC_VALIDATE+tipoDiagnostico+DIAGNOSTIC_COMPLETATA);
}
else {
String errore = null;
if(!this.erroriValidazione.isEmpty()) {
errore = ModIValidazioneSintattica.buildErrore(this.erroriValidazione, factory);
}
else {
errore = ModIValidazioneSintattica.buildErrore(this.erroriProcessamento, factory);
}
msgDiag.addKeyword(CostantiPdD.KEY_ERRORE_PROCESSAMENTO, errore);
msgDiag.logPersonalizzato(DIAGNOSTIC_VALIDATE+tipoDiagnostico+DIAGNOSTIC_FALLITA);
}
verifica = false;
}
if(isRichiesta) {
tipoDiagnostico = ".autorizzazione.";
msgDiag.logPersonalizzato(DIAGNOSTIC_VALIDATE+tipoDiagnostico+DIAGNOSTIC_IN_CORSO);
autorizzazione = true;
sizeListaErroriValidazionePrimaAutorizzazione = this.erroriValidazione.size();
sizeListaProcessamentoValidazionePrimaAutorizzazione = this.erroriProcessamento.size();
// vale sia per sicurezza messaggio che per token
// durante l'identificazione viene identificato 1 solo applicativo (non possono essere differenti tra token e trasporto)
// viene quindi inserito dentro busta e usato per i controlli sottostanti
if(pa==null) {
String interfaceName = null;
if(msg!=null && msg.getTransportRequestContext()!=null && msg.getTransportRequestContext().getInterfaceName()!=null) {
interfaceName = msg.getTransportRequestContext().getInterfaceName();
}
else if(requestInfo!=null && requestInfo.getProtocolContext()!=null && requestInfo.getProtocolContext().getInterfaceName()!=null) {
interfaceName = requestInfo.getProtocolContext().getInterfaceName();
}
if(interfaceName==null) {
throw new ProtocolException("ID Porta non presente");
}
IDPortaApplicativa idPA = new IDPortaApplicativa();
idPA.setNome(interfaceName);
pa = factory.getCachedConfigIntegrationReader(state, requestInfo).getPortaApplicativa(idPA); // pa invocata
}
/** Identificazione Mittente by LineeGuida e Token */
boolean saIdentificatoBySecurity = busta.getServizioApplicativoFruitore()!=null && !CostantiPdD.SERVIZIO_APPLICATIVO_ANONIMO.equals(busta.getServizioApplicativoFruitore());
boolean sicurezzaToken = this.context.containsKey(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_TOKEN_INFORMAZIONI_NORMALIZZATE);
boolean saIdentificatoByToken = false;
boolean saVerificatoBySecurity = false;
if(sicurezzaToken) {
IDServizioApplicativo idSAbyToken = null;
StringBuilder sbError = new StringBuilder();
try {
idSAbyToken = IdentificazioneApplicativoMittenteUtils.identificazioneApplicativoMittenteByToken(this.log, state, busta, this.context, requestInfo, msgDiag, sbError);
}catch(Exception e) {
if(sbError!=null && sbError.length()>0) {
this.context.addObject(Costanti.ERRORE_AUTORIZZAZIONE, Costanti.ERRORE_TRUE);
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.SICUREZZA_AUTORIZZAZIONE_FALLITA,
sbError.toString()));
return;
}
else {
throw e;
}
}
saIdentificatoByToken = idSAbyToken!=null;
if(saIdentificatoByToken) {
/** && !saIdentificatoBySecurity) {
L'identificazione per sicurezza, se c'è abilitata l'autenticazione per token, non dovrebbe esserci mai poichè la funzionalità è stata disabilitata.
Con autenticazione token attiva, gli applicativi anche se presente un x509 non vengono identificati dall'autenticazione https effettuata in AbstractModIValidazioneSintatticaCommons e di conseguenza in ModIValidazioneSintatticaRest e ModIValidazioneSintatticaSoap durante il trattamento del token di sicurezza
bisogna quindi verificare, se è presente un certificato x509 di firma, che corrisponda a quello registrato nell'applicativo di tipo token identificato*/
SecurityToken securityTokenForContext = SecurityTokenUtilities.readSecurityToken(this.context);
if(securityTokenForContext!=null) {
try {
if(securityTokenForContext.getAuthorization()!=null && securityTokenForContext.getAuthorization().getCertificate()!=null) {
sbError = new StringBuilder();
String tipoToken = //"Http Header "+
(securityTokenForContext.getAuthorization().getHttpHeaderName()!=null ? securityTokenForContext.getAuthorization().getHttpHeaderName() : HttpConstants.AUTHORIZATION);
IdentificazioneApplicativoMittenteUtils.checkApplicativoTokenByX509(this.log, idSAbyToken,
state, requestInfo, tipoToken, securityTokenForContext.getAuthorization().getCertificate(), sbError);
saVerificatoBySecurity = true;
}
if(securityTokenForContext.getIntegrity()!=null && securityTokenForContext.getIntegrity().getCertificate()!=null) {
sbError = new StringBuilder();
String tipoToken = //"Http Header "+
(securityTokenForContext.getIntegrity().getHttpHeaderName()!=null ? securityTokenForContext.getIntegrity().getHttpHeaderName() : this.modiProperties.getRestSecurityTokenHeaderModI());
IdentificazioneApplicativoMittenteUtils.checkApplicativoTokenByX509(this.log, idSAbyToken,
state, requestInfo, tipoToken, securityTokenForContext.getIntegrity().getCertificate(), sbError);
saVerificatoBySecurity = true;
}
if(securityTokenForContext.getEnvelope()!=null && securityTokenForContext.getEnvelope().getCertificate()!=null) {
sbError = new StringBuilder();
String tipoToken = "WSSecurity";
IdentificazioneApplicativoMittenteUtils.checkApplicativoTokenByX509(this.log, idSAbyToken,
state, requestInfo, tipoToken, securityTokenForContext.getEnvelope().getCertificate(), sbError);
saVerificatoBySecurity = true;
}
}catch(Exception e) {
if(sbError!=null && sbError.length()>0) {
this.context.addObject(Costanti.ERRORE_AUTORIZZAZIONE, Costanti.ERRORE_TRUE);
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.SICUREZZA_AUTORIZZAZIONE_FALLITA,
sbError.toString()));
return;
}
else {
throw e;
}
}
}
}
}
boolean saFruitoreAnonimo = busta.getServizioApplicativoFruitore()==null || CostantiPdD.SERVIZIO_APPLICATIVO_ANONIMO.equals(busta.getServizioApplicativoFruitore());
/** Tipi di Autorizzazione definiti */
boolean autorizzazionePerRichiedente = false;
if(pa.getAutorizzazioneToken()!=null) {
autorizzazionePerRichiedente = StatoFunzionalita.ABILITATO.equals(pa.getAutorizzazioneToken().getAutorizzazioneApplicativi());
}
if(!autorizzazionePerRichiedente && pa.getServiziApplicativiAutorizzati()!=null) {
// backward compatibility
autorizzazionePerRichiedente = pa.getServiziApplicativiAutorizzati().sizeServizioApplicativoList()>0;
}
boolean autorizzazionePerRuolo = false;
boolean checkRuoloRegistro = false;
boolean checkRuoloEsterno = false;
if(pa.getAutorizzazioneToken()!=null) {
autorizzazionePerRuolo = StatoFunzionalita.ABILITATO.equals(pa.getAutorizzazioneToken().getAutorizzazioneRuoli());
}
if(autorizzazionePerRuolo) {
if( pa.getAutorizzazioneToken().getTipologiaRuoli()==null ||
RuoloTipologia.QUALSIASI.equals(pa.getAutorizzazioneToken().getTipologiaRuoli())){
checkRuoloRegistro = true;
checkRuoloEsterno = true;
}
else if( RuoloTipologia.INTERNO.equals(pa.getAutorizzazioneToken().getTipologiaRuoli())){
checkRuoloRegistro = true;
}
else if( RuoloTipologia.ESTERNO.equals(pa.getAutorizzazioneToken().getTipologiaRuoli())){
checkRuoloEsterno = true;
}
}
/** Verifica consistenza identificazione del mittente */
if(
(
autorizzazionePerRichiedente
||
(autorizzazionePerRuolo && checkRuoloRegistro && !checkRuoloEsterno)
)
&&
saFruitoreAnonimo
){
this.context.addObject(Costanti.ERRORE_AUTORIZZAZIONE, Costanti.ERRORE_TRUE);
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.SICUREZZA_AUTORIZZAZIONE_FALLITA,
"Applicativo Mittente non identificato"));
return;
}
if(!saFruitoreAnonimo &&
(autorizzazionePerRichiedente || checkRuoloRegistro)
){
// se utilizzo l'informazione dell'applicativo, tale informazione deve essere consistente rispetto a tutti i criteri di sicurezza
if(sicurezzaMessaggio && !sicurezzaMessaggioIDAR04 &&
!saIdentificatoBySecurity && !saVerificatoBySecurity) {
this.context.addObject(Costanti.ERRORE_AUTORIZZAZIONE, Costanti.ERRORE_TRUE);
addErroreMittenteNonAutorizzato(busta, "il certificato di firma non corrisponde all'applicativo");
return;
}
if(sicurezzaToken &&
!saIdentificatoByToken) {
// CASO DEPRECATO: questo caso non puo' succedere poiche' nel caso di sicurezza token l'identificazione avviene SOLO per token
// quindi si rientra nel caso sopra 'Applicativo Mittente non identificato'
this.context.addObject(Costanti.ERRORE_AUTORIZZAZIONE, Costanti.ERRORE_TRUE);
addErroreMittenteNonAutorizzato(busta, "il claim 'clientId' presente nel token non corrisponde all'applicativo");
return;
}
}
/** Autorizzazione per Richiedente */
Eccezione eccezioneAutorizzazionePerRichiedente = null;
if(autorizzazionePerRichiedente) {
boolean autorizzato = false;
if(pa.getServiziApplicativiAutorizzati()!=null) {
for (PortaApplicativaAutorizzazioneServizioApplicativo paSA : pa.getServiziApplicativiAutorizzati().getServizioApplicativoList()) {
if(paSA.getTipoSoggettoProprietario().equals(busta.getTipoMittente()) &&
paSA.getNomeSoggettoProprietario().equals(busta.getMittente()) &&
paSA.getNome().equals(busta.getServizioApplicativoFruitore())) {
autorizzato = true;
}
}
}
if(!autorizzato) {
eccezioneAutorizzazionePerRichiedente = getErroreMittenteNonAutorizzato(busta, null);
}
}
/** Autorizzazione per Ruolo */
Eccezione eccezioneAutorizzazionePerRuolo = null;
if(autorizzazionePerRuolo) {
StringBuilder detailsBufferRuoli = new StringBuilder();
ServizioApplicativo sa = null;
if(!saFruitoreAnonimo) {
IDServizioApplicativo idSA = new IDServizioApplicativo();
idSA.setIdSoggettoProprietario(new IDSoggetto(busta.getTipoMittente(), busta.getMittente()));
idSA.setNome(busta.getServizioApplicativoFruitore());
sa = factory.getCachedConfigIntegrationReader(state,requestInfo).getServizioApplicativo(idSA);
}
boolean authRuoli = ConfigurazionePdDReader._autorizzazioneRoles(
RegistroServiziManager.getInstance(state),
null, sa,
null, false,
this.context, requestInfo,
checkRuoloRegistro, checkRuoloEsterno,
detailsBufferRuoli,
pa.getAutorizzazioneToken().getRuoli().getMatch(), pa.getAutorizzazioneToken().getRuoli(),
true);
if(!authRuoli) {
String errore = "Applicativo Mittente";
if(!saFruitoreAnonimo) {
errore = errore + " "+ busta.getServizioApplicativoFruitore() + " (Soggetto: "+busta.getMittente()+")";
}
errore = errore + " non autorizzato; ";
eccezioneAutorizzazionePerRuolo = this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.SICUREZZA_AUTORIZZAZIONE_FALLITA,
errore + detailsBufferRuoli.toString());
}
}
/** Gestione Eccezioni */
if(autorizzazionePerRichiedente && autorizzazionePerRuolo) {
if(eccezioneAutorizzazionePerRichiedente!=null && eccezioneAutorizzazionePerRuolo!=null) {
this.context.addObject(Costanti.ERRORE_AUTORIZZAZIONE, Costanti.ERRORE_TRUE);
this.erroriValidazione.add(eccezioneAutorizzazionePerRuolo); // uso eccezione per ruolo che e' più completa come messaggistica
}
// se una delle due autorizzazione e' andata a buon fine devo autorizzare
}
else {
if(eccezioneAutorizzazionePerRichiedente!=null || eccezioneAutorizzazionePerRuolo!=null) {
this.context.addObject(Costanti.ERRORE_AUTORIZZAZIONE, Costanti.ERRORE_TRUE);
if(eccezioneAutorizzazionePerRichiedente!=null) {
this.erroriValidazione.add(eccezioneAutorizzazionePerRichiedente);
}
else {
this.erroriValidazione.add(eccezioneAutorizzazionePerRuolo);
}
}
}
int sizeListaEccezioniPrimaAutorizzazione = sizeListaErroriValidazionePrimaAutorizzazione + sizeListaProcessamentoValidazionePrimaAutorizzazione;
int sizeListaEccezioniDipoAutorizzazione = this.erroriValidazione.size() + this.erroriProcessamento.size();
if(sizeListaEccezioniPrimaAutorizzazione == sizeListaEccezioniDipoAutorizzazione) {
msgDiag.logPersonalizzato(DIAGNOSTIC_VALIDATE+tipoDiagnostico+DIAGNOSTIC_COMPLETATA);
}
else {
String errore = null;
if(sizeListaErroriValidazionePrimaAutorizzazione!=this.erroriValidazione.size()) {
errore = ModIValidazioneSintattica.buildErrore(this.erroriValidazione, sizeListaErroriValidazionePrimaAutorizzazione, factory);
}
else {
errore = ModIValidazioneSintattica.buildErrore(this.erroriProcessamento, sizeListaProcessamentoValidazionePrimaAutorizzazione, factory);
}
msgDiag.addKeyword(CostantiPdD.KEY_ERRORE_PROCESSAMENTO, errore);
msgDiag.logPersonalizzato(DIAGNOSTIC_VALIDATE+tipoDiagnostico+DIAGNOSTIC_FALLITA);
}
autorizzazione = false;
} // fine autorizzazione
}catch(Exception e){
if(msgDiag!=null && (verifica || autorizzazione)) {
msgDiag.addKeyword(CostantiPdD.KEY_ERRORE_PROCESSAMENTO, e.getMessage());
msgDiag.logPersonalizzato(DIAGNOSTIC_VALIDATE+tipoDiagnostico+DIAGNOSTIC_FALLITA);
}
this.erroriProcessamento.add(this.validazioneUtils.newEccezioneProcessamento(CodiceErroreCooperazione.ERRORE_GENERICO_PROCESSAMENTO_MESSAGGIO,
e.getMessage(),e));
}
}
private boolean isAudienceValid(String audienceAtteso, String audience, List<String> listAudience) {
boolean checkAudience = false;
if(audienceAtteso!=null) {
checkAudience = audienceAtteso.equals(audience);
if(!checkAudience && listAudience!=null && !listAudience.isEmpty()) {
for (String check : listAudience) {
if(audienceAtteso.equals(check)) {
checkAudience = true;
break;
}
}
}
}
return checkAudience;
}
private void checkExp(String exp, Date now, boolean rest, String prefix) throws ProtocolException {
boolean enabled = true;
if(rest) {
enabled = this.modiProperties.isRestSecurityTokenClaimsExpTimeCheck();
}
else {
enabled = this.modiProperties.isSoapSecurityTokenTimestampExpiresTimeCheck();
}
if(!enabled) {
return;
}
if(prefix==null) {
prefix="";
}
Date dateExp = null;
try {
dateExp = DateUtils.getSimpleDateFormatMs().parse(exp);
}catch(Exception e) {
throw new ProtocolException(e.getMessage(),e);
}
/*
* The "exp" (expiration time) claim identifies the expiration time on
* or after which the JWT MUST NOT be accepted for processing. The
* processing of the "exp" claim requires that the current date/time
* MUST be before the expiration date/time listed in the "exp" claim.
**/
Date checkNow = now;
Long tolerance = null;
if(rest) {
tolerance = this.modiProperties.getRestSecurityTokenClaimsExpTimeCheckToleranceMilliseconds();
}
else {
tolerance = this.modiProperties.getSoapSecurityTokenTimestampExpiresTimeCheckToleranceMilliseconds();
}
if(tolerance!=null && tolerance.longValue()>0) {
checkNow = new Date(now.getTime() - tolerance.longValue());
}
if(!checkNow.before(dateExp)){
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.MESSAGGIO_SCADUTO,
prefix+"Token scaduto in data '"+exp+"'"));
}
}
private void checkNbf(String nbf, Date now, String prefix) throws ProtocolException {
if(prefix==null) {
prefix="";
}
Date dateNbf = null;
try {
dateNbf = DateUtils.getSimpleDateFormatMs().parse(nbf);
}catch(Exception e) {
throw new ProtocolException(e.getMessage(),e);
}
/*
* The "nbf" (not before) claim identifies the time before which the JWT
* MUST NOT be accepted for processing. The processing of the "nbf"
* claim requires that the current date/time MUST be after or equal to
* the not-before date/time listed in the "nbf" claim.
**/
if(!dateNbf.before(now)){
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.MESSAGGIO_SCADUTO,
prefix+"Token non utilizzabile prima della data '"+nbf+"'"));
}
}
private void checkIat(String iat, OpenSPCoop2Message msg, boolean rest, String prefix) throws ProtocolException {
if(prefix==null) {
prefix="";
}
Date dateIat = null;
try {
dateIat = DateUtils.getSimpleDateFormatMs().parse(iat);
}catch(Exception e) {
throw new ProtocolException(e.getMessage(),e);
}
/*
* The "iat" (issued at) claim identifies the time at which the JWT was
* issued. This claim can be used to determine the age of the JWT.
* The iat Claim can be used to reject tokens that were issued too far away from the current time,
* limiting the amount of time that nonces need to be stored to prevent attacks. The acceptable range is Client specific.
**/
Long old = null;
Object iatObject = null;
if(msg!=null) {
iatObject = msg.getContextProperty(ModICostanti.MODIPA_OPENSPCOOP2_MSG_CONTEXT_IAT_TTL_CHECK);
}
if(iatObject instanceof Long) {
old = (Long) iatObject;
}
if(old==null) {
if(rest) {
old = this.modiProperties.getRestSecurityTokenClaimsIatTimeCheckMilliseconds();
}
else {
old = this.modiProperties.getSoapSecurityTokenTimestampCreatedTimeCheckMilliseconds();
}
}
if(old!=null) {
Date oldMax = new Date((DateManager.getTimeMillis() - old.longValue()));
if(dateIat.before(oldMax)) {
logError(prefix+"Token creato da troppo tempo (data creazione: '"+iat+"', data più vecchia consentita: '"+DateUtils.getSimpleDateFormatMs().format(oldMax)+"', configurazione ms: '"+old.longValue()+"')");
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.MESSAGGIO_SCADUTO,
prefix+"Token creato da troppo tempo (data creazione: '"+iat+"')"));
}
}
checkIatFuture(dateIat, prefix, iat, rest);
}
private void checkIatFuture(Date dateIat, String prefix, String iat, boolean rest) throws ProtocolException {
Long future = null;
if(rest) {
future = this.modiProperties.getRestSecurityTokenClaimsIatTimeCheckFutureToleranceMilliseconds();
}
else {
future = this.modiProperties.getSoapSecurityTokenTimestampCreatedTimeCheckFutureToleranceMilliseconds();
}
if(future!=null) {
Date futureMax = new Date((DateManager.getTimeMillis() + future.longValue()));
if(dateIat.after(futureMax)) {
logError(prefix+"Token creato nel futuro (data creazione: '"+iat+"', data massima futura consentita: '"+DateUtils.getSimpleDateFormatMs().format(futureMax)+"', configurazione ms: '"+future.longValue()+"')");
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(CodiceErroreCooperazione.ORA_REGISTRAZIONE_NON_VALIDA,
prefix+"Token creato nel futuro (data creazione: '"+iat+"')"));
}
}
}
private void validatePurposeId(RemoteStoreConfig rsc, String prefixAudit, String securityAuditPattern) throws ProtocolException {
try {
if(rsc!=null &&
(this.modiProperties.isSecurityTokenAuditExpectedPurposeId() || this.modiProperties.isSecurityTokenAuditCompareAuthorizationPurposeId())) {
SecurityToken securityToken = ModIUtilities.readSecurityToken(this.context);
if(securityToken==null) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_NON_PRESENTE,
"Token di sicurezza non presenti"));
return;
}
RestMessageSecurityToken restSecurityToken = securityToken.getAccessToken();
String prefixAuthorization = getPrefixHeader(HttpConstants.AUTHORIZATION);
String labelAuditPattern = CostantiDB.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_PATTERN_AUDIT_REST_02.equals(securityAuditPattern) ?
CostantiLabel.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_PATTERN_AUDIT_REST_02 : CostantiLabel.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_PATTERN_AUDIT_REST_01;
String suffixAudit02 = " (richiesto con pattern '"+labelAuditPattern+"')";
if(restSecurityToken==null) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_NON_PRESENTE,
prefixAuthorization+MSG_ERRORE_NON_PRESENTE+suffixAudit02));
return;
}
RestMessageSecurityToken auditToken = securityToken.getAudit();
if(auditToken==null) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_NON_PRESENTE,
prefixAudit+MSG_ERRORE_NON_PRESENTE));
return;
}
boolean expected = this.modiProperties.isSecurityTokenAuditExpectedPurposeId();
String purposeIdAuthorization = readPurposeId(restSecurityToken, prefixAuthorization, expected);
String purposeIdAudit = readPurposeId(auditToken, prefixAudit, expected);
if(this.modiProperties.isSecurityTokenAuditCompareAuthorizationPurposeId() &&
purposeIdAuthorization!=null && purposeIdAudit!=null && !purposeIdAuthorization.equals(purposeIdAudit)) {
String claim = org.openspcoop2.pdd.core.token.Costanti.PDND_PURPOSE_ID;
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_NON_PRESENTE,
prefixAudit+"Claim '"+claim+"' presente nel token contiene un valore '"+purposeIdAudit+"' differente da quello presente nel token "+HttpConstants.AUTHORIZATION+" ("+purposeIdAuthorization+")"));
}
}
}catch(Exception e) {
throw new ProtocolException(e.getMessage(),e);
}
}
private String readPurposeId(RestMessageSecurityToken restSecurityToken, String prefixAuthorization, boolean required) throws ProtocolException {
String purposeId = null;
String purposeIdClaim = org.openspcoop2.pdd.core.token.Costanti.PDND_PURPOSE_ID;
try {
purposeId = restSecurityToken.getPayloadClaim(purposeIdClaim);
if( (purposeId==null || StringUtils.isEmpty(purposeId)) && required ) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_VALIDO,
prefixAuthorization+getErroreClaimNonPresente(purposeIdClaim)));
}
}catch(Exception e) {
logError("Lettura purpose id token fallita: "+e.getMessage(),e);
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_VALIDO,
prefixAuthorization+getErroreClaimNonValido(purposeIdClaim)));
}
return purposeId;
}
private void validateAudit02(String securityMessageProfileSorgenteTokenIdAuth, boolean rest, String prefixAudit) throws ProtocolException {
boolean expectedAccessToken = false;
if(ModICostanti.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_SORGENTE_TOKEN_IDAUTH_VALUE_PDND.equals(securityMessageProfileSorgenteTokenIdAuth) ||
ModICostanti.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_SORGENTE_TOKEN_IDAUTH_VALUE_OAUTH.equals(securityMessageProfileSorgenteTokenIdAuth)) {
expectedAccessToken = true;
}
SecurityToken securityToken = ModIUtilities.readSecurityToken(this.context);
if(securityToken==null) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_NON_PRESENTE,
"Token di sicurezza non presenti"));
return;
}
RestMessageSecurityToken restSecurityToken = null;
if(expectedAccessToken) {
restSecurityToken = securityToken.getAccessToken();
}
else {
if(rest) {
restSecurityToken = securityToken.getAuthorization();
}
else {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_VALIDO,
"Token di sicurezza IDAuth Locale su API Soap non è utilizzabile con pattern "+CostantiLabel.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_PATTERN_AUDIT_REST_02));
return;
}
}
String prefixAuthorization = getPrefixHeader(HttpConstants.AUTHORIZATION);
String suffixAudit02 = " (richiesto con pattern '"+CostantiLabel.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_PATTERN_AUDIT_REST_02+"')";
if(restSecurityToken==null) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_NON_PRESENTE,
prefixAuthorization+MSG_ERRORE_NON_PRESENTE+suffixAudit02));
return;
}
String digestClaimPrefix = org.openspcoop2.pdd.core.token.Costanti.PDND_DIGEST+".";
String digestAlgo = readDigestAlgorithm(digestClaimPrefix, restSecurityToken, prefixAuthorization);
String digestValue = readDigestValue(digestClaimPrefix, restSecurityToken, prefixAuthorization);
if(digestAlgo==null || digestValue==null) {
return; // errori gestiti nei metodi sopra
}
RestMessageSecurityToken auditSecurityToken = securityToken.getAudit();
if(auditSecurityToken==null || auditSecurityToken.getToken()==null || StringUtils.isEmpty(auditSecurityToken.getToken())) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_PRESENTE,
prefixAudit+MSG_ERRORE_NON_PRESENTE));
return;
}
// calcolo digest value token audit
String digestAuditRicalcolato = null;
try {
digestAuditRicalcolato = org.openspcoop2.utils.digest.DigestUtils.getDigestValue(auditSecurityToken.getToken().getBytes(), digestAlgo, DigestEncoding.HEX,
false); // se rfc3230 true aggiunge prefisso algoritmo=
}catch(Exception e) {
logError("Calcolo digest del token di audit fallito: "+e.getMessage(),e);
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA,
prefixAudit+"check digest failed"));
return;
}
if(!digestValue.equalsIgnoreCase(digestAuditRicalcolato)) {
String digestValueClaim = digestClaimPrefix+org.openspcoop2.pdd.core.token.Costanti.PDND_DIGEST_VALUE;
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_VALIDO,
prefixAuthorization+"possiede un valore nel campo '"+digestValueClaim+"' non corrispondente al token di audit previsto dal pattern '"+CostantiLabel.MODIPA_PROFILO_SICUREZZA_MESSAGGIO_CORNICE_SICUREZZA_PATTERN_AUDIT_REST_02+"'"));
}
}
private String readDigestAlgorithm(String digestClaimPrefix, RestMessageSecurityToken restSecurityToken, String prefixAuthorization) throws ProtocolException {
String digestAlgo = null;
String digestAlgClaim = digestClaimPrefix+org.openspcoop2.pdd.core.token.Costanti.PDND_DIGEST_ALG;
try {
digestAlgo = restSecurityToken.getPayloadClaim(digestAlgClaim);
if(digestAlgo==null || StringUtils.isEmpty(digestAlgo)) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_VALIDO,
prefixAuthorization+getErroreClaimNonPresente(digestAlgClaim)));
}
}catch(Exception e) {
logError("Lettura algoritmo di digest in authorization token fallita: "+e.getMessage(),e);
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_VALIDO,
prefixAuthorization+getErroreClaimNonValido(digestAlgClaim)));
}
return digestAlgo;
}
private String readDigestValue(String digestClaimPrefix, RestMessageSecurityToken restSecurityToken, String prefixAuthorization) throws ProtocolException {
String digestValue = null;
String digestValueClaim = digestClaimPrefix+org.openspcoop2.pdd.core.token.Costanti.PDND_DIGEST_VALUE;
try {
digestValue = restSecurityToken.getPayloadClaim(digestValueClaim);
if(digestValue==null || StringUtils.isEmpty(digestValue)) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_VALIDO,
prefixAuthorization+getErroreClaimNonPresente(digestValueClaim)));
}
}catch(Exception e) {
logError("Lettura valore del digest audit in authorization token fallita: "+e.getMessage(),e);
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.SICUREZZA_TOKEN_NON_VALIDO,
prefixAuthorization+getErroreClaimNonValido(digestValueClaim)));
}
return digestValue;
}
private void validateTokenAuthorizationId(OpenSPCoop2Message msg,
String prefixAuthorization,
ModIValidazioneSemanticaProfiloSicurezza modIValidazioneSemanticaProfiloSicurezza) throws ProtocolException {
boolean useJtiAuthorization = ModIUtils.useJtiAuthorizationObject(msg);
if(useJtiAuthorization) {
String jtiClaimReceived = TokenUtilities.readJtiFromInformazioniToken(this.context);
if(jtiClaimReceived==null || StringUtils.isEmpty(jtiClaimReceived)) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
CodiceErroreCooperazione.IDENTIFICATIVO_MESSAGGIO_NON_PRESENTE,
prefixAuthorization+getErroreClaimNonPresente(Claims.JSON_WEB_TOKEN_RFC_7519_JWT_ID)));
}
else {
if(modIValidazioneSemanticaProfiloSicurezza!=null) {
// nop
}
/** SPOSTATO IN RICEZIONE BUSTE per generare il corretto idMessaggio */
/**ModIUtils.replaceBustaIdWithJtiTokenId(modIValidazioneSemanticaProfiloSicurezza, jtiClaimReceived);*/
}
}
}
private PortaApplicativa validateTokenAuthorizationAudience(OpenSPCoop2Message msg, IProtocolFactory<?> factory, IState state, RequestInfo requestInfo,
boolean isRichiesta, String prefixAuthorization,
boolean checkAudienceByModIConfig) throws ProtocolException {
PortaApplicativa pa = readPortaApplicativa(msg, factory, state, requestInfo);
boolean audienceCheckDefinedInAuthorizationTokenClaims = isAudienceCheckDefinedInAuthorizationTokenClaims(pa);
if(!audienceCheckDefinedInAuthorizationTokenClaims) {
validateTokenAuthorizationAudienceByModIConfig(msg, factory, state, requestInfo,
isRichiesta, prefixAuthorization,
checkAudienceByModIConfig);
}
return pa;
}
private void validateTokenAuthorizationAudienceByModIConfig(OpenSPCoop2Message msg, IProtocolFactory<?> factory, IState state, RequestInfo requestInfo,
boolean isRichiesta, String prefixAuthorization,
boolean checkAudienceByModIConfig) throws ProtocolException {
List<String> audienceClaimReceived = readAudienceFromTokenOAuth();
if(audienceClaimReceived==null || audienceClaimReceived.isEmpty()) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
isRichiesta ? CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_EROGATORE_NON_PRESENTE :
CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_FRUITORE_NON_PRESENTE,
prefixAuthorization+getErroreClaimNonPresente(Claims.JSON_WEB_TOKEN_RFC_7519_AUDIENCE)));
}
else {
if(checkAudienceByModIConfig) {
checkAudienceModIConfig(msg, factory, state, requestInfo,
isRichiesta, prefixAuthorization,
audienceClaimReceived);
}
else {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
isRichiesta ? CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_EROGATORE_NON_VALIDO :
CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_FRUITORE_NON_VALIDO,
prefixAuthorization+"Token contenente un claim '"+Claims.JSON_WEB_TOKEN_RFC_7519_AUDIENCE+"' non verificabile; autorizzazione per token claim non definita"));
}
}
}
private PortaApplicativa readPortaApplicativa(OpenSPCoop2Message msg, IProtocolFactory<?> factory, IState state, RequestInfo requestInfo) throws ProtocolException {
PortaApplicativa pa = null;
String interfaceName = null;
if(msg!=null && msg.getTransportRequestContext()!=null && msg.getTransportRequestContext().getInterfaceName()!=null) {
interfaceName = msg.getTransportRequestContext().getInterfaceName();
}
else if(requestInfo!=null && requestInfo.getProtocolContext()!=null && requestInfo.getProtocolContext().getInterfaceName()!=null) {
interfaceName = requestInfo.getProtocolContext().getInterfaceName();
}
if(interfaceName==null) {
throw new ProtocolException("ID Porta non presente");
}
IDPortaApplicativa idPA = new IDPortaApplicativa();
idPA.setNome(interfaceName);
try {
pa = factory.getCachedConfigIntegrationReader(state, requestInfo).getPortaApplicativa(idPA); // pa invocata
}catch(Exception e) {
throw new ProtocolException(e.getMessage(),e);
}
return pa;
}
private PortaApplicativa readPortaApplicativaDefault(OpenSPCoop2Message msg, IProtocolFactory<?> factory, IState state, RequestInfo requestInfo) throws ProtocolException {
PortaApplicativa paDefault = null;
if(msg!=null) {
Object nomePortaInvocataObject = msg.getContextProperty(CostantiPdD.NOME_PORTA_INVOCATA);
String nomePorta = null;
if(nomePortaInvocataObject instanceof String) {
nomePorta = (String) nomePortaInvocataObject;
}
if(nomePorta==null && this.context!=null && this.context.containsKey(CostantiPdD.NOME_PORTA_INVOCATA)) {
nomePorta = (String) this.context.getObject(CostantiPdD.NOME_PORTA_INVOCATA);
}
if(nomePorta==null && requestInfo!=null && requestInfo.getProtocolContext()!=null && requestInfo.getProtocolContext().getInterfaceName()!=null) {
nomePorta = requestInfo.getProtocolContext().getInterfaceName(); // se non e' presente 'NOME_PORTA_INVOCATA' significa che non e' stato invocato un gruppo specifico
}
if(nomePorta!=null) {
IDPortaApplicativa idPA = new IDPortaApplicativa();
idPA.setNome(nomePorta);
try {
paDefault = factory.getCachedConfigIntegrationReader(state, requestInfo).getPortaApplicativa(idPA);
}catch(Exception e) {
throw new ProtocolException(e.getMessage(),e);
}
}
else {
throw new ProtocolException("ID Porta 'default' non presente");
}
}
return paDefault;
}
private boolean isAudienceCheckDefinedInAuthorizationTokenClaims(PortaApplicativa pa) throws ProtocolException {
boolean audienceCheckDefinedInAuthorizationTokenClaims = false;
if(pa.getGestioneToken()!=null && pa.getGestioneToken().getOptions()!=null) {
SortedMap<List<String>> properties = null;
try {
properties = PropertiesUtilities.convertTextToSortedListMap(pa.getGestioneToken().getOptions());
}catch(Exception e) {
throw new ProtocolException(e.getMessage(),e);
}
if(properties!=null && properties.size()>0 && properties.containsKey(Claims.JSON_WEB_TOKEN_RFC_7519_AUDIENCE)) {
audienceCheckDefinedInAuthorizationTokenClaims = true; // la verifica viene fatta nell'autorizzazione per token claims
}
}
return audienceCheckDefinedInAuthorizationTokenClaims;
}
private List<String> readAudienceFromTokenOAuth() {
Object oInformazioniTokenNormalizzate = null;
if(this.context!=null) {
oInformazioniTokenNormalizzate = this.context.getObject(org.openspcoop2.pdd.core.token.Costanti.PDD_CONTEXT_TOKEN_INFORMAZIONI_NORMALIZZATE);
}
InformazioniToken informazioniTokenNormalizzate = null;
List<String> audienceClaimReceived = null;
if(oInformazioniTokenNormalizzate!=null) {
informazioniTokenNormalizzate = (InformazioniToken) oInformazioniTokenNormalizzate;
audienceClaimReceived = informazioniTokenNormalizzate.getAud();
}
return audienceClaimReceived;
}
private void checkAudienceModIConfig(OpenSPCoop2Message msg, IProtocolFactory<?> factory, IState state, RequestInfo requestInfo,
boolean isRichiesta, String prefixAuthorization,
List<String> audienceClaimReceived) throws ProtocolException {
PortaApplicativa paDefault = readPortaApplicativaDefault(msg, factory, state, requestInfo);
/**System.out.println("VERIFICO RISPETTO AL VALORE ATTESO '"+modISecurityConfig.getAudience()+"'");*/
checkAudienceModIConfig(msg, state, requestInfo,
isRichiesta, prefixAuthorization,
paDefault,
audienceClaimReceived);
}
private void checkAudienceModIConfig(OpenSPCoop2Message msg, IState state, RequestInfo requestInfo,
boolean isRichiesta, String prefixAuthorization,
PortaApplicativa paDefault,
List<String> audienceClaimReceived) throws ProtocolException {
ModISecurityConfig modISecurityConfig = new ModISecurityConfig(msg, this.protocolFactory, state,requestInfo,
!isRichiesta, // fruizione,
isRichiesta, // request,
paDefault);
boolean find = false;
for (String claim : audienceClaimReceived) {
if(claim.equalsIgnoreCase(modISecurityConfig.getAudience())) {
find = true;
break;
}
}
if(!find) {
this.erroriValidazione.add(this.validazioneUtils.newEccezioneValidazione(
isRichiesta ? CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_EROGATORE_NON_VALIDO :
CodiceErroreCooperazione.SERVIZIO_APPLICATIVO_FRUITORE_NON_VALIDO,
prefixAuthorization+getErroreClaimNonValido(Claims.JSON_WEB_TOKEN_RFC_7519_AUDIENCE)));
}
}
private void logError(String msg) {
if(this.log!=null) {
this.log.error(msg);
}
}
private void logError(String msg, Exception e) {
if(this.log!=null) {
this.log.error(msg,e);
}
}
}