MessageSecurityReceiver_xml.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */


  20. package org.openspcoop2.security.message.xml;

  21. import java.security.PublicKey;
  22. import java.security.cert.X509Certificate;

  23. import org.openspcoop2.message.OpenSPCoop2Message;
  24. import org.openspcoop2.message.OpenSPCoop2RestMessage;
  25. import org.openspcoop2.message.OpenSPCoop2RestXmlMessage;
  26. import org.openspcoop2.message.constants.MessageType;
  27. import org.openspcoop2.message.constants.ServiceBinding;
  28. import org.openspcoop2.protocol.sdk.Busta;
  29. import org.openspcoop2.protocol.sdk.constants.CodiceErroreCooperazione;
  30. import org.openspcoop2.security.SecurityException;
  31. import org.openspcoop2.security.message.AbstractRESTMessageSecurityReceiver;
  32. import org.openspcoop2.security.message.MessageSecurityContext;
  33. import org.openspcoop2.security.message.constants.SecurityConstants;
  34. import org.openspcoop2.security.message.utils.EncryptionBean;
  35. import org.openspcoop2.security.message.utils.KeystoreUtils;
  36. import org.openspcoop2.security.message.utils.SignatureBean;
  37. import org.openspcoop2.utils.Utilities;
  38. import org.openspcoop2.utils.certificate.KeyStore;
  39. import org.openspcoop2.utils.security.SymmetricKeyWrappedMode;
  40. import org.openspcoop2.utils.security.VerifyXmlSignature;
  41. import org.openspcoop2.utils.security.XmlDecrypt;
  42. import org.w3c.dom.Element;



  43. /**
  44.  * Classe per la gestione della WS-Security (WSDoAllReceiver).
  45.  *
  46.  * @author Lorenzo Nardi (nardi@link.it)
  47.  * @author $Author$
  48.  * @version $Rev$, $Date$
  49.  *
  50.  */
  51. public class MessageSecurityReceiver_xml extends AbstractRESTMessageSecurityReceiver {

  52.     private VerifyXmlSignature xmlVerifierSignature = null;
  53.     private XmlDecrypt xmlDecrypt = null;

  54.     @Override
  55.     public void process(MessageSecurityContext messageSecurityContext,OpenSPCoop2Message messageParam,Busta busta,org.openspcoop2.utils.Map<Object> ctx) throws SecurityException{
  56.        
  57.         boolean signatureProcess = false;
  58.         boolean encryptProcess = false;
  59.         try{
  60.            
  61.             if(ServiceBinding.REST.equals(messageParam.getServiceBinding())==false){
  62.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with REST Binding");
  63.             }
  64.             if(MessageType.XML.equals(messageParam.getMessageType())==false) {
  65.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with REST Binding and a xml message, found: "+messageParam.getMessageType());
  66.             }
  67.             OpenSPCoop2RestXmlMessage restXmlMessage = messageParam.castAsRestXml();
  68.            
  69.            
  70.            
  71.             // ********** Leggo operazioni ***************
  72.             boolean encrypt = false;
  73.             boolean signature = false;

  74.             String[]actions = ((String)messageSecurityContext.getIncomingProperties().get(SecurityConstants.ACTION)).split(" ");
  75.             for (int i = 0; i < actions.length; i++) {
  76.                 if(SecurityConstants.isActionEncryption(actions[i].trim()) || SecurityConstants.isActionDecryption(actions[i].trim())){
  77.                     encrypt = true;
  78.                 }
  79.                 else if(SecurityConstants.SIGNATURE_ACTION.equals(actions[i].trim())){
  80.                     signature = true;
  81.                 }
  82.                 else {
  83.                     throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+"; action '"+actions[i]+"' unsupported");
  84.                 }
  85.             }
  86.            
  87.             if(encrypt && signature) {
  88.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with one function beetwen encrypt or signature");
  89.             }
  90.             if(!encrypt && !signature) {
  91.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" require one function beetwen encrypt or signature");
  92.             }
  93.            
  94.            
  95.            
  96.             if(signature) {
  97.                
  98.                
  99.                 // **************** Leggo parametri signature store **************************
  100.                            
  101.                 SignatureBean bean = null;
  102.                 try {
  103.                     bean = KeystoreUtils.getReceiverSignatureBean(messageSecurityContext,ctx);
  104.                 }catch(Exception e) {
  105.                     throw e;
  106.                 }
  107.                    
  108.                 KeyStore signatureKS = bean.getKeystore();
  109.                 KeyStore signatureTrustStoreKS = bean.getTruststore();
  110.                 String aliasSignatureUser = bean.getUser();

  111.                 if(signatureKS==null && signatureTrustStoreKS==null) {
  112.                     throw new SecurityException(XMLCostanti.XML_ENGINE_VERIFIER_SIGNATURE_DESCRIPTION+" require truststore");
  113.                 }
  114.                 if(aliasSignatureUser==null) {
  115.                     throw new SecurityException(XMLCostanti.XML_ENGINE_VERIFIER_SIGNATURE_DESCRIPTION+" require alias certificate");
  116.                 }
  117.                    
  118.                 if(signatureTrustStoreKS!=null) {
  119.                     this.xmlVerifierSignature = new VerifyXmlSignature(signatureTrustStoreKS, aliasSignatureUser);  
  120.                 }
  121.                 else {
  122.                     this.xmlVerifierSignature = new VerifyXmlSignature(signatureKS, aliasSignatureUser);    
  123.                 }
  124.                

  125.                 // **************** Process **************************
  126.                
  127.                 signatureProcess = true; // le eccezioni lanciate da adesso sono registrato con codice relative alla verifica
  128.                 boolean verify = this.xmlVerifierSignature.verify(restXmlMessage.getContent(),false);
  129.                 if(!verify) {
  130.                     throw new Exception("Signature verification failed");
  131.                 }
  132.                
  133.             } // fine signature
  134.            
  135.            
  136.            
  137.             else if(encrypt) {
  138.                
  139.                
  140.                 // **************** Leggo parametri encryption store **************************
  141.                            
  142.                 EncryptionBean bean = null;
  143.                 try {
  144.                     bean = KeystoreUtils.getReceiverEncryptionBean(messageSecurityContext,ctx);
  145.                 }catch(Exception e) {
  146.                     throw e;
  147.                 }
  148.                
  149.                 KeyStore encryptionKS = bean.getKeystore();
  150.                 boolean encryptionSymmetric = bean.isEncryptionSimmetric();
  151.                 SymmetricKeyWrappedMode encryptionSymmetricWrappedMode = null;
  152.                 if(encryptionSymmetric) {
  153.                     encryptionSymmetricWrappedMode = SymmetricKeyWrappedMode.SYM_ENC_KEY_WRAPPED_SYMMETRIC_KEY;
  154.                 }
  155.                 else {
  156.                     encryptionSymmetricWrappedMode = SymmetricKeyWrappedMode.SYM_ENC_KEY_WRAPPED_ASYMMETRIC_KEY;
  157.                 }
  158.                 String aliasEncryptUser = bean.getUser();
  159.                 String aliasEncryptPassword = bean.getPassword();

  160.                 if(encryptionSymmetric) {
  161.                     String encryptionSymmetricWrapped = (String) messageSecurityContext.getIncomingProperties().get(SecurityConstants.DECRYPTION_SYMMETRIC_WRAPPED);
  162.                     if(encryptionSymmetricWrapped!=null) {
  163.                         if(SecurityConstants.DECRYPTION_SYMMETRIC_WRAPPED_TRUE.equalsIgnoreCase(encryptionSymmetricWrapped)) {
  164.                             encryptionSymmetricWrappedMode = SymmetricKeyWrappedMode.SYM_ENC_KEY_WRAPPED_SYMMETRIC_KEY;
  165.                         }
  166.                         else if(SecurityConstants.DECRYPTION_SYMMETRIC_WRAPPED_FALSE.equalsIgnoreCase(encryptionSymmetricWrapped)) {
  167.                             encryptionSymmetricWrappedMode = SymmetricKeyWrappedMode.SYM_ENC_KEY_NO_WRAPPED;
  168.                         }
  169.                     }
  170.                 }
  171.                
  172.                 if(encryptionKS==null) {
  173.                     throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require keystore");
  174.                 }
  175.                 if(aliasEncryptUser==null) {
  176.                     if(encryptionSymmetric) {
  177.                         throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require alias secret key");
  178.                     }
  179.                     else {
  180.                         throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require alias private key");
  181.                     }
  182.                 }
  183.                 if(aliasEncryptPassword==null) {
  184.                     if(encryptionSymmetric) {
  185.                         throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require password secret key");
  186.                     }
  187.                     else {
  188.                         throw new SecurityException(XMLCostanti.XML_ENGINE_DECRYPT_DESCRIPTION+" require password private key");
  189.                     }
  190.                 }

  191.                 this.xmlDecrypt = new XmlDecrypt(encryptionKS, encryptionSymmetric, encryptionSymmetricWrappedMode, aliasEncryptUser, aliasEncryptPassword);

  192.                 boolean detach = true;
  193.                 String encryptionSymmetricWrapped = (String) messageSecurityContext.getIncomingProperties().get(SecurityConstants.DETACH_SECURITY_INFO);
  194.                 if(encryptionSymmetricWrapped!=null) {
  195.                     if(SecurityConstants.FALSE.equalsIgnoreCase(encryptionSymmetricWrapped)) {
  196.                         detach = false;
  197.                     }
  198.                 }
  199.                 Element xmlEncrypted = null;
  200.                 if(!detach) {
  201.                     xmlEncrypted = (Element) restXmlMessage.getContent().cloneNode(true);
  202.                 }
  203.    
  204.                
  205.                 // **************** Process **************************
  206.                            
  207.                 encryptProcess = true; // le eccezioni lanciate da adesso sono registrato con codice relative alla verifica
  208.                 if(detach) {
  209.                     this.xmlDecrypt.decrypt(restXmlMessage.getContent());
  210.                 }
  211.                 else {
  212.                     this.xmlDecrypt.decrypt(xmlEncrypted);
  213.                 }
  214.            
  215.             } // fine encrypt
  216.            
  217.            
  218.            
  219.                        
  220.         } catch (Exception e) {
  221.            
  222.             SecurityException secException = new SecurityException(e.getMessage(), e);
  223.            
  224.            
  225.             /* **** MESSAGGIO ***** */
  226.             String msg = Utilities.getInnerNotEmptyMessageException(e).getMessage();
  227.            
  228.             Throwable innerExc = Utilities.getLastInnerException(e);
  229.             String innerMsg = null;
  230.             if(innerExc!=null){
  231.                 innerMsg = innerExc.getMessage();
  232.             }
  233.            
  234.             String messaggio = null;
  235.             if(msg!=null){
  236.                 messaggio = new String(msg);
  237.                 if(innerMsg!=null && !innerMsg.equals(msg)){
  238.                     messaggio = messaggio + " ; " + innerMsg;
  239.                 }
  240.             }
  241.             else{
  242.                 if(innerMsg!=null){
  243.                     messaggio = innerMsg;
  244.                 }
  245.             }
  246.            
  247.             secException.setMsgErrore(messaggio);
  248.            
  249.            
  250.             /* ***** CODICE **** */
  251.            
  252.             if(signatureProcess){
  253.                 secException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA_FIRMA_NON_VALIDA);
  254.             }
  255.             else if(encryptProcess){
  256.                 secException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA_CIFRATURA_NON_VALIDA);
  257.             }
  258.             else {
  259.                 secException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA);
  260.             }
  261.            
  262.            
  263.             throw secException;
  264.         }

  265.     }

  266.     @Override
  267.     public void detachSecurity(MessageSecurityContext messageSecurityContext, OpenSPCoop2RestMessage<?> messageParam)
  268.             throws SecurityException {
  269.        
  270.         try {
  271.        
  272.             if(ServiceBinding.REST.equals(messageParam.getServiceBinding())==false){
  273.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with REST Binding");
  274.             }
  275.             if(MessageType.XML.equals(messageParam.getMessageType())==false) {
  276.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" usable only with REST Binding and a xml message, found: "+messageParam.getMessageType());
  277.             }
  278.             OpenSPCoop2RestXmlMessage restXmlMessage = messageParam.castAsRestXml();
  279.                    
  280.             if(this.xmlVerifierSignature!=null) {
  281.                 this.xmlVerifierSignature.detach(restXmlMessage.getContent());
  282.             }
  283.             else if(this.xmlDecrypt!=null) {
  284.                 // nop: giĆ  fatto prima
  285.             }
  286.             else {
  287.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (detach method) usable only after one function beetwen encrypt or signature");
  288.             }
  289.            
  290.         }catch(Exception e) {
  291.             throw new SecurityException(e.getMessage(), e);
  292.         }
  293.     }

  294.     @Override
  295.     public String getCertificate() throws SecurityException {
  296.         try {
  297.             if(this.xmlVerifierSignature!=null) {
  298.                 if( this.xmlVerifierSignature.getKeyInfo()!=null ) {
  299.                     // X509
  300.                     if( this.xmlVerifierSignature.getKeyInfo().getX509Certificate()!=null && this.xmlVerifierSignature.getKeyInfo().getX509Certificate().getIssuerX500Principal()!=null ) {
  301.                         return this.xmlVerifierSignature.getKeyInfo().getX509Certificate().getIssuerX500Principal().getName();
  302.                     }
  303.                     // RSA
  304.                     if( this.xmlVerifierSignature.getKeyInfo().getPublicKey()!=null) {
  305.                         // non c'e' una stringa da tornare
  306.                     }
  307.                 }
  308.                 return null;
  309.             }
  310.             else if(this.xmlDecrypt!=null) {
  311.                 return null;
  312.             }
  313.             else {
  314.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (getCertificate method) usable only after one function beetwen encrypt or signature");
  315.             }
  316.         }catch(Exception e) {
  317.             throw new SecurityException(e.getMessage(), e);
  318.         }
  319.     }

  320.     @Override
  321.     public X509Certificate getX509Certificate() throws SecurityException {
  322.         try {
  323.             if(this.xmlVerifierSignature!=null) {
  324.                 if( this.xmlVerifierSignature.getKeyInfo()!=null ) {
  325.                     // X509
  326.                     if( this.xmlVerifierSignature.getKeyInfo().getX509Certificate()!=null && this.xmlVerifierSignature.getKeyInfo().getX509Certificate().getIssuerX500Principal()!=null ) {
  327.                         return this.xmlVerifierSignature.getKeyInfo().getX509Certificate();
  328.                     }
  329.                 }
  330.                 return null;
  331.             }
  332.             else if(this.xmlDecrypt!=null) {
  333.                 return null;
  334.             }
  335.             else {
  336.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (getCertificate method) usable only after one function beetwen encrypt or signature");
  337.             }
  338.         }catch(Exception e) {
  339.             throw new SecurityException(e.getMessage(), e);
  340.         }
  341.     }

  342.     @Override
  343.     public PublicKey getPublicKey() throws SecurityException {
  344.         try {
  345.             if(this.xmlVerifierSignature!=null) {
  346.                 if( this.xmlVerifierSignature.getKeyInfo()!=null ) {
  347.                     // RSA
  348.                     if( this.xmlVerifierSignature.getKeyInfo().getPublicKey()!=null) {
  349.                         return this.xmlVerifierSignature.getKeyInfo().getPublicKey();
  350.                     }
  351.                 }
  352.                 return null;
  353.             }
  354.             else if(this.xmlDecrypt!=null) {
  355.                 return null;
  356.             }
  357.             else {
  358.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (getCertificate method) usable only after one function beetwen encrypt or signature");
  359.             }
  360.         }catch(Exception e) {
  361.             throw new SecurityException(e.getMessage(), e);
  362.         }
  363.     }

  364.     @Override
  365.     public String getCertificateId() throws SecurityException {
  366.         try {
  367.             if(this.xmlVerifierSignature!=null) {
  368.                 if( this.xmlVerifierSignature.getKeyInfo()!=null ) {
  369.                     // RSA
  370.                     if( this.xmlVerifierSignature.getKeyInfo().getId()!=null) {
  371.                         return this.xmlVerifierSignature.getKeyInfo().getId();
  372.                     }
  373.                 }
  374.                 return null;
  375.             }
  376.             else if(this.xmlDecrypt!=null) {
  377.                 return null;
  378.             }
  379.             else {
  380.                 throw new SecurityException(XMLCostanti.XML_ENGINE_DESCRIPTION+" (getCertificate method) usable only after one function beetwen encrypt or signature");
  381.             }
  382.         }catch(Exception e) {
  383.             throw new SecurityException(e.getMessage(), e);
  384.         }
  385.     }
  386.    
  387. }