WSSUtilities.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.wss4j;

  21. import java.io.InputStream;
  22. import java.util.ArrayList;
  23. import java.util.Iterator;
  24. import java.util.List;

  25. import javax.activation.DataHandler;
  26. import javax.xml.soap.AttachmentPart;
  27. import javax.xml.soap.MimeHeader;
  28. import javax.xml.soap.MimeHeaders;
  29. import javax.xml.transform.Source;
  30. import javax.xml.transform.dom.DOMSource;

  31. import org.apache.commons.codec.binary.Base64InputStream;
  32. import org.apache.commons.lang.StringEscapeUtils;
  33. import org.apache.cxf.attachment.AttachmentImpl;
  34. import org.apache.cxf.binding.soap.SoapMessage;
  35. import org.apache.cxf.message.Attachment;
  36. import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
  37. import org.apache.wss4j.dom.handler.WSHandlerResult;
  38. import org.openspcoop2.message.OpenSPCoop2SoapMessage;
  39. import org.openspcoop2.message.xml.MessageXMLUtils;
  40. import org.openspcoop2.security.message.constants.SecurityConstants;
  41. import org.openspcoop2.security.message.utils.AttachmentProcessingPart;
  42. import org.openspcoop2.utils.Utilities;
  43. import org.openspcoop2.utils.dch.InputStreamDataSource;
  44. import org.openspcoop2.utils.io.Base64Utilities;
  45. import org.openspcoop2.utils.regexp.RegularExpressionEngine;
  46. import org.openspcoop2.utils.transport.http.HttpConstants;
  47. import org.slf4j.Logger;
  48. import org.w3c.dom.Node;

  49. /**
  50.  * WSSUtilities
  51.  *
  52.  * @author Lorenzo Nardi (nardi@link.it)
  53.  * @author Tommaso Burlon (tommaso.burlon@link.it)
  54.  * @author $Author$
  55.  * @version $Rev$, $Date$
  56.  */
  57. public class WSSUtilities {

  58.     public static void printWSResult(Logger log,List<?> results){
  59.         if(results!=null){
  60.             Iterator<?> it = results.iterator();
  61.             while (it.hasNext()) {
  62.                 Object object = it.next();
  63.                 if(object instanceof WSHandlerResult){
  64.                     WSHandlerResult wsResult = (WSHandlerResult) object;
  65.                     log.debug("Actor ["+wsResult.getActor()+"]");
  66.                     List<WSSecurityEngineResult> wsResultList =  wsResult.getResults();
  67.                     if(wsResultList!=null){
  68.                         for (int i = 0; i < wsResultList.size(); i++) {
  69.                             log.debug("WSResult["+i+"]="+wsResultList.get(i).toString());
  70.                         }
  71.                     }
  72.                 }
  73.             }
  74.         }
  75.     }
  76.    
  77.     public static List<Attachment> readAttachments(List<String> cidAttachmentsForSecurity,OpenSPCoop2SoapMessage message, SoapMessage msgCtx) throws Exception{
  78.         List<Attachment> listAttachments = null;
  79.         if(cidAttachmentsForSecurity!=null && cidAttachmentsForSecurity.size()>0){
  80.             listAttachments = new ArrayList<Attachment>();
  81.             for (String cid : cidAttachmentsForSecurity) {              
  82.                 //System.out.println("GET ID ["+cid+"]");
  83.                 MimeHeaders mhs = new MimeHeaders();
  84.                 mhs.addHeader(HttpConstants.CONTENT_ID, cid);
  85.                 Iterator<?> itAttach = message.getAttachments(mhs);
  86.                 if(itAttach==null){
  87.                     throw new Exception("Attachment with Content-ID ["+cid+"] not found");
  88.                 }
  89.                 AttachmentPart ap = (AttachmentPart) itAttach.next();
  90.                 if(ap==null){
  91.                     throw new Exception("Attachment with Content-ID ["+cid+"] not found");
  92.                 }
  93.                 listAttachments.add(convertToCxfAttachment(ap, msgCtx));
  94.             }
  95.         }
  96.         return listAttachments;
  97.     }
  98.    
  99.     public static List<Attachment> readAttachments(AttachmentProcessingPart app,OpenSPCoop2SoapMessage message, SoapMessage msgCtx) throws Exception{
  100.         List<Attachment> listAttachments = null;
  101.         if(app!=null){
  102.             List<AttachmentPart> listApDaTrattare = app.getOutput(message);
  103.             if(listApDaTrattare!=null && listApDaTrattare.size()>0){
  104.                 listAttachments = new ArrayList<Attachment>();
  105.                 for (int i = 0; i < listApDaTrattare.size(); i++) {
  106.                     AttachmentPart ap = listApDaTrattare.get(i);
  107.                     //System.out.println("AP ["+ap.getContentId()+"] ["+StringEscapeUtils.escapeXml(ap.getContentId())+"] ["+ap.getContentType()+"] add");
  108.                     listAttachments.add(convertToCxfAttachment(ap, msgCtx));
  109.                 }
  110.             }
  111.         }
  112.         return listAttachments;
  113.     }
  114.    
  115.     private static Attachment convertToCxfAttachment(AttachmentPart ap, SoapMessage msgCtx) throws Exception{
  116.         DataHandler dh = ap.getDataHandler();
  117.         DataHandler dhNEW = null;
  118.         byte[]bufferArray = null;
  119.         String s = null;
  120.         boolean encodeBase64 = msgCtx.containsKey(SecurityConstants.PRE_BASE64_ENCODING_ATTACHMENT) ?
  121.                 msgCtx.get(SecurityConstants.PRE_BASE64_ENCODING_ATTACHMENT).equals(SecurityConstants.PRE_BASE64_ENCODING_ATTACHMENT_TRUE) :
  122.                 SecurityConstants.PRE_BASE64_ENCODING_ATTACHMENT_DEFAULT;

  123.         if(dh.getContentType()!=null && dh.getContentType().startsWith(HttpConstants.CONTENT_TYPE_PLAIN) && !encodeBase64){
  124.             dhNEW = dh;
  125.         }
  126.         else if(!encodeBase64 && (RegularExpressionEngine.isMatch(dh.getContentType(),".*\\/xml")
  127.                 ||
  128.                 RegularExpressionEngine.isMatch(dh.getContentType(),".*\\+xml"))){
  129.             dhNEW = dh;
  130.         }
  131.         else{
  132.             try{
  133.                 InputStream ins = null;
  134.                 if (encodeBase64) {
  135.                     ins = new Base64InputStream(dh.getInputStream(), true);
  136.                 } else {
  137.                     ins = dh.getInputStream();
  138.                 }

  139.                 InputStreamDataSource isds = new InputStreamDataSource(ap.getContentId(), dh.getContentType(), ins);
  140.                 dhNEW = new DataHandler(isds);
  141.             }catch(javax.activation.UnsupportedDataTypeException edtx){
  142.                 // eccezione che può essere lanciata da dh.getInputStream() se il datahandler non è stato creato con un datasource

  143.                 // provo a prendere getContent
  144.                 Object o = dh.getContent();
  145.                 if(o!=null){
  146.                     if(o instanceof String){
  147.                         s = (String) o;
  148.                         //System.out.println("SET AS STRING");
  149.                         dhNEW = new DataHandler(s, dh.getContentType());
  150.                     }
  151.                     else if(o instanceof byte[]){
  152.                         bufferArray = (byte[])o;
  153.                         InputStreamDataSource isds = new InputStreamDataSource(ap.getContentId(), dh.getContentType(), bufferArray);
  154.                         dhNEW = new DataHandler(isds);
  155.                     }
  156.                     else if(o instanceof InputStream){
  157.                         InputStreamDataSource isds = new InputStreamDataSource(ap.getContentId(), dh.getContentType(), (InputStream)o);
  158.                         dhNEW = new DataHandler(isds);
  159.                     }
  160.                     else{
  161.                         throw new Exception("Attach ["+ap.getContentId()+"] ["+dh.getContentType()+"] with type not supported: "+o.getClass().getName(),edtx);
  162.                     }
  163.                 }
  164.                 else{
  165.                     throw new Exception("Attach ["+ap.getContentId()+"] ["+dh.getContentType()+"] error: "+edtx.getMessage(),edtx);
  166.                 }
  167.             }
  168.            
  169.         }
  170.        
  171.         String id = ap.getContentId();
  172.         boolean addAttachmentIdBrackets = msgCtx.containsKey(SecurityConstants.ADD_ATTACHMENT_ID_BRACKETS) ?
  173.                 msgCtx.get(SecurityConstants.ADD_ATTACHMENT_ID_BRACKETS).equals(SecurityConstants.ADD_ATTACHMENT_ID_BRACKETS_TRUE) :
  174.                     SecurityConstants.ADD_ATTACHMENT_ID_BRACKETS_DEFAULT;
  175.         if (!addAttachmentIdBrackets) {
  176.             id = id.replaceAll("(^<)|(>$)", "");
  177.         }

  178.         AttachmentImpl at = new AttachmentImpl(StringEscapeUtils.escapeXml(id));
  179.         boolean encryptAttachmentsHeader = msgCtx.containsKey(SecurityConstants.ENCRYPT_ATTACHMENT_HEADERS) ?
  180.                 msgCtx.get(SecurityConstants.ENCRYPT_ATTACHMENT_HEADERS).equals(SecurityConstants.ENCRYPT_ATTACHMENT_HEADERS_TRUE) :
  181.                     SecurityConstants.ENCRYPT_ATTACHMENT_HEADERS_DEFAULT;
  182.         if (encryptAttachmentsHeader) {
  183.             Iterator<MimeHeader> headers = ap.getAllMimeHeaders();
  184.             while (headers.hasNext()) {
  185.                 MimeHeader header = headers.next();
  186.                 at.setHeader(header.getName(), header.getValue());
  187.             }
  188.         }
  189.        
  190.         if (encodeBase64) {
  191.             at.setHeader(HttpConstants.CONTENT_TRANSFER_ENCODING, HttpConstants.CONTENT_TRANSFER_ENCODING_VALUE_BASE64);
  192.         }
  193.        
  194.         at.setDataHandler(dhNEW);
  195.         return at;
  196.     }
  197.    
  198.     private static Object postProcessAttachment(Object o, SoapMessage msgCtx) {
  199.         boolean decodeBase64 = msgCtx.containsKey(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT) ?
  200.                 msgCtx.get(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT).equals(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT_TRUE) :
  201.                 SecurityConstants.POST_BASE64_DECODING_ATTACHMENT_DEFAULT;

  202.         if (decodeBase64) {
  203.             if (o instanceof String) {
  204.                 return new String(Base64Utilities.decode((String) o));
  205.             }
  206.                
  207.             if (o instanceof byte[]) {
  208.                 return Base64Utilities.decode((byte[])o);
  209.             }
  210.                
  211.             if (o instanceof InputStream) {
  212.                 return new Base64InputStream((InputStream)o);
  213.             }
  214.         }
  215.         return o;
  216.     }

  217.     public static void updateAttachments(List<Attachment> listAttachments,OpenSPCoop2SoapMessage message, SoapMessage msgCtx) throws Exception{
  218.         if(listAttachments!=null && listAttachments.size()>0){
  219.             boolean decodeBase64 = msgCtx.containsKey(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT) ?
  220.                     msgCtx.get(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT).equals(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT_TRUE) :
  221.                     SecurityConstants.POST_BASE64_DECODING_ATTACHMENT_DEFAULT;
  222.             boolean encodeBase64 = msgCtx.containsKey(SecurityConstants.POST_BASE64_ENCODING_ATTACHMENT) ?
  223.                     msgCtx.get(SecurityConstants.POST_BASE64_ENCODING_ATTACHMENT).equals(SecurityConstants.POST_BASE64_ENCODING_ATTACHMENT_TRUE) :
  224.                     SecurityConstants.POST_BASE64_ENCODING_ATTACHMENT_DEFAULT;

  225.             for (Attachment attachmentPart : listAttachments) {
  226.                 MimeHeaders mhs = new MimeHeaders();
  227.                 mhs.addHeader(HttpConstants.CONTENT_ID, StringEscapeUtils.unescapeXml(attachmentPart.getId()));

  228.                 AttachmentPart ap = (AttachmentPart) message.getAttachments(mhs).next();
  229.                 if (encodeBase64)
  230.                     ap.addMimeHeader(HttpConstants.CONTENT_TRANSFER_ENCODING, HttpConstants.CONTENT_TRANSFER_ENCODING_VALUE_BASE64);
  231.                 if (decodeBase64)
  232.                     ap.addMimeHeader(HttpConstants.CONTENT_TRANSFER_ENCODING, HttpConstants.CONTENT_TRANSFER_ENCODING_VALUE_BINARY);

  233.                 DataHandler dh = attachmentPart.getDataHandler();
  234.                 byte[]bufferArray = null;
  235.                 String s = null;
  236.                 if(dh.getContentType()!=null && dh.getContentType().startsWith(HttpConstants.CONTENT_TYPE_PLAIN)){
  237.                     Object o = dh.getContent();
  238.                     if(o instanceof String){
  239.                         s = (String) postProcessAttachment(o, msgCtx);
  240.                         message.updateAttachmentPart(ap, s, dh.getContentType());
  241.                     }
  242.                     else if(o instanceof byte[]){
  243.                         bufferArray = (byte[]) postProcessAttachment(o, msgCtx);
  244.                         message.updateAttachmentPart(ap, bufferArray, dh.getContentType());
  245.                     }
  246.                     else if(o instanceof InputStream){
  247.                         bufferArray = Utilities.getAsByteArray((InputStream)postProcessAttachment(o, msgCtx));
  248.                         message.updateAttachmentPart(ap, bufferArray, dh.getContentType());
  249.                     }
  250.                     else{
  251.                         throw new Exception("Attach-Plain ["+attachmentPart.getId()+"] ["+dh.getContentType()+"] with type not supported: "+o.getClass().getName());
  252.                     }
  253.                 }
  254.                 else if(RegularExpressionEngine.isMatch(dh.getContentType(),".*\\/xml")
  255.                         ||
  256.                         RegularExpressionEngine.isMatch(dh.getContentType(),".*\\+xml")){
  257.                     // potenziale xml
  258.                    
  259.                     Object o = dh.getContent();
  260.                     boolean testXml = false;
  261.                     boolean updated = false;
  262.                     Node n = null;
  263.                     if(o instanceof String){
  264.                         s = (String) postProcessAttachment(o, msgCtx);
  265.                         //System.out.println("SET AS STRING");
  266.                         message.updateAttachmentPart(ap, s, dh.getContentType());
  267.                         updated = true;
  268.                     }
  269.                     else if(o instanceof byte[]){
  270.                         bufferArray = (byte[])postProcessAttachment(o, msgCtx);
  271.                         //System.out.println("SET AS SOURCE (byte[])");
  272.                         testXml = true;
  273.                     }
  274.                     else if(o instanceof InputStream){
  275.                         bufferArray = Utilities.getAsByteArray((InputStream)postProcessAttachment(o, msgCtx));
  276.                         //System.out.println("SET AS SOURCE (IS)");
  277.                         testXml = true;
  278.                     }
  279.                     else if(o instanceof Node){
  280.                         n = (Node) postProcessAttachment(o, msgCtx);
  281.                         //System.out.println("SET AS SOURCE (NODE)");
  282.                     }
  283.                     else{
  284.                         throw new Exception("Attach-XML ["+attachmentPart.getId()+"] ["+dh.getContentType()+"] with type not supported: "+o.getClass().getName());
  285.                     }
  286.                    
  287.                     if(testXml){
  288.                         try{
  289.                             if(n==null){
  290.                                 n = MessageXMLUtils.getInstance(message.getFactory()).newElement(bufferArray);
  291.                             }
  292.                         }catch(Exception e){
  293.                             // no xml
  294.                             message.updateAttachmentPart(ap, bufferArray, dh.getContentType());
  295.                             updated = true;
  296.                         }
  297.                     }
  298.                    
  299.                     if(updated==false){
  300.                         Source streamSource = new DOMSource(n);
  301.                         DataHandler newDH = new DataHandler(streamSource, dh.getContentType());
  302.                         message.updateAttachmentPart(ap,newDH);
  303.                     }
  304.                 }
  305.                 else{
  306.                     try{
  307.                         InputStream ins = (InputStream) postProcessAttachment(dh.getInputStream(), msgCtx);
  308.                         InputStreamDataSource isds = new InputStreamDataSource(attachmentPart.getId(), dh.getContentType(), ins);
  309.                         DataHandler dhNEW = new DataHandler(isds);
  310.                         message.updateAttachmentPart(ap, dhNEW);
  311.                     }catch(javax.activation.UnsupportedDataTypeException edtx){
  312.                         // eccezione che può essere lanciata da dh.getInputStream() se il datahandler non è stato creato con un datasource

  313.                         // provo a prendere getContent
  314.                         Object o = dh.getContent();
  315.                         DataHandler dhNEW = null;
  316.                         if(o!=null){
  317.                             if(o instanceof String){
  318.                                 s = (String) o;
  319.                                 //System.out.println("SET AS STRING");
  320.                                 dhNEW = new DataHandler(s, dh.getContentType());
  321.                             }
  322.                             else if(o instanceof byte[]){
  323.                                 bufferArray = (byte[])o;
  324.                                 InputStreamDataSource isds = new InputStreamDataSource(attachmentPart.getId(), dh.getContentType(), bufferArray);
  325.                                 dhNEW = new DataHandler(isds);
  326.                             }
  327.                             else if(o instanceof InputStream){
  328.                                 InputStreamDataSource isds = new InputStreamDataSource(attachmentPart.getId(), dh.getContentType(), (InputStream)o);
  329.                                 dhNEW = new DataHandler(isds);
  330.                             }
  331.                             else{
  332.                                 throw new Exception("Attach ["+ap.getContentId()+"] ["+dh.getContentType()+"] with type not supported: "+o.getClass().getName(),edtx);
  333.                             }
  334.                         }
  335.                         else{
  336.                             throw new Exception("Attach ["+ap.getContentId()+"] ["+dh.getContentType()+"] error: "+edtx.getMessage(),edtx);
  337.                         }
  338.                         message.updateAttachmentPart(ap, dhNEW);
  339.                     }
  340.                 }
  341.             }
  342.         }
  343.     }
  344.    
  345. }