WSSUtilities.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.wss4j;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.activation.DataHandler;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import org.apache.commons.codec.binary.Base64InputStream;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.cxf.attachment.AttachmentImpl;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.message.Attachment;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.WSHandlerResult;
import org.openspcoop2.message.OpenSPCoop2SoapMessage;
import org.openspcoop2.message.xml.MessageXMLUtils;
import org.openspcoop2.security.message.constants.SecurityConstants;
import org.openspcoop2.security.message.utils.AttachmentProcessingPart;
import org.openspcoop2.utils.Utilities;
import org.openspcoop2.utils.dch.InputStreamDataSource;
import org.openspcoop2.utils.io.Base64Utilities;
import org.openspcoop2.utils.regexp.RegularExpressionEngine;
import org.openspcoop2.utils.transport.http.HttpConstants;
import org.slf4j.Logger;
import org.w3c.dom.Node;
/**
* WSSUtilities
*
* @author Lorenzo Nardi (nardi@link.it)
* @author Tommaso Burlon (tommaso.burlon@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class WSSUtilities {
public static void printWSResult(Logger log,List<?> results){
if(results!=null){
Iterator<?> it = results.iterator();
while (it.hasNext()) {
Object object = it.next();
if(object instanceof WSHandlerResult){
WSHandlerResult wsResult = (WSHandlerResult) object;
log.debug("Actor ["+wsResult.getActor()+"]");
List<WSSecurityEngineResult> wsResultList = wsResult.getResults();
if(wsResultList!=null){
for (int i = 0; i < wsResultList.size(); i++) {
log.debug("WSResult["+i+"]="+wsResultList.get(i).toString());
}
}
}
}
}
}
public static List<Attachment> readAttachments(List<String> cidAttachmentsForSecurity,OpenSPCoop2SoapMessage message, SoapMessage msgCtx) throws Exception{
List<Attachment> listAttachments = null;
if(cidAttachmentsForSecurity!=null && cidAttachmentsForSecurity.size()>0){
listAttachments = new ArrayList<Attachment>();
for (String cid : cidAttachmentsForSecurity) {
//System.out.println("GET ID ["+cid+"]");
MimeHeaders mhs = new MimeHeaders();
mhs.addHeader(HttpConstants.CONTENT_ID, cid);
Iterator<?> itAttach = message.getAttachments(mhs);
if(itAttach==null){
throw new Exception("Attachment with Content-ID ["+cid+"] not found");
}
AttachmentPart ap = (AttachmentPart) itAttach.next();
if(ap==null){
throw new Exception("Attachment with Content-ID ["+cid+"] not found");
}
listAttachments.add(convertToCxfAttachment(ap, msgCtx));
}
}
return listAttachments;
}
public static List<Attachment> readAttachments(AttachmentProcessingPart app,OpenSPCoop2SoapMessage message, SoapMessage msgCtx) throws Exception{
List<Attachment> listAttachments = null;
if(app!=null){
List<AttachmentPart> listApDaTrattare = app.getOutput(message);
if(listApDaTrattare!=null && listApDaTrattare.size()>0){
listAttachments = new ArrayList<Attachment>();
for (int i = 0; i < listApDaTrattare.size(); i++) {
AttachmentPart ap = listApDaTrattare.get(i);
//System.out.println("AP ["+ap.getContentId()+"] ["+StringEscapeUtils.escapeXml(ap.getContentId())+"] ["+ap.getContentType()+"] add");
listAttachments.add(convertToCxfAttachment(ap, msgCtx));
}
}
}
return listAttachments;
}
private static Attachment convertToCxfAttachment(AttachmentPart ap, SoapMessage msgCtx) throws Exception{
DataHandler dh = ap.getDataHandler();
DataHandler dhNEW = null;
byte[]bufferArray = null;
String s = null;
boolean encodeBase64 = msgCtx.containsKey(SecurityConstants.PRE_BASE64_ENCODING_ATTACHMENT) ?
msgCtx.get(SecurityConstants.PRE_BASE64_ENCODING_ATTACHMENT).equals(SecurityConstants.PRE_BASE64_ENCODING_ATTACHMENT_TRUE) :
SecurityConstants.PRE_BASE64_ENCODING_ATTACHMENT_DEFAULT;
if(dh.getContentType()!=null && dh.getContentType().startsWith(HttpConstants.CONTENT_TYPE_PLAIN) && !encodeBase64){
dhNEW = dh;
}
else if(!encodeBase64 && (RegularExpressionEngine.isMatch(dh.getContentType(),".*\\/xml")
||
RegularExpressionEngine.isMatch(dh.getContentType(),".*\\+xml"))){
dhNEW = dh;
}
else{
try{
InputStream ins = null;
if (encodeBase64) {
ins = new Base64InputStream(dh.getInputStream(), true);
} else {
ins = dh.getInputStream();
}
InputStreamDataSource isds = new InputStreamDataSource(ap.getContentId(), dh.getContentType(), ins);
dhNEW = new DataHandler(isds);
}catch(javax.activation.UnsupportedDataTypeException edtx){
// eccezione che può essere lanciata da dh.getInputStream() se il datahandler non è stato creato con un datasource
// provo a prendere getContent
Object o = dh.getContent();
if(o!=null){
if(o instanceof String){
s = (String) o;
//System.out.println("SET AS STRING");
dhNEW = new DataHandler(s, dh.getContentType());
}
else if(o instanceof byte[]){
bufferArray = (byte[])o;
InputStreamDataSource isds = new InputStreamDataSource(ap.getContentId(), dh.getContentType(), bufferArray);
dhNEW = new DataHandler(isds);
}
else if(o instanceof InputStream){
InputStreamDataSource isds = new InputStreamDataSource(ap.getContentId(), dh.getContentType(), (InputStream)o);
dhNEW = new DataHandler(isds);
}
else{
throw new Exception("Attach ["+ap.getContentId()+"] ["+dh.getContentType()+"] with type not supported: "+o.getClass().getName(),edtx);
}
}
else{
throw new Exception("Attach ["+ap.getContentId()+"] ["+dh.getContentType()+"] error: "+edtx.getMessage(),edtx);
}
}
}
String id = ap.getContentId();
boolean addAttachmentIdBrackets = msgCtx.containsKey(SecurityConstants.ADD_ATTACHMENT_ID_BRACKETS) ?
msgCtx.get(SecurityConstants.ADD_ATTACHMENT_ID_BRACKETS).equals(SecurityConstants.ADD_ATTACHMENT_ID_BRACKETS_TRUE) :
SecurityConstants.ADD_ATTACHMENT_ID_BRACKETS_DEFAULT;
if (!addAttachmentIdBrackets) {
id = id.replaceAll("(^<)|(>$)", "");
}
AttachmentImpl at = new AttachmentImpl(StringEscapeUtils.escapeXml(id));
boolean encryptAttachmentsHeader = msgCtx.containsKey(SecurityConstants.ENCRYPT_ATTACHMENT_HEADERS) ?
msgCtx.get(SecurityConstants.ENCRYPT_ATTACHMENT_HEADERS).equals(SecurityConstants.ENCRYPT_ATTACHMENT_HEADERS_TRUE) :
SecurityConstants.ENCRYPT_ATTACHMENT_HEADERS_DEFAULT;
if (encryptAttachmentsHeader) {
Iterator<MimeHeader> headers = ap.getAllMimeHeaders();
while (headers.hasNext()) {
MimeHeader header = headers.next();
at.setHeader(header.getName(), header.getValue());
}
}
if (encodeBase64) {
at.setHeader(HttpConstants.CONTENT_TRANSFER_ENCODING, HttpConstants.CONTENT_TRANSFER_ENCODING_VALUE_BASE64);
}
at.setDataHandler(dhNEW);
return at;
}
private static Object postProcessAttachment(Object o, SoapMessage msgCtx) {
boolean decodeBase64 = msgCtx.containsKey(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT) ?
msgCtx.get(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT).equals(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT_TRUE) :
SecurityConstants.POST_BASE64_DECODING_ATTACHMENT_DEFAULT;
if (decodeBase64) {
if (o instanceof String) {
return new String(Base64Utilities.decode((String) o));
}
if (o instanceof byte[]) {
return Base64Utilities.decode((byte[])o);
}
if (o instanceof InputStream) {
return new Base64InputStream((InputStream)o);
}
}
return o;
}
public static void updateAttachments(List<Attachment> listAttachments,OpenSPCoop2SoapMessage message, SoapMessage msgCtx) throws Exception{
if(listAttachments!=null && listAttachments.size()>0){
boolean decodeBase64 = msgCtx.containsKey(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT) ?
msgCtx.get(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT).equals(SecurityConstants.POST_BASE64_DECODING_ATTACHMENT_TRUE) :
SecurityConstants.POST_BASE64_DECODING_ATTACHMENT_DEFAULT;
boolean encodeBase64 = msgCtx.containsKey(SecurityConstants.POST_BASE64_ENCODING_ATTACHMENT) ?
msgCtx.get(SecurityConstants.POST_BASE64_ENCODING_ATTACHMENT).equals(SecurityConstants.POST_BASE64_ENCODING_ATTACHMENT_TRUE) :
SecurityConstants.POST_BASE64_ENCODING_ATTACHMENT_DEFAULT;
for (Attachment attachmentPart : listAttachments) {
MimeHeaders mhs = new MimeHeaders();
mhs.addHeader(HttpConstants.CONTENT_ID, StringEscapeUtils.unescapeXml(attachmentPart.getId()));
AttachmentPart ap = (AttachmentPart) message.getAttachments(mhs).next();
if (encodeBase64)
ap.addMimeHeader(HttpConstants.CONTENT_TRANSFER_ENCODING, HttpConstants.CONTENT_TRANSFER_ENCODING_VALUE_BASE64);
if (decodeBase64)
ap.addMimeHeader(HttpConstants.CONTENT_TRANSFER_ENCODING, HttpConstants.CONTENT_TRANSFER_ENCODING_VALUE_BINARY);
DataHandler dh = attachmentPart.getDataHandler();
byte[]bufferArray = null;
String s = null;
if(dh.getContentType()!=null && dh.getContentType().startsWith(HttpConstants.CONTENT_TYPE_PLAIN)){
Object o = dh.getContent();
if(o instanceof String){
s = (String) postProcessAttachment(o, msgCtx);
message.updateAttachmentPart(ap, s, dh.getContentType());
}
else if(o instanceof byte[]){
bufferArray = (byte[]) postProcessAttachment(o, msgCtx);
message.updateAttachmentPart(ap, bufferArray, dh.getContentType());
}
else if(o instanceof InputStream){
bufferArray = Utilities.getAsByteArray((InputStream)postProcessAttachment(o, msgCtx));
message.updateAttachmentPart(ap, bufferArray, dh.getContentType());
}
else{
throw new Exception("Attach-Plain ["+attachmentPart.getId()+"] ["+dh.getContentType()+"] with type not supported: "+o.getClass().getName());
}
}
else if(RegularExpressionEngine.isMatch(dh.getContentType(),".*\\/xml")
||
RegularExpressionEngine.isMatch(dh.getContentType(),".*\\+xml")){
// potenziale xml
Object o = dh.getContent();
boolean testXml = false;
boolean updated = false;
Node n = null;
if(o instanceof String){
s = (String) postProcessAttachment(o, msgCtx);
//System.out.println("SET AS STRING");
message.updateAttachmentPart(ap, s, dh.getContentType());
updated = true;
}
else if(o instanceof byte[]){
bufferArray = (byte[])postProcessAttachment(o, msgCtx);
//System.out.println("SET AS SOURCE (byte[])");
testXml = true;
}
else if(o instanceof InputStream){
bufferArray = Utilities.getAsByteArray((InputStream)postProcessAttachment(o, msgCtx));
//System.out.println("SET AS SOURCE (IS)");
testXml = true;
}
else if(o instanceof Node){
n = (Node) postProcessAttachment(o, msgCtx);
//System.out.println("SET AS SOURCE (NODE)");
}
else{
throw new Exception("Attach-XML ["+attachmentPart.getId()+"] ["+dh.getContentType()+"] with type not supported: "+o.getClass().getName());
}
if(testXml){
try{
if(n==null){
n = MessageXMLUtils.getInstance(message.getFactory()).newElement(bufferArray);
}
}catch(Exception e){
// no xml
message.updateAttachmentPart(ap, bufferArray, dh.getContentType());
updated = true;
}
}
if(updated==false){
Source streamSource = new DOMSource(n);
DataHandler newDH = new DataHandler(streamSource, dh.getContentType());
message.updateAttachmentPart(ap,newDH);
}
}
else{
try{
InputStream ins = (InputStream) postProcessAttachment(dh.getInputStream(), msgCtx);
InputStreamDataSource isds = new InputStreamDataSource(attachmentPart.getId(), dh.getContentType(), ins);
DataHandler dhNEW = new DataHandler(isds);
message.updateAttachmentPart(ap, dhNEW);
}catch(javax.activation.UnsupportedDataTypeException edtx){
// eccezione che può essere lanciata da dh.getInputStream() se il datahandler non è stato creato con un datasource
// provo a prendere getContent
Object o = dh.getContent();
DataHandler dhNEW = null;
if(o!=null){
if(o instanceof String){
s = (String) o;
//System.out.println("SET AS STRING");
dhNEW = new DataHandler(s, dh.getContentType());
}
else if(o instanceof byte[]){
bufferArray = (byte[])o;
InputStreamDataSource isds = new InputStreamDataSource(attachmentPart.getId(), dh.getContentType(), bufferArray);
dhNEW = new DataHandler(isds);
}
else if(o instanceof InputStream){
InputStreamDataSource isds = new InputStreamDataSource(attachmentPart.getId(), dh.getContentType(), (InputStream)o);
dhNEW = new DataHandler(isds);
}
else{
throw new Exception("Attach ["+ap.getContentId()+"] ["+dh.getContentType()+"] with type not supported: "+o.getClass().getName(),edtx);
}
}
else{
throw new Exception("Attach ["+ap.getContentId()+"] ["+dh.getContentType()+"] error: "+edtx.getMessage(),edtx);
}
message.updateAttachmentPart(ap, dhNEW);
}
}
}
}
}
}