ProcessSignedMessage.java

  1. /*
  2.  * AdroitLogic UltraESB Enterprise Service Bus
  3.  *
  4.  * Copyright (c) 2010-2012 AdroitLogic Private Ltd. (http://adroitlogic.org). All Rights Reserved.
  5.  *
  6.  * GNU Affero General Public License Usage
  7.  *
  8.  * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
  9.  * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
  10.  * any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  13.  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
  14.  * more details.
  15.  *
  16.  * You should have received a copy of the GNU Affero General Public License along with this program (See LICENSE-AGPL.TXT).
  17.  * If not, see http://www.gnu.org/licenses/agpl-3.0.html
  18.  *
  19.  * Commercial Usage
  20.  *
  21.  * Licensees holding valid UltraESB Commercial licenses may use this file in accordance with the UltraESB Commercial
  22.  * License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written
  23.  * agreement between you and AdroitLogic.
  24.  *
  25.  * If you are unsure which license is appropriate for your use, or have questions regarding the use of this file,
  26.  * please contact AdroitLogic at info@adroitlogic.com
  27.  */
  28. /*
  29.  * Modificato da Link.it (https://link.it) per supportare le seguenti funzionalità:
  30.  * - firma e cifratura degli attachments
  31.  * - cifratura con chiave simmetrica
  32.  * - supporto CRL
  33.  *
  34.  * Copyright (c) 2011-2025 Link.it srl (https://link.it).
  35.  *
  36.  */

  37. package org.openspcoop2.security.message.soapbox;

  38. import java.security.cert.X509Certificate;

  39. import org.adroitlogic.soapbox.CryptoUtil;
  40. import org.adroitlogic.soapbox.MessageSecurityContext;
  41. import org.adroitlogic.soapbox.Processor;
  42. import org.adroitlogic.soapbox.SBConstants;
  43. import org.adroitlogic.soapbox.SecurityFailureException;
  44. import org.openspcoop2.message.OpenSPCoop2SoapMessage;
  45. import org.openspcoop2.security.message.signature.XMLSecEnvelopeIdResolver;
  46. import org.openspcoop2.utils.LoggerWrapperFactory;
  47. import org.slf4j.Logger;
  48. import org.w3c.dom.Element;

  49. /**
  50.  * ProcessSignedMessage
  51.  *
  52.  * Author of the original AdroitLogic code:
  53.  * @author asankha
  54.  *
  55.  * Authors of the Link.it modification to the code:
  56.  * @author Andrea Poli (apoli@link.it)
  57.  * @author Giovanni Bussu (bussu@link.it)
  58.  * @author $Author$
  59.  * @version $Rev$, $Date$
  60.  */
  61. public class ProcessSignedMessage implements Processor {

  62.     private OpenSPCoop2SoapMessage message;
  63.     public void setMessage(OpenSPCoop2SoapMessage message) {
  64.         this.message = message;
  65.     }
  66.     private String actor;
  67.     private boolean mustUnderstand;
  68.     public void setActor(String actor) {
  69.         this.actor = actor;
  70.     }
  71.     public void setMustUnderstand(boolean mustUnderstand) {
  72.         this.mustUnderstand = mustUnderstand;
  73.     }
  74.    
  75.     private X509Certificate [] certificates = null;
  76.     public X509Certificate[] getCertificates() {
  77.         return this.certificates;
  78.     }
  79.    
  80.     private static final Logger logger = LoggerWrapperFactory.getLogger(ProcessSignedMessage.class);

  81.     @Override
  82.     public void process(org.adroitlogic.soapbox.SecurityConfig secConfig, MessageSecurityContext msgSecCtx) {

  83.         //System.out.println("PROCESS SIGN XMLSEC["+this.useXMLSec+"]");
  84.        
  85.         // ** Recupero header WSSecurity **
  86.         Element wsseSecurityElem = null;
  87.         try{
  88.             wsseSecurityElem = WSSUtils.getWSSecurityHeader(msgSecCtx.getDocument(), this.actor, this.mustUnderstand);
  89.         }catch(Exception e){
  90.             throw new SecurityFailureException(e.getMessage(), e);
  91.         }
  92.        
  93.        
  94.        
  95.         // ** Recupero elemento Signaure **
  96.         Element elemSignature = CryptoUtil.getSecurityProcessorElement(wsseSecurityElem, SBConstants.DS, "Signature");
  97.         if (elemSignature == null) {
  98.             if (ProcessSignedMessage.logger.isDebugEnabled()) {
  99.                 ProcessSignedMessage.logger.debug("Message is not signed - skipping ProcessSignedMessage");
  100.             }
  101.             throw new SecurityFailureException("WS-Security failure - Message is not signed");
  102.         }

  103.        
  104.        
  105.         // *** 1. Prepare to verify signature engine***
  106.         // NOTA:
  107.         // Vi sono fondamentalmente due versioni di XMLSignature con classi correlate.
  108.         // - com.sun.org.apache.xml.internal.security.signature: presente nel runtime di java
  109.         // - org.apache.xml.security.signature: presente in xmlsec-2.1.7.jar
  110.         //
  111.         // A seconda della versione utilizzata devono essere implementate delle classi a corredo:
  112.         // - com.sun.org.apache.xml.internal.security.transforms.TransformSpi implementato tramite org.openspcoop2.security.message.signature.SunAttachmentContentTransform
  113.         // - org.apache.xml.security.transforms.TransformSpi implementato tramite org.openspcoop2.security.message.signature.XMLSecAttachmentContentTransform
  114.         // NOTA: L'implementazione del Transformer tramite le classi della Sun cosi come realizzate usano metodi diversi presenti su Java 1.6 patch 26 o maggiore rispetto a Java 7.
  115.         //       Java 1.7 ha modificato i metodi della classe astratta com.sun.org.apache.xml.internal.security.transforms.TransformSpi
  116.         //       Il codice seguente e' stato scritto per poter effettuare i test incrociati sulle due versioni adeguando le classi utilizzate rispetto ad una variabile cablata nel codice
  117.         //       definita in org.openspcoop2.security.message.soapbox.MesageSecurityContext_soapbox.USE_XMLSEC_IMPL
  118.         //
  119.         // A seconda della versione utilizzata devono inoltre essere implementate le classe di risoluzione delle signature reference
  120.         // - com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi implementata tramite org.openspcoop2.security.message.signature.SunEnvelopeIdResolver
  121.         // - org.apache.xml.security.utils.resolver.ResourceResolverSpi implementata tramite org.openspcoop2.security.message.signature.XMLSecEnvelopeIdResolver
  122.        
  123.         // NOTA!!!: tutto il discorso sopra e' terminato con java 11
  124.        
  125.         org.apache.xml.security.signature.XMLSignature sigXMLSec = null;
  126.         //org.apache.xml.security.signature.XMLSignature sig2 = null;
  127.         try {
  128.             sigXMLSec = new org.apache.xml.security.signature.XMLSignature(elemSignature, null);
  129.             //sig2 = new org.apache.xml.security.signature.XMLSignature(msgSecCtx.getDocument(), null, "http://www.w3.org/2000/09/xmldsig#rsa-sha1", "http://www.w3.org/2001/10/xml-exc-c14n#");
  130.         } catch (Exception e) {
  131.             throw new SecurityFailureException("No signature or error in processing signature in document", e);
  132.         }
  133.         sigXMLSec.addResourceResolver(XMLSecEnvelopeIdResolver.getInstance(this.message));
  134.        
  135.        
  136.                
  137.        
  138.         // *** 2. Extract certificate for the signature, from reference or other means ***
  139.         X509Certificate[] certs = null;
  140.         org.apache.xml.security.keys.KeyInfo keyInfo = sigXMLSec.getKeyInfo();
  141.         if (keyInfo != null && keyInfo.containsKeyValue()) {
  142.             throw new UnsupportedOperationException("Verification of signatures from PublicKeys not yet supported");
  143.         } else if (keyInfo != null) {
  144.             certs = CryptoUtil.getCertificatesFromSecurityTokenReference(secConfig, msgSecCtx,
  145.                     CryptoUtil.getFirstChild(elemSignature, SBConstants.WSSE, SBConstants.SECURITY_TOKEN_REFERENCE));
  146.         } else {
  147.             throw new SecurityFailureException("No key information for signature was found");
  148.         }
  149.         this.certificates = certs;
  150.        
  151.        
  152.        
  153.        
  154.         // *** 3. Check validity of certificate used and validate signature ***
  155.         if (certs != null && certs.length != 0) {

  156.             for (int i=0; i<certs.length; i++) {
  157.                 try {
  158.                     certs[i].checkValidity();
  159.                 } catch (Exception e) {
  160.                     throw new SecurityFailureException("Certificate used for signature with DN : " +
  161.                         certs[i].getSubjectDN().toString() + " is not valid", e);
  162.                 }
  163.             }

  164.             try {
  165.                 ((SoapBoxSecurityConfig)secConfig).validateX509Certificate(certs);
  166.             } catch (Exception e) {
  167.                 throw new SecurityFailureException("Certificate used for signature with DN : " +
  168.                     certs[0].getSubjectDN().toString() + " or its issuer/s is/are not valid", e);
  169.             }

  170.             try {
  171.                 boolean signValid = false;
  172.                 signValid = sigXMLSec.checkSignatureValue(certs[0]);
  173.                
  174.                 if (!signValid) {
  175.                     //System.out.println("TEST["+sig2.checkSignatureValue(certs[0])+"]");
  176.                     throw new SecurityFailureException("Signature verification failed");
  177.                 } else {
  178.                     msgSecCtx.setProperty(org.adroitlogic.soapbox.api.MessageSecurityContext.USER_CERTS, certs);
  179.                 }
  180.             } catch (Exception e) {
  181.                 throw new SecurityFailureException("Signature verification failed", e);
  182.             }
  183.         } else {
  184.             throw new SecurityFailureException("Certificate for signature was not found");
  185.         }

  186.         if (ProcessSignedMessage.logger.isDebugEnabled()) {
  187.             ProcessSignedMessage.logger.debug("Signature verified successfully");
  188.         }
  189.     }

  190. }