MessageSecurityReceiver_xml.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.message.xml;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import org.openspcoop2.message.OpenSPCoop2Message;
import org.openspcoop2.message.OpenSPCoop2RestMessage;
import org.openspcoop2.message.OpenSPCoop2RestXmlMessage;
import org.openspcoop2.message.constants.MessageType;
import org.openspcoop2.message.constants.ServiceBinding;
import org.openspcoop2.protocol.sdk.Busta;
import org.openspcoop2.protocol.sdk.constants.CodiceErroreCooperazione;
import org.openspcoop2.security.SecurityException;
import org.openspcoop2.security.message.AbstractRESTMessageSecurityReceiver;
import org.openspcoop2.security.message.MessageSecurityContext;
import org.openspcoop2.security.message.constants.SecurityConstants;
import org.openspcoop2.security.message.utils.EncryptionBean;
import org.openspcoop2.security.message.utils.KeystoreUtils;
import org.openspcoop2.security.message.utils.SignatureBean;
import org.openspcoop2.utils.Utilities;
import org.openspcoop2.utils.certificate.KeyStore;
import org.openspcoop2.utils.security.SymmetricKeyWrappedMode;
import org.openspcoop2.utils.security.VerifyXmlSignature;
import org.openspcoop2.utils.security.XmlDecrypt;
import org.w3c.dom.Element;
/**
* Classe per la gestione della WS-Security (WSDoAllReceiver).
*
* @author Lorenzo Nardi (nardi@link.it)
* @author $Author$
* @version $Rev$, $Date$
*
*/
public class MessageSecurityReceiver_xml extends AbstractRESTMessageSecurityReceiver {
private VerifyXmlSignature xmlVerifierSignature = null;
private XmlDecrypt xmlDecrypt = null;
@Override
public void process(MessageSecurityContext messageSecurityContext,OpenSPCoop2Message messageParam,Busta busta,org.openspcoop2.utils.Map<Object> ctx) throws SecurityException{
boolean signatureProcess = false;
boolean encryptProcess = false;
try{
if(ServiceBinding.REST.equals(messageParam.getServiceBinding())==false){
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with REST Binding");
}
if(MessageType.XML.equals(messageParam.getMessageType())==false) {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with REST Binding and a xml message, found: "+messageParam.getMessageType());
}
OpenSPCoop2RestXmlMessage restXmlMessage = messageParam.castAsRestXml();
// ********** Leggo operazioni ***************
boolean encrypt = false;
boolean signature = false;
String[]actions = ((String)messageSecurityContext.getIncomingProperties().get(SecurityConstants.ACTION)).split(" ");
for (int i = 0; i < actions.length; i++) {
if(SecurityConstants.isActionEncryption(actions[i].trim()) || SecurityConstants.isActionDecryption(actions[i].trim())){
encrypt = true;
}
else if(SecurityConstants.SIGNATURE_ACTION.equals(actions[i].trim())){
signature = true;
}
else {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+"; action '"+actions[i]+"' unsupported");
}
}
if(encrypt && signature) {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with one function beetwen encrypt or signature");
}
if(!encrypt && !signature) {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" require one function beetwen encrypt or signature");
}
if(signature) {
// **************** Leggo parametri signature store **************************
SignatureBean bean = null;
try {
bean = KeystoreUtils.getReceiverSignatureBean(messageSecurityContext,ctx);
}catch(Exception e) {
throw e;
}
KeyStore signatureKS = bean.getKeystore();
KeyStore signatureTrustStoreKS = bean.getTruststore();
String aliasSignatureUser = bean.getUser();
if(signatureKS==null && signatureTrustStoreKS==null) {
throw new SecurityException(XMLCostanti.XML_ENGINE_VERIFIER_SIGNATURE_DESCRIPTION+" require truststore");
}
if(aliasSignatureUser==null) {
throw new SecurityException(XMLCostanti.XML_ENGINE_VERIFIER_SIGNATURE_DESCRIPTION+" require alias certificate");
}
if(signatureTrustStoreKS!=null) {
this.xmlVerifierSignature = new VerifyXmlSignature(signatureTrustStoreKS, aliasSignatureUser);
}
else {
this.xmlVerifierSignature = new VerifyXmlSignature(signatureKS, aliasSignatureUser);
}
// **************** Process **************************
signatureProcess = true; // le eccezioni lanciate da adesso sono registrato con codice relative alla verifica
boolean verify = this.xmlVerifierSignature.verify(restXmlMessage.getContent(),false);
if(!verify) {
throw new Exception("Signature verification failed");
}
} // fine signature
else if(encrypt) {
// **************** Leggo parametri encryption store **************************
EncryptionBean bean = null;
try {
bean = KeystoreUtils.getReceiverEncryptionBean(messageSecurityContext,ctx);
}catch(Exception e) {
throw e;
}
KeyStore encryptionKS = bean.getKeystore();
boolean encryptionSymmetric = bean.isEncryptionSimmetric();
SymmetricKeyWrappedMode encryptionSymmetricWrappedMode = null;
if(encryptionSymmetric) {
encryptionSymmetricWrappedMode = SymmetricKeyWrappedMode.SYM_ENC_KEY_WRAPPED_SYMMETRIC_KEY;
}
else {
encryptionSymmetricWrappedMode = SymmetricKeyWrappedMode.SYM_ENC_KEY_WRAPPED_ASYMMETRIC_KEY;
}
String aliasEncryptUser = bean.getUser();
String aliasEncryptPassword = bean.getPassword();
if(encryptionSymmetric) {
String encryptionSymmetricWrapped = (String) messageSecurityContext.getIncomingProperties().get(SecurityConstants.DECRYPTION_SYMMETRIC_WRAPPED);
if(encryptionSymmetricWrapped!=null) {
if(SecurityConstants.DECRYPTION_SYMMETRIC_WRAPPED_TRUE.equalsIgnoreCase(encryptionSymmetricWrapped)) {
encryptionSymmetricWrappedMode = SymmetricKeyWrappedMode.SYM_ENC_KEY_WRAPPED_SYMMETRIC_KEY;
}
else if(SecurityConstants.DECRYPTION_SYMMETRIC_WRAPPED_FALSE.equalsIgnoreCase(encryptionSymmetricWrapped)) {
encryptionSymmetricWrappedMode = SymmetricKeyWrappedMode.SYM_ENC_KEY_NO_WRAPPED;
}
}
}
if(encryptionKS==null) {
throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require keystore");
}
if(aliasEncryptUser==null) {
if(encryptionSymmetric) {
throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require alias secret key");
}
else {
throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require alias private key");
}
}
if(aliasEncryptPassword==null) {
if(encryptionSymmetric) {
throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require password secret key");
}
else {
throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require password private key");
}
}
this.xmlDecrypt = new XmlDecrypt(encryptionKS, encryptionSymmetric, encryptionSymmetricWrappedMode, aliasEncryptUser, aliasEncryptPassword);
boolean detach = true;
String encryptionSymmetricWrapped = (String) messageSecurityContext.getIncomingProperties().get(SecurityConstants.DETACH_SECURITY_INFO);
if(encryptionSymmetricWrapped!=null) {
if(SecurityConstants.FALSE.equalsIgnoreCase(encryptionSymmetricWrapped)) {
detach = false;
}
}
Element xmlEncrypted = null;
if(!detach) {
xmlEncrypted = (Element) restXmlMessage.getContent().cloneNode(true);
}
// **************** Process **************************
encryptProcess = true; // le eccezioni lanciate da adesso sono registrato con codice relative alla verifica
if(detach) {
this.xmlDecrypt.decrypt(restXmlMessage.getContent());
}
else {
this.xmlDecrypt.decrypt(xmlEncrypted);
}
} // fine encrypt
} catch (Exception e) {
SecurityException secException = new SecurityException(e.getMessage(), e);
/* **** MESSAGGIO ***** */
String msg = Utilities.getInnerNotEmptyMessageException(e).getMessage();
Throwable innerExc = Utilities.getLastInnerException(e);
String innerMsg = null;
if(innerExc!=null){
innerMsg = innerExc.getMessage();
}
String messaggio = null;
if(msg!=null){
messaggio = new String(msg);
if(innerMsg!=null && !innerMsg.equals(msg)){
messaggio = messaggio + " ; " + innerMsg;
}
}
else{
if(innerMsg!=null){
messaggio = innerMsg;
}
}
secException.setMsgErrore(messaggio);
/* ***** CODICE **** */
if(signatureProcess){
secException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA_FIRMA_NON_VALIDA);
}
else if(encryptProcess){
secException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA_CIFRATURA_NON_VALIDA);
}
else {
secException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA);
}
throw secException;
}
}
@Override
public void detachSecurity(MessageSecurityContext messageSecurityContext, OpenSPCoop2RestMessage<?> messageParam)
throws SecurityException {
try {
if(ServiceBinding.REST.equals(messageParam.getServiceBinding())==false){
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with REST Binding");
}
if(MessageType.XML.equals(messageParam.getMessageType())==false) {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with REST Binding and a xml message, found: "+messageParam.getMessageType());
}
OpenSPCoop2RestXmlMessage restXmlMessage = messageParam.castAsRestXml();
if(this.xmlVerifierSignature!=null) {
this.xmlVerifierSignature.detach(restXmlMessage.getContent());
}
else if(this.xmlDecrypt!=null) {
// nop: giĆ fatto prima
}
else {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (detach method) usable only after one function beetwen encrypt or signature");
}
}catch(Exception e) {
throw new SecurityException(e.getMessage(), e);
}
}
@Override
public String getCertificate() throws SecurityException {
try {
if(this.xmlVerifierSignature!=null) {
if( this.xmlVerifierSignature.getKeyInfo()!=null ) {
// X509
if( this.xmlVerifierSignature.getKeyInfo().getX509Certificate()!=null && this.xmlVerifierSignature.getKeyInfo().getX509Certificate().getIssuerX500Principal()!=null ) {
return this.xmlVerifierSignature.getKeyInfo().getX509Certificate().getIssuerX500Principal().getName();
}
// RSA
if( this.xmlVerifierSignature.getKeyInfo().getPublicKey()!=null) {
// non c'e' una stringa da tornare
}
}
return null;
}
else if(this.xmlDecrypt!=null) {
return null;
}
else {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (getCertificate method) usable only after one function beetwen encrypt or signature");
}
}catch(Exception e) {
throw new SecurityException(e.getMessage(), e);
}
}
@Override
public X509Certificate getX509Certificate() throws SecurityException {
try {
if(this.xmlVerifierSignature!=null) {
if( this.xmlVerifierSignature.getKeyInfo()!=null ) {
// X509
if( this.xmlVerifierSignature.getKeyInfo().getX509Certificate()!=null && this.xmlVerifierSignature.getKeyInfo().getX509Certificate().getIssuerX500Principal()!=null ) {
return this.xmlVerifierSignature.getKeyInfo().getX509Certificate();
}
}
return null;
}
else if(this.xmlDecrypt!=null) {
return null;
}
else {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (getCertificate method) usable only after one function beetwen encrypt or signature");
}
}catch(Exception e) {
throw new SecurityException(e.getMessage(), e);
}
}
@Override
public PublicKey getPublicKey() throws SecurityException {
try {
if(this.xmlVerifierSignature!=null) {
if( this.xmlVerifierSignature.getKeyInfo()!=null ) {
// RSA
if( this.xmlVerifierSignature.getKeyInfo().getPublicKey()!=null) {
return this.xmlVerifierSignature.getKeyInfo().getPublicKey();
}
}
return null;
}
else if(this.xmlDecrypt!=null) {
return null;
}
else {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (getCertificate method) usable only after one function beetwen encrypt or signature");
}
}catch(Exception e) {
throw new SecurityException(e.getMessage(), e);
}
}
@Override
public String getCertificateId() throws SecurityException {
try {
if(this.xmlVerifierSignature!=null) {
if( this.xmlVerifierSignature.getKeyInfo()!=null ) {
// RSA
if( this.xmlVerifierSignature.getKeyInfo().getId()!=null) {
return this.xmlVerifierSignature.getKeyInfo().getId();
}
}
return null;
}
else if(this.xmlDecrypt!=null) {
return null;
}
else {
throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (getCertificate method) usable only after one function beetwen encrypt or signature");
}
}catch(Exception e) {
throw new SecurityException(e.getMessage(), e);
}
}
}