MessageSecurityReceiver_soapbox.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.soapbox;

  21. import java.io.ByteArrayOutputStream;
  22. import java.io.PrintStream;
  23. import java.security.PublicKey;
  24. import java.security.cert.X509Certificate;
  25. import java.util.ArrayList;
  26. import java.util.HashMap;
  27. import java.util.Iterator;
  28. import java.util.List;
  29. import java.util.Map;

  30. import javax.xml.namespace.QName;
  31. import javax.xml.soap.AttachmentPart;
  32. import javax.xml.soap.SOAPException;
  33. import javax.xml.soap.SOAPPart;

  34. import org.adroitlogic.soapbox.MessageSecurityContext;
  35. import org.adroitlogic.ultraesb.core.MessageImpl;
  36. import org.openspcoop2.message.OpenSPCoop2Message;
  37. import org.openspcoop2.message.OpenSPCoop2SoapMessage;
  38. import org.openspcoop2.message.constants.ServiceBinding;
  39. import org.openspcoop2.message.exception.MessageException;
  40. import org.openspcoop2.message.exception.MessageNotSupportedException;
  41. import org.openspcoop2.message.soap.reference.Reference;
  42. import org.openspcoop2.protocol.sdk.Busta;
  43. import org.openspcoop2.protocol.sdk.constants.CodiceErroreCooperazione;
  44. import org.openspcoop2.security.SecurityException;
  45. import org.openspcoop2.security.message.AbstractSOAPMessageSecurityReceiver;
  46. import org.openspcoop2.security.message.SubErrorCodeSecurity;
  47. import org.openspcoop2.security.message.constants.SecurityConstants;
  48. import org.openspcoop2.security.message.engine.MessageUtilities;
  49. import org.openspcoop2.security.message.engine.WSSUtilities;
  50. import org.openspcoop2.security.message.utils.EncryptionBean;
  51. import org.openspcoop2.security.message.utils.KeystoreUtils;
  52. import org.openspcoop2.security.message.utils.SignatureBean;
  53. import org.openspcoop2.utils.Utilities;
  54. import org.openspcoop2.utils.certificate.KeyStore;
  55. import org.openspcoop2.utils.resources.ClassLoaderUtilities;
  56. import org.w3c.dom.Document;



  57. /**
  58.  * WSSContext_soapbox
  59.  *
  60.  * @author Andrea Poli (apoli@link.it)
  61.  * @author Giovanni Bussu (bussu@link.it)
  62.  * @author $Author$
  63.  * @version $Rev$, $Date$
  64.  */
  65. public class MessageSecurityReceiver_soapbox extends AbstractSOAPMessageSecurityReceiver{

  66.     private X509Certificate [] certificates = null;
  67.    

  68.     @Override
  69.     public void process(org.openspcoop2.security.message.MessageSecurityContext messageSecurityContext,OpenSPCoop2Message messageParam,Busta busta,org.openspcoop2.utils.Map<Object> ctx) throws SecurityException{
  70.         try{
  71.            
  72.             if(ServiceBinding.SOAP.equals(messageParam.getServiceBinding())==false){
  73.                 throw new SecurityException("SoapBox Engine usable only with SOAP Binding");
  74.             }
  75.             OpenSPCoop2SoapMessage message = messageParam.castAsSoap();
  76.            
  77.            
  78.            
  79.             // ********** Leggo operazioni ***************
  80.             boolean decrypt = false;
  81.             boolean signature = false;
  82.             boolean timestamp = false;

  83.             String[]actions = ((String)messageSecurityContext.getIncomingProperties().get(SecurityConstants.ACTION)).split(" ");
  84.             for (int i = 0; i < actions.length; i++) {
  85.                 if(SecurityConstants.isActionEncryption(actions[i].trim())){
  86.                     decrypt = true;
  87.                 }
  88.                 else if(SecurityConstants.SIGNATURE_ACTION.equals(actions[i].trim())){
  89.                     signature = true;
  90.                 }
  91.                 else if(SecurityConstants.TIMESTAMP_ACTION.equals(actions[i].trim())){
  92.                     timestamp = true;
  93.                 }
  94.             }
  95.             // rilasciato vincolo di abilitazione signature o encryption per abilitare il timestamp
  96. //          if(!signature && !decrypt && timestamp){
  97. //              throw new WSSException("La funzionalita' "+WSSConstants.TIMESTAMP_ACTION+" richiede per essere abilitata almeno una delle seguenti altre funzionalita': "+
  98. //                      WSSConstants.ENCRYPT_ACTION+","+WSSConstants.SIGNATURE_ACTION);
  99. //          }
  100.            
  101.            
  102.            
  103.            
  104.             // ********** Inizializzo Header WSS ***************

  105.             SOAPPart sp = message.getSOAPPart();
  106.             //Document d = sp;
  107.             Document d = sp.getDocumentElement().getOwnerDocument();
  108.             Object mustUnderstandObject = messageSecurityContext.getIncomingProperties().get(SecurityConstants.MUST_UNDERSTAND);
  109.             boolean mustUnderstand = false;
  110.             if(mustUnderstandObject!=null){
  111.                 mustUnderstand = SecurityConstants.TRUE.equals(mustUnderstandObject);
  112.             }
  113.             MessageSecurityContext msgSecCtx = new MessageSecurityContext(d, new MessageImpl(true, null, "http"));
  114.             Iterator<?> it = message.getAttachments();
  115.             if(it!=null){
  116.                 while(it.hasNext()) {
  117.                     AttachmentPart part = (AttachmentPart) it.next();
  118.                     String contentId = part.getContentId();
  119.                     if(contentId.startsWith("<"))
  120.                         contentId = contentId.substring(1);
  121.                     if(contentId.endsWith(">"))
  122.                         contentId = contentId.substring(0,contentId.length()-1);
  123.                     msgSecCtx.setProperty(contentId, part); //tolgo < e > dal nome eventualmente
  124.                 }
  125.             }
  126.            
  127.            
  128.            
  129.            
  130.            
  131.            
  132.             // **************** Inizializzo process per validare timestamp **************************
  133.            
  134.             ProcessTimestampedMessage verifyTimestampedProc = null;
  135.             if(timestamp){
  136.                 verifyTimestampedProc = new ProcessTimestampedMessage();
  137.                
  138.                 //future time to live
  139.                 Object futureTtlObject = messageSecurityContext.getIncomingProperties().get(SecurityConstants.TIMESTAMP_FUTURE_TTL);
  140.                 if(futureTtlObject==null){
  141.                     futureTtlObject = SecurityConstants.TIMESTAMP_SOAPBOX_FUTURE_TTL_DEFAULT;
  142.                 }
  143.                 String ttl = (String) futureTtlObject;
  144.                 long futureTtlLong = -1;
  145.                 try{
  146.                     futureTtlLong = Long.parseLong(ttl);
  147.                 }catch(Exception e){
  148.                     throw new Exception("Indicazione "+SecurityConstants.TIMESTAMP_FUTURE_TTL+" non corretta: "+e.getMessage());
  149.                 }

  150.                 msgSecCtx.setProperty(SecurityConstants.TIMESTAMP_FUTURE_TTL, futureTtlLong * 1000l);

  151.                 //strict Timestamp handling
  152.                 Object strictObject = messageSecurityContext.getIncomingProperties().get(SecurityConstants.TIMESTAMP_STRICT);
  153.                 if(strictObject==null){
  154.                     strictObject = SecurityConstants.TRUE;
  155.                 }
  156.                 String strict = (String) strictObject;
  157.                 boolean strictBoolean = false;
  158.                 try{
  159.                     strictBoolean = Boolean.parseBoolean(strict);
  160.                 }catch(Exception e){
  161.                     throw new Exception("Indicazione "+SecurityConstants.TIMESTAMP_STRICT+" non corretta: "+e.getMessage());
  162.                 }

  163.                 msgSecCtx.setProperty(SecurityConstants.TIMESTAMP_STRICT, strictBoolean);
  164.             }
  165.            
  166.            
  167.            
  168.            
  169.            
  170.            
  171.             // **************** Inizializzo process per decifrare **************************

  172.             ProcessPartialEncryptedMessage decryptMsgProc = null;
  173.             if(decrypt){
  174.                 decryptMsgProc = (ProcessPartialEncryptedMessage) ClassLoaderUtilities.newInstance(message.getProcessPartialEncryptedMessageClass());
  175.                 decryptMsgProc.setMessage(message);
  176.                 decryptMsgProc.setActor(messageSecurityContext.getActor());
  177.                 decryptMsgProc.setMustUnderstand(mustUnderstand);
  178.             }
  179.            
  180.            
  181.            
  182.            
  183.            
  184.            
  185.            
  186.             // **************** Inizializzo process per validare la firma **************************
  187.            
  188.             ProcessSignedMessage signMsgProc = null;
  189.             if(signature){
  190.                 signMsgProc = new ProcessSignedMessage();
  191.                 signMsgProc.setMessage(message);
  192.                 signMsgProc.setActor(messageSecurityContext.getActor());
  193.                 signMsgProc.setMustUnderstand(mustUnderstand);
  194.             }
  195.            
  196.            
  197.            
  198.            
  199.            
  200.            
  201.            
  202.            
  203.            
  204.             // **************** Leggo parametri decryption store **************************
  205.             KeyStore decryptionKS = null;
  206.             KeyStore decryptionTrustStoreKS = null;
  207.             String aliasDecryptUser = null;
  208.             String aliasDecryptPassword = null;
  209.             boolean decryptionSymmetric = false;
  210.             if(decrypt){
  211.                 EncryptionBean bean = KeystoreUtils.getReceiverEncryptionBean(messageSecurityContext,ctx);
  212.                
  213.                 decryptionKS = bean.getKeystore();
  214.                 decryptionTrustStoreKS = bean.getTruststore();
  215.                 decryptionSymmetric = bean.isEncryptionSimmetric();
  216.                 aliasDecryptUser = bean.getUser();
  217.                 aliasDecryptPassword = bean.getPassword();
  218.            
  219.             }
  220.            
  221.            
  222.            
  223.            
  224.             // **************** Leggo parametri signature store **************************
  225.             KeyStore signatureKS = null;
  226.             KeyStore signatureTrustStoreKS = null;
  227.             String aliasSignatureUser = null;
  228.             String aliasSignaturePassword = null;
  229.             String crlPath = null;
  230.             if(signature){
  231.                
  232.                 SignatureBean bean = KeystoreUtils.getReceiverSignatureBean(messageSecurityContext,ctx);
  233.                
  234.                 signatureKS = bean.getKeystore();
  235.                 signatureTrustStoreKS = bean.getTruststore();
  236.                 aliasSignatureUser = bean.getUser();
  237.                 aliasSignaturePassword = bean.getPassword();
  238.                 crlPath = bean.getCrlPath();

  239.             }
  240.            
  241.            
  242.            
  243.            
  244.            
  245.            
  246.            
  247.            
  248.            
  249.            
  250.             // **************** Inizializzo Secure Context for encryption **************************
  251.             org.openspcoop2.security.message.soapbox.SoapBoxSecurityConfig securityConfig_decryption = null;
  252.             if(decrypt){            
  253.                 msgSecCtx.getEncryptionRequest().setCertAlias(aliasDecryptUser);
  254.                
  255.                 Map<String, String> passwordMap_decryption = new HashMap<>();
  256.                 passwordMap_decryption.put(aliasDecryptUser, aliasDecryptPassword);
  257.                 if(decryptionTrustStoreKS==null){
  258.                     decryptionTrustStoreKS = decryptionKS;
  259.                 }
  260.                 securityConfig_decryption = new org.openspcoop2.security.message.soapbox.SoapBoxSecurityConfig(decryptionKS, decryptionTrustStoreKS, passwordMap_decryption,ctx);
  261.                 securityConfig_decryption.setSymmetricSharedKey(decryptionSymmetric);
  262.             }
  263.            
  264.            
  265.            
  266.            
  267.            
  268.            
  269.            
  270.            
  271.            
  272.             // **************** Inizializzo Secure Context for signature **************************
  273.             org.openspcoop2.security.message.soapbox.SoapBoxSecurityConfig securityConfig_signature = null;
  274.             if(signature){          
  275.                 Map<String, String> passwordMap_signature = new HashMap<>();
  276.                 passwordMap_signature.put(aliasSignatureUser, aliasSignaturePassword);
  277.                 if(signatureTrustStoreKS==null){
  278.                     signatureTrustStoreKS = signatureKS;
  279.                 }
  280.                 securityConfig_signature = new org.openspcoop2.security.message.soapbox.SoapBoxSecurityConfig(signatureKS, signatureTrustStoreKS, passwordMap_signature,crlPath,ctx);
  281.             }  
  282.            
  283.            
  284.            
  285.            
  286.            
  287.            
  288.            
  289.            
  290.            
  291.             // **************** Process **************************

  292.             // Devo rileggerle per eseguire nell'ordine
  293.             actions = ((String)messageSecurityContext.getIncomingProperties().get(SecurityConstants.ACTION)).split(" ");
  294.             for (int i = actions.length-1; i >= 0; i--) {
  295.                 if(SecurityConstants.isActionEncryption(actions[i].trim()) || SecurityConstants.isActionDecryption(actions[i].trim())){
  296.                     decryptMsgProc.process(securityConfig_decryption, msgSecCtx);
  297.                     //refreshAttachments(message); // per impostare il nuovo contenuto degli attachment, una volta decriptati (non serve se non si imposta il CONTENT_TRANSFER_ENCODING a base64!!)
  298.                 }
  299.                 else if(SecurityConstants.SIGNATURE_ACTION.equals(actions[i].trim())){
  300.                     signMsgProc.process(securityConfig_signature, msgSecCtx);
  301.                     this.certificates = signMsgProc.getCertificates();
  302.                 }
  303.                 else if(SecurityConstants.TIMESTAMP_ACTION.equals(actions[i].trim())){
  304.                     if(securityConfig_signature!=null){
  305.                         verifyTimestampedProc.process(securityConfig_signature, msgSecCtx);
  306.                     }
  307.                     else if(securityConfig_decryption!=null){
  308.                         verifyTimestampedProc.process(securityConfig_decryption, msgSecCtx);
  309.                     } else {
  310.                         verifyTimestampedProc.process(null, msgSecCtx);
  311.                     }
  312.                 }
  313.             }
  314.            
  315.            
  316.            
  317.            
  318.            
  319.            
  320.            
  321.            
  322.            
  323.         } catch (Exception e) {
  324.            
  325.             SecurityException wssException = new SecurityException(e.getMessage(), e);
  326.            
  327.            
  328.             /* **** MESSAGGIO ***** */
  329.             String msg = Utilities.getInnerNotEmptyMessageException(e).getMessage();
  330.            
  331.             Throwable innerExc = Utilities.getLastInnerException(e);
  332.             String innerMsg = null;
  333.             if(innerExc!=null){
  334.                 innerMsg = innerExc.getMessage();
  335.             }
  336.            
  337.             String messaggio = null;
  338.             if(msg!=null){
  339.                 messaggio = new String(msg);
  340.                 if(innerMsg!=null && !innerMsg.equals(msg)){
  341.                     messaggio = messaggio + " ; " + innerMsg;
  342.                 }
  343.             }
  344.             else{
  345.                 if(innerMsg!=null){
  346.                     messaggio = innerMsg;
  347.                 }
  348.             }
  349.            
  350.             wssException.setMsgErrore(messaggio);
  351.            
  352.            

  353.             /* ***** CODICE **** */
  354.            
  355.             boolean signature = false;
  356.             boolean encrypt = false;
  357.             try{
  358.                 ByteArrayOutputStream bout = new ByteArrayOutputStream();
  359.                 PrintStream printStream = new PrintStream(bout);
  360.                 e.printStackTrace(printStream);
  361.                 bout.flush();
  362.                 printStream.flush();
  363.                 bout.close();
  364.                 printStream.close();
  365.                
  366.                 if(bout.toString().contains("ProcessSignedMessage")){
  367.                     signature = true;
  368.                 }
  369.                 else if(bout.toString().contains("Signature verification failed")){
  370.                     signature = true;
  371.                 }
  372.                 else if(bout.toString().contains("Message is not signed")){
  373.                     signature = true;
  374.                 }
  375.                 else if(bout.toString().contains("ProcessPartialEncryptedMessage")){
  376.                     encrypt = true;
  377.                 }
  378.                
  379.             }catch(Exception eClose){}
  380.            
  381.             if(signature){
  382.                 wssException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA_FIRMA_NON_VALIDA);
  383.             }
  384.             else if(encrypt){
  385.                 wssException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA_CIFRATURA_NON_VALIDA);
  386.             }
  387.             else {
  388.                 wssException.setCodiceErrore(CodiceErroreCooperazione.SICUREZZA);
  389.             }
  390.            
  391.            
  392.            
  393.             throw wssException;
  394.         }

  395.     }

  396.     @SuppressWarnings("unused")
  397.     private void refreshAttachments(OpenSPCoop2SoapMessage openspcoop2Message) throws MessageException, MessageNotSupportedException, SOAPException{
  398.         java.util.Iterator<?> itAp = openspcoop2Message.getAttachments();
  399.         List<AttachmentPart> v = new ArrayList<AttachmentPart>();
  400.         while(itAp.hasNext()){
  401.             AttachmentPart ap =
  402.                 (AttachmentPart) itAp.next();
  403.             v.add(ap);
  404.         }
  405.         openspcoop2Message.removeAllAttachments();
  406.         while(v.size()>0){
  407.             AttachmentPart ap = v.remove(0);
  408.             AttachmentPart apNew = openspcoop2Message.createAttachmentPart();
  409.             apNew.setDataHandler(ap.getDataHandler());
  410.             Iterator<?> itMhs = ap.getAllMimeHeaders();
  411.             while (itMhs.hasNext()) {
  412.                 javax.xml.soap.MimeHeader mh = (javax.xml.soap.MimeHeader) itMhs.next();
  413.                 //System.out.println("TIPO["+mh.getName()+"] VALUE["+mh.getValue()+"]");
  414.                 if(!"Content-Transfer-Encoding".equals(mh.getName())){
  415.                     apNew.addMimeHeader(mh.getName(), mh.getValue());
  416.                 }
  417.             }
  418.             openspcoop2Message.addAttachmentPart(apNew);
  419.         }
  420.     }
  421.    

  422.    
  423.     @Override
  424.     public String getCertificate() throws SecurityException{
  425.         if(this.certificates!=null &&
  426.             this.certificates.length > 0){
  427.             return this.certificates[0].getSubjectX500Principal().toString();
  428.         }
  429.         return null;
  430.     }
  431.    
  432.     @Override
  433.     public X509Certificate getX509Certificate() throws SecurityException {
  434.         if(this.certificates!=null &&
  435.             this.certificates.length > 0){
  436.             return this.certificates[0];
  437.         }
  438.         return null;
  439.     }

  440.     @Override
  441.     public PublicKey getPublicKey() {
  442.         if(this.certificates!=null &&
  443.             this.certificates.length > 0){
  444.             return this.certificates[0].getPublicKey();
  445.         }
  446.         return null;
  447.     }
  448.    
  449.     @Override
  450.     public String getCertificateId() throws SecurityException{
  451.         return null;
  452.     }
  453.    

  454.     @Override
  455.     public List<Reference> getDirtyElements(
  456.             org.openspcoop2.security.message.MessageSecurityContext messageSecurityContext,
  457.             OpenSPCoop2SoapMessage message) throws SecurityException {
  458.         return WSSUtilities.getDirtyElements(messageSecurityContext, message);
  459.     }

  460.     @Override
  461.     public Map<QName, QName> checkEncryptSignatureParts(
  462.             org.openspcoop2.security.message.MessageSecurityContext messageSecurityContext,
  463.             List<Reference> elementsToClean, OpenSPCoop2SoapMessage message,
  464.             List<SubErrorCodeSecurity> codiciErrore) throws SecurityException {
  465.         return MessageUtilities.checkEncryptSignatureParts(messageSecurityContext, elementsToClean, message, codiciErrore, SecurityConstants.QNAME_WSS_ELEMENT_SECURITY);
  466.     }

  467.     @Override
  468.     public void checkEncryptionPartElements(Map<QName, QName> notResolved,
  469.             OpenSPCoop2SoapMessage message,
  470.             List<SubErrorCodeSecurity> erroriRilevati) throws SecurityException {
  471.         MessageUtilities.checkEncryptionPartElements(notResolved, message, erroriRilevati);
  472.     }

  473.     @Override
  474.     public void cleanDirtyElements(
  475.             org.openspcoop2.security.message.MessageSecurityContext messageSecurityContext,
  476.             OpenSPCoop2SoapMessage message, List<Reference> elementsToClean,
  477.             boolean detachHeaderWSSecurity, boolean removeAllIdRef)
  478.             throws SecurityException {
  479.         WSSUtilities.cleanDirtyElements(messageSecurityContext, message, elementsToClean, detachHeaderWSSecurity,removeAllIdRef);
  480.        
  481.     }

  482.    
  483. }