AbstractOpenSPCoop2Message_saaj_impl.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.message.soap;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import org.apache.commons.io.output.CountingOutputStream;
import org.apache.wss4j.common.WSS4JConstants;
import org.openspcoop2.message.ForwardConfig;
import org.openspcoop2.message.OpenSPCoop2MessageFactory;
import org.openspcoop2.message.OpenSPCoop2MessageProperties;
import org.openspcoop2.message.constants.Costanti;
import org.openspcoop2.message.constants.MessageType;
import org.openspcoop2.message.exception.MessageException;
import org.openspcoop2.message.exception.MessageNotSupportedException;
import org.openspcoop2.message.soap.reader.OpenSPCoop2MessageSoapStreamReader;
import org.openspcoop2.message.soap.reference.AttachmentReference;
import org.openspcoop2.message.soap.reference.ElementReference;
import org.openspcoop2.message.soap.reference.Reference;
import org.openspcoop2.message.xml.MessageDynamicNamespaceContextFactory;
import org.openspcoop2.message.xml.MessageXMLUtils;
import org.openspcoop2.message.xml.XPathExpressionEngine;
import org.openspcoop2.utils.LoggerWrapperFactory;
import org.openspcoop2.utils.dch.DataContentHandlerManager;
import org.openspcoop2.utils.transport.http.ContentTypeUtilities;
import org.openspcoop2.utils.transport.http.HttpConstants;
import org.openspcoop2.utils.xml.AbstractXPathExpressionEngine;
import org.openspcoop2.utils.xml.DynamicNamespaceContext;
import org.openspcoop2.utils.xml.XPathNotFoundException;
import org.openspcoop2.utils.xml.XPathReturnType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* AbstractXMLBaseOpenSPCoop2Message
*
* @author Andrea Poli (apoli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public abstract class AbstractOpenSPCoop2Message_saaj_impl extends AbstractBaseOpenSPCoop2SoapMessage {
private SOAPMessage soapMessage;
protected SOAPMessage _getSoapMessage() {
return this.soapMessage;
}
public AbstractOpenSPCoop2Message_saaj_impl(OpenSPCoop2MessageFactory messageFactory, SOAPMessage soapMessage){
super(messageFactory);
this.soapMessage = soapMessage;
}
/* Informazioni SOAP (senza costruire il DOM) */
@Override
public OpenSPCoop2MessageSoapStreamReader getSoapReader() throws MessageException,MessageNotSupportedException {
//throw new MessageException("NotImplemented; use soap impl");
return null;
}
/* Metodi SOAP */
@Override
protected SOAPMessage _getSOAPMessage() throws MessageException{
return this.soapMessage;
}
@Override
public SOAPPart getSOAPPart() throws MessageException,MessageNotSupportedException{
return this.soapMessage.getSOAPPart();
}
@Override
public SOAPBody getSOAPBody() throws MessageException,MessageNotSupportedException{
try{
return this.soapMessage.getSOAPBody();
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public boolean hasSOAPFault() throws MessageException,MessageNotSupportedException{
SOAPBody body = getSOAPBody();
return body!=null && body.hasFault();
}
@Override
public boolean isSOAPBodyEmpty() throws MessageException,MessageNotSupportedException{
SOAPBody body = getSOAPBody();
boolean hasContent = body!=null;
if(hasContent){
hasContent = SoapUtils.getFirstNotEmptyChildNode(this.messageFactory, body, false)!=null;
}
return !hasContent;
}
@Override
public SOAPHeader getSOAPHeader() throws MessageException,MessageNotSupportedException{
try{
return this.soapMessage.getSOAPHeader();
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
/* Attachments SOAP */
@Override
public void addAttachmentPart(AttachmentPart attachmentPart) throws MessageException,MessageNotSupportedException{
this.soapMessage.addAttachmentPart(attachmentPart);
}
@Override
public AttachmentPart createAttachmentPart(DataHandler dataHandler) throws MessageException,MessageNotSupportedException{
return this.soapMessage.createAttachmentPart(dataHandler);
}
@Override
public AttachmentPart createAttachmentPart() throws MessageException,MessageNotSupportedException{
return this.soapMessage.createAttachmentPart();
}
@Override
public boolean hasAttachments() throws MessageException,MessageNotSupportedException{
return this.soapMessage.countAttachments()>0;
}
@Override
public int countAttachments() throws MessageException,MessageNotSupportedException{
return this.soapMessage.countAttachments();
}
@Override
public Iterator<?> getAttachments() throws MessageException,MessageNotSupportedException{
return this.soapMessage.getAttachments();
}
@Override
public Iterator<?> getAttachments(MimeHeaders headers) throws MessageException,MessageNotSupportedException{
String[] values = headers.getHeader("Content-Id");
if(values.length > 0 && (!values[0].startsWith("<") || !values[0].endsWith(">"))) {
headers.removeHeader("Content-Id");
headers.setHeader("Content-Id", "<" + values[0] + ">");
}
return this.soapMessage.getAttachments(headers);
}
@Override
public AttachmentPart getAttachment(SOAPElement element) throws MessageException,MessageNotSupportedException{
try{
return this.soapMessage.getAttachment(element);
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void removeAllAttachments() throws MessageException,MessageNotSupportedException{
this.soapMessage.removeAllAttachments();
}
@Override
public void removeAttachments(MimeHeaders mhs) throws MessageException,MessageNotSupportedException{
this.soapMessage.removeAttachments(mhs);
// Aggiorno il Content-Type se sono finiti gli Attachments.
if(this.soapMessage.countAttachments() == 0){
this.setContentType(HttpConstants.CONTENT_TYPE_SOAP_1_1);
}
}
@Override
public void updateAttachmentPart(AttachmentPart ap,DataHandler dh) throws MessageException,MessageNotSupportedException{
ap.setDataHandler(dh);
}
@Override
public void updateAttachmentPart(AttachmentPart ap,byte[]content,String contentType) throws MessageException,MessageNotSupportedException {
// Se si usa il solo metodo del ramo else, in tomcat si ottiene il seguente errore (con dump abilitato):
// ... Unable to run the JAXP transformer on a stream [B cannot be cast to javax.xml.transform.Source (sourceException: Error during saving a multipart message)
try {
String baseType = ContentTypeUtilities.readBaseTypeFromContentType(contentType);
if(HttpConstants.CONTENT_TYPE_TEXT_XML.equals(baseType)) {
Source streamSource = null;
DataContentHandlerManager dchManager = new DataContentHandlerManager(LoggerWrapperFactory.getLogger(AbstractOpenSPCoop2Message_saaj_impl.class));
if(dchManager.readMimeTypesContentHandler().containsKey(HttpConstants.CONTENT_TYPE_TEXT_XML)) {
// Se è non registrato un content handler per text/xml
// succede se dentro l'ear non c'e' il jar mailapi e l'application server non ha caricato il modulo mailapi (es. tramite versione standalone standard)
// e si usa il metodo seguente DOMSource si ottiene il seguente errore:
// javax.xml.soap.SOAPException: no object DCH for MIME type text/xml
// at com.sun.xml.messaging.saaj.soap.MessageImpl.writeTo(MessageImpl.java:1396) ~[saaj-impl-1.3.28.jar:?]
//System.out.println("XML (DOMSource)");
streamSource = new DOMSource(MessageXMLUtils.getInstance(this.messageFactory).newElement(content));
}
else {
// Se è registrato un content handler per text/xml
// e succede se dentro l'ear c'e' il jar mailapi oppure se l'application server ha caricato il modulo mailapi (es. tramite versione standalone full)
// e si usa il metodo seguente StreamSource, si ottiene il seguente errore:
// Unable to run the JAXP transformer on a stream org.xml.sax.SAXParseException; Premature end of file. (sourceException: Error during saving a multipart message)
// com.sun.xml.messaging.saaj.SOAPExceptionImpl: Error during saving a multipart message
// at com.sun.xml.messaging.saaj.soap.MessageImpl.writeTo(MessageImpl.java:1396) ~[saaj-impl-1.3.28.jar:?]
// at org.openspcoop2.message.Message1_1_FIX_Impl.writeTo(Message1_1_FIX_Impl.java:172) ~[openspcoop2_message_BUILD-13516.jar:?]
// at org.openspcoop2.message.OpenSPCoop2Message_11_impl.writeTo
//System.out.println("XML (StreamSource)");
streamSource = new javax.xml.transform.stream.StreamSource(new java.io.ByteArrayInputStream(content));
}
ap.setContent(streamSource, contentType);
}
else {
this.updateAttachmentPart(ap, new DataHandler(content,contentType));
}
}catch(Exception e) {
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void updateAttachmentPart(AttachmentPart ap,String content,String contentType) throws MessageException,MessageNotSupportedException {
this.updateAttachmentPart(ap, new DataHandler(content,contentType));
}
/* ContentID Attachments SOAP */
@Override
public String createContentID(String ns) throws MessageException,MessageNotSupportedException{
return _createContentID(ns);
}
protected static String _createContentID(String ns) throws MessageException,MessageNotSupportedException{
try{
return "<" + org.apache.cxf.attachment.AttachmentUtil.createContentID(ns) + ">";
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
/* Trasporto */
@Override
public OpenSPCoop2MessageProperties getForwardTransportHeader(ForwardConfig forwardConfig) throws MessageException{
OpenSPCoop2MessageProperties msg = super.getForwardTransportHeader(forwardConfig);
return new OpenSPCoop2MessageMimeHeaderProperties(this.soapMessage,msg);
}
/* ContentType */
protected abstract String _super_getContentType();
@Override
public void updateContentType() throws MessageException {
try{
if(countAttachments() > 0){
if(saveRequired()) {
saveChanges();
}
}
else {
if(saveRequired()) {
boolean pulizia = false;
String contentType = _super_getContentType();
if((ContentTypeUtilities.isMtom(contentType)) ){
// Bug Fix: OP-375 'Unable to internalize message' con messaggi senza attachments con ContentType 'multipart/related; ...type="application/xop+xml"'
// Capita per i messaggi che contengono un content type multipart e però non sono effettivamente presenti attachments.
saveChanges();
pulizia = true;
}
else if((ContentTypeUtilities.isMultipartRelated(contentType)) ){
// Bug Fix: OP-678 'Unable to internalize message' con messaggi senza attachments con ContentType 'multipart/related; ...type="text/xml"'
// Capita per i messaggi che contengono un content type multipart e però non sono effettivamente presenti attachments.
saveChanges();
pulizia = true;
}
if(pulizia) {
try {
javax.mail.internet.ContentType ctObj = new javax.mail.internet.ContentType(contentType);
// Bug Fix: OP-909
// Rimane il tipo 'Multipart-Type' come Content-Type in caso di messaggio 'MTOM' senza allegati.
String contentTypeInternal = ContentTypeUtilities.getInternalMultipartContentType(contentType);
javax.mail.internet.ContentType ctObjInternal = new javax.mail.internet.ContentType(contentTypeInternal);
ctObj.setPrimaryType(ctObjInternal.getPrimaryType());
ctObj.setSubType(ctObjInternal.getSubType());
String type = ctObj.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_TYPE);
if(type!=null && !type.equals("")) {
ctObj.getParameterList().remove(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_TYPE);
}
String boundary = ctObj.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_BOUNDARY);
if(boundary!=null && !boundary.equals("")) {
ctObj.getParameterList().remove(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_BOUNDARY);
}
String start = ctObj.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START);
if(start!=null && !start.equals("")) {
ctObj.getParameterList().remove(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START);
}
String startInfo = ctObj.getParameter(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START_INFO);
if(startInfo!=null && !startInfo.equals("")) {
ctObj.getParameterList().remove(HttpConstants.CONTENT_TYPE_MULTIPART_PARAMETER_START_INFO);
}
this.setContentType(ctObj.toString());
}catch(Throwable t) {
System.err.println("Pulizia messaggio Multipart normalizzato senza attachment non riuscita: "+t.getMessage());
t.printStackTrace(System.err);
}
}
}
}
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
/* WriteTo e Save */
@Override
public boolean isContentBuilded() {
return true; // e' insito nel costruttore
}
@Override
public void writeTo(OutputStream os, boolean consume) throws MessageException{
try{
CountingOutputStream cos = new CountingOutputStream(os);
this.soapMessage.writeTo(cos);
this.outgoingsize = cos.getByteCount();
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void saveChanges() throws MessageException{
try{
this.soapMessage.saveChanges();
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public boolean saveRequired(){
return this.soapMessage.saveRequired();
}
/* SOAP Utilities */
@Override
public Element getFirstChildElement(SOAPElement element) throws MessageException,MessageNotSupportedException {
return _getFirstChildElement(element);
}
protected static Element _getFirstChildElement(SOAPElement element) throws MessageException,MessageNotSupportedException {
Element firstElement = null;
NodeList nl = element.getChildNodes();
if(nl!=null) {
for (int i = 0; i < nl.getLength(); i++) {
Node tmp = nl.item(i);
if(tmp instanceof Element) {
firstElement = (Element) tmp;
break;
}
}
}
/**
* Usato anzi 'element.getChildNodes()'; il metodo getChildElements, in un soap body faceva perdere tutti gli altri elementi nella validazione dei contenuti usando il dynamic namespace context
* Iterator<?> it = element.getChildElements();
while (it.hasNext() && firstElement==null){
Node tmp = (Node) it.next();
if(tmp instanceof Element) firstElement = (Element) tmp;
}*/
return firstElement;
}
@Override
public SOAPElement createSOAPElement(byte[] bytes) throws MessageException,MessageNotSupportedException {
return _createSOAPElement(bytes, this.getMessageType(), this.messageFactory);
}
protected static SOAPElement _createSOAPElement(byte[] bytes, MessageType messageType, OpenSPCoop2MessageFactory messageFactory) throws MessageException,MessageNotSupportedException {
try{
SOAPFactory soapFactory = null;
if(MessageType.SOAP_11.equals(messageType)){
soapFactory = messageFactory.getSoapFactory11();
}
else if(MessageType.SOAP_12.equals(messageType)){
soapFactory = messageFactory.getSoapFactory12();
}
else{
throw new MessageException("MessageType ["+messageType+"] not supported");
}
return soapFactory.createElement(MessageXMLUtils.getInstance(messageFactory).newElement(bytes));
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public SOAPHeaderElement newSOAPHeaderElement(SOAPHeader hdr,QName name) throws MessageException,MessageNotSupportedException {
return _newSOAPHeaderElement(hdr,name);
}
protected static SOAPHeaderElement _newSOAPHeaderElement(SOAPHeader hdr,QName name) throws MessageException,MessageNotSupportedException {
try{
SOAPHeaderElement newHeader = hdr.addHeaderElement(name);
return newHeader;
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void addHeaderElement(SOAPHeader hdr,SOAPHeaderElement hdrElement) throws MessageException,MessageNotSupportedException{
_addHeaderElement(hdr, hdrElement);
}
protected static void _addHeaderElement(SOAPHeader hdr,SOAPHeaderElement hdrElement) throws MessageException,MessageNotSupportedException{
try{
hdr.addChildElement(hdrElement);
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void removeHeaderElement(SOAPHeader hdr,SOAPHeaderElement hdrElement) throws MessageException,MessageNotSupportedException{
_removeHeaderElement(hdr, hdrElement);
}
protected static void _removeHeaderElement(SOAPHeader hdr,SOAPHeaderElement hdrElement) throws MessageException,MessageNotSupportedException{
try{
hdr.removeChild(hdrElement);
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void setFaultCode(SOAPFault fault, SOAPFaultCode code,
QName eccezioneName) throws MessageException,MessageNotSupportedException {
_setFaultCode(fault, code, eccezioneName);
}
protected static void _setFaultCode(SOAPFault fault, SOAPFaultCode code,
QName eccezioneName) throws MessageException,MessageNotSupportedException {
try{
fault.setFaultCode(eccezioneName);
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void setFaultString(SOAPFault fault, String message) throws MessageException,MessageNotSupportedException{
_setFaultString(fault, message);
}
protected static void _setFaultString(SOAPFault fault, String message) throws MessageException,MessageNotSupportedException{
try{
SoapUtils.setFaultString(fault, message, null);
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void setFaultString(SOAPFault fault, String message, Locale locale) throws MessageException,MessageNotSupportedException{
_setFaultString(fault, message, locale);
}
protected static void _setFaultString(SOAPFault fault, String message, Locale locale) throws MessageException,MessageNotSupportedException{
try{
SoapUtils.setFaultString(fault, message, locale);
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
/* Ws Security */
private SOAPPart getSOAPPartForSearchWSSecurity(){
return this.soapMessage.getSOAPPart();
}
@Override
public List<Reference> getWSSDirtyElements(String actor, boolean mustUnderstand) throws MessageException,MessageNotSupportedException {
try{
List<Reference> references = new ArrayList<Reference>();
// Prendo il security Header di mia competenza
SOAPElement security = (SOAPElement) WSSecurityUtils.getSecurityHeader(this.getSOAPPartForSearchWSSecurity(),this.messageType, actor,
this.isThrowExceptionIfFoundMoreSecurityHeader());
//TODO verificare se actor==null && mustUnderstand==false?
if(security!=null){
// Prendo i riferimenti agli elementi cifrati
Iterator<?> it = security.getChildElements(new QName(WSS4JConstants.ENC_NS, WSS4JConstants.ENC_KEY_LN));
if(it.hasNext()){
SOAPElement encryptedKey = (SOAPElement) it.next();
SOAPElement referenceList = (SOAPElement) encryptedKey.getChildElements(new QName(WSS4JConstants.ENC_NS, WSS4JConstants.REF_LIST_LN)).next();
List<SOAPElement> referenceListElements = SoapUtils.getNotEmptyChildSOAPElement(referenceList);
for (int i = 0; i < referenceListElements.size(); i++) {
String referenceWithSharp = referenceListElements.get(i).getAttributeValue(new QName("URI"));
// Il riferimento presenta un # prima dell'identificativo se e' un elemento o cid: se e' un attachment
if(referenceWithSharp.startsWith("#")){
String reference = referenceWithSharp.substring(1);
// Vado a vedere se ' cifrato {Content} o {Element}
SOAPElement encryptedElement = (SOAPElement) org.apache.wss4j.common.util.XMLUtils.findElementById(this.getSOAPPartForSearchWSSecurity().getEnvelope(), reference, true);
if(encryptedElement==null){
throw new SOAPException("Element with 'Id' attribute value ("+referenceWithSharp+") not found "+Costanti.FIND_ERROR_ENCRYPTED_REFERENCES);
}
// Verifico se sto cifrando un attachment
QName qName = new QName(WSS4JConstants.ENC_NS, "CipherData");
Iterator<?> childElements = encryptedElement.getChildElements(qName);
if(childElements!=null && childElements.hasNext()){
QName qNameReference = new QName(WSS4JConstants.ENC_NS, "CipherReference");
Iterator<?> childElementsReference = ((SOAPElement)childElements.next()).getChildElements(qNameReference);
if(childElementsReference!=null && childElementsReference.hasNext()){
// Attachment cifrato
String referenceAttach = ((SOAPElement) childElementsReference.next()).getAttributeValue(new QName("URI"));
if(referenceAttach.startsWith("cid:")){
String referenceCID = referenceAttach.substring(4);
references.add(new AttachmentReference (AttachmentReference.TYPE_ENCRYPT_ATTACHMENT, referenceCID));
}else{
throw new SOAPException("Element 'CipherReference' with attribute 'cid' wrong "+Costanti.FIND_ERROR_ENCRYPTED_REFERENCES);
}
}else{
// Elemento cifrato
if(encryptedElement.getAttributeNS(null, "Type").equals(WSS4JConstants.ENC_NS + "Content"))
references.add(new ElementReference(encryptedElement.getParentElement(), ElementReference.TYPE_ENCRYPT_CONTENT, reference));
else
references.add(new ElementReference (encryptedElement.getParentElement(), ElementReference.TYPE_ENCRYPT_ELEMENT, reference));
}
}
else{
throw new SOAPException("Element 'CipherData' not found "+Costanti.FIND_ERROR_ENCRYPTED_REFERENCES);
}
}
}
}
// Prendo i riferimenti agli elementi firmati
it = security.getChildElements(new QName(WSS4JConstants.SIG_NS, WSS4JConstants.SIG_LN));
if(it.hasNext()){
SOAPElement signature = (SOAPElement) it.next();
SOAPElement signatureInfo = (SOAPElement) signature.getChildElements(new QName(WSS4JConstants.SIG_NS, "SignedInfo")).next();
Iterator<?> referenceIterator = signatureInfo.getChildElements(new QName(WSS4JConstants.SIG_NS, "Reference"));
while (referenceIterator.hasNext()) {
String referenceWithSharp = ((SOAPElement) referenceIterator.next()).getAttributeValue(new QName("URI"));
// Il riferimento presenta un # prima dell'identificativo se e' un elemento o cid: se e' un attachment
if(referenceWithSharp.startsWith("#")){
String reference = referenceWithSharp.substring(1);
SOAPEnvelope soapEnvelope = this.getSOAPPartForSearchWSSecurity().getEnvelope();
SOAPElement signedElement = (SOAPElement) org.apache.wss4j.common.util.XMLUtils.findElementById(soapEnvelope, reference, true);
if(signedElement==null){
// Provo a vedere se l'elemento firmato e' una Assertion
DynamicNamespaceContext dnc = null;
if(MessageType.SOAP_11.equals(this.getMessageType())) {
dnc = MessageDynamicNamespaceContextFactory.getInstance(this.messageFactory).getNamespaceContextFromSoapEnvelope11(soapEnvelope);
} else {
dnc = MessageDynamicNamespaceContextFactory.getInstance(this.messageFactory).getNamespaceContextFromSoapEnvelope12(soapEnvelope);
}
AbstractXPathExpressionEngine xpathExpressionEngine = new XPathExpressionEngine(this.messageFactory);
try {
String xpath = Costanti.XPATH_SAML_20_ASSERTION + "[@"+Costanti.SAML_20_ASSERTION_ID+"='"+reference+"']";
Object o = xpathExpressionEngine.getMatchPattern(security, dnc, xpath, XPathReturnType.NODE);
signedElement = (SOAPElement) o;
} catch(XPathNotFoundException e) {}
if(signedElement==null){
try {
String xpath = Costanti.XPATH_SAML_11_ASSERTION + "[@"+Costanti.SAML_11_ASSERTION_ID+"='"+reference+"']";
Object o = xpathExpressionEngine.getMatchPattern(security, dnc, xpath, XPathReturnType.NODE);
signedElement = (SOAPElement) o;
} catch(XPathNotFoundException e) {}
}
if(signedElement==null){
throw new SOAPException("Element with 'Id' attribute value ("+referenceWithSharp+") not found "+Costanti.FIND_ERROR_SIGNATURE_REFERENCES);
}
}
references.add(new ElementReference (signedElement, ElementReference.TYPE_SIGNATURE, reference));
} else if(referenceWithSharp.startsWith("cid:")){
String reference = referenceWithSharp.substring(4);
references.add(new AttachmentReference(AttachmentReference.TYPE_SIGN_ATTACHMENT, reference));
}
}
}
}
return references;
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
@Override
public void cleanWSSDirtyElements(String actor, boolean mustUnderstand, List<Reference> references, boolean detachHeaderWSSecurity, boolean removeAllIdRef) throws MessageException,MessageNotSupportedException {
try{
// Prendo il security Header di mia competenza
SOAPElement security = (SOAPElement) WSSecurityUtils.getSecurityHeader(this.getSOAPPartForSearchWSSecurity(),this.messageType, actor,
this.isThrowExceptionIfFoundMoreSecurityHeader());
// Rimuovo l'header Security
if(detachHeaderWSSecurity){
security.detachNode();
}
boolean found;
// Pulisco i nodi sporchi
for(int i=0; i<references.size(); i++){
Reference reference = references.get(i);
if(reference instanceof ElementReference) {
SOAPElement elementToClean = ((ElementReference)reference).getElement();
switch (reference.getType()) {
case ElementReference.TYPE_SIGNATURE:
// Devo vedere se altri hanno firmato l'elemento ed in tal caso lasciar fare l'id ed il namespace
found = false;
NodeList securities = this.getSOAPHeader().getElementsByTagNameNS(WSS4JConstants.WSSE_NS, WSS4JConstants.WSSE_LN);
for(int s=0; s<securities.getLength(); s++){
security = (SOAPElement) securities.item(s);
// Prendo i riferimenti agli elementi firmati
Iterator<?> it = security.getChildElements(new QName(WSS4JConstants.SIG_NS, WSS4JConstants.SIG_LN));
if(it.hasNext()){
SOAPElement signature = (SOAPElement) it.next();
SOAPElement signatureInfo = (SOAPElement) signature.getChildElements(new QName(WSS4JConstants.SIG_NS, "SignedInfo")).next();
Iterator<?> referenceIterator = signatureInfo.getChildElements(new QName(WSS4JConstants.SIG_NS, "Reference"));
while (referenceIterator.hasNext()) {
String referenceWithSharp = ((SOAPElement) referenceIterator.next()).getAttributeValue(new QName("URI"));
if(reference.getReference().equals(referenceWithSharp.substring(1))) {
found = true;
}
}
}
}
if(!found) {
boolean removeIdRefSignature = false;
if(removeAllIdRef){
// alcune implementazioni vecchie generano degli attributi wsu:Id 'zombie' che quindi non possono essere ripuliti controllandoli con le reference.
// Per poter interoperare con tali implementazioni è possibile abilitare tale opzione
removeIdRefSignature = true;
elementToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
}
else{
String valoreRefSignature = elementToClean.getAttributeNS(WSS4JConstants.WSU_NS, "Id");
// fix: l'id puo' appartenere ad un altro header wssecurity con diverso actor/mustUnderstand. Controllo il valore.
//System.out.println("CHECK TYPE_SIGNATURE ["+valoreRefSignature+"] ["+reference.getReference()+"]");
if(valoreRefSignature!=null && valoreRefSignature.equals(reference.getReference())){
removeIdRefSignature = true;
}
if(removeIdRefSignature){
elementToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
}
}
List<String> prefixesToRemoveContent = new ArrayList<>();
Iterator<?> prefixes = elementToClean.getNamespacePrefixes();
while(prefixes.hasNext()){
String prefix = (String) prefixes.next();
String namespace = elementToClean.getNamespaceURI(prefix);
if(namespace.equals(WSS4JConstants.WSU_NS)) {
if(removeIdRefSignature){
prefixesToRemoveContent.add(prefix);
}
}
}
for(int y=0; y<prefixesToRemoveContent.size(); y++)
elementToClean.removeNamespaceDeclaration(prefixesToRemoveContent.get(y));
}
break;
case ElementReference.TYPE_ENCRYPT_CONTENT:
List<String> prefixesToRemoveContent = new ArrayList<>();
Iterator<?> prefixesContent = elementToClean.getNamespacePrefixes();
while(prefixesContent.hasNext()){
String prefix = (String) prefixesContent.next();
String namespace = elementToClean.getNamespaceURI(prefix);
if(namespace.equals(WSS4JConstants.ENC_NS) || namespace.equals(elementToClean.getNamespaceURI(prefix))){
prefixesToRemoveContent.add(prefix);
}
}
for(int y=0; y<prefixesToRemoveContent.size(); y++)
elementToClean.removeNamespaceDeclaration(prefixesToRemoveContent.get(y));
boolean removeIdRefEncContent = false;
if(removeAllIdRef){
// alcune implementazioni vecchie generano degli attributi wsu:Id 'zombie' che quindi non possono essere ripuliti controllandoli con le reference.
// Per poter interoperare con tali implementazioni è possibile abilitare tale opzione
removeIdRefEncContent = true;
elementToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
}
else{
String valoreRefEncContent = elementToClean.getAttributeNS(WSS4JConstants.WSU_NS, "Id");
// fix: l'id puo' appartenere ad un altro header wssecurity con diverso actor/mustUnderstand. Controllo il valore.
//System.out.println("CHECK TYPE_ENCRYPT_CONTENT ["+valoreRefEncContent+"] ["+reference.getReference()+"]");
if(valoreRefEncContent!=null && valoreRefEncContent.equals(reference.getReference())){
removeIdRefEncContent = true;
}
if(removeIdRefEncContent){
elementToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
}
}
prefixesToRemoveContent = new ArrayList<>();
prefixesContent = elementToClean.getNamespacePrefixes();
while(prefixesContent.hasNext()){
String prefix = (String) prefixesContent.next();
String namespace = elementToClean.getNamespaceURI(prefix);
if(namespace.equals(WSS4JConstants.WSU_NS)) {
if(removeIdRefEncContent){
prefixesToRemoveContent.add(prefix);
}
}
}
for(int y=0; y<prefixesToRemoveContent.size(); y++)
elementToClean.removeNamespaceDeclaration(prefixesToRemoveContent.get(y));
break;
case ElementReference.TYPE_ENCRYPT_ELEMENT:
// Questo codice si occupa di pulire la "sporcizia" wss presente comunque nel elemento cifrato e decifrato.
// Poiche' non c'e' modo, esaminando il messaggio cifrato, di identificare (nome e namespace da decifrare) l'elemento cifrato per intero, si e' scelto di tenersi traccia del padre,
// e a questo punto di ripulire tutti i figli che contengono sporcizia.
// Eventuali figli cifrati in modalita' 'content' rientreranno comunque anche in questa casistica.
Iterator<?> childrenToClean = elementToClean.getChildElements();
while(childrenToClean.hasNext()) {
Object next = childrenToClean.next();
if(next instanceof SOAPElement) {
SOAPElement childToClean = (SOAPElement) next;
List<String> prefixesToRemoveElement = new ArrayList<>();
Iterator<?> prefixesElement = childToClean.getNamespacePrefixes();
while(prefixesElement.hasNext()){
String prefix = (String) prefixesElement.next();
String namespace = childToClean.getNamespaceURI(prefix);
if(namespace.equals(WSS4JConstants.WSU_NS)){
prefixesToRemoveElement.add(prefix);
}
}
for(int y=0; y<prefixesToRemoveElement.size(); y++)
childToClean.removeNamespaceDeclaration(prefixesToRemoveElement.get(y));
boolean removeIdRefEncElement = false;
if(removeAllIdRef){
// alcune implementazioni vecchie generano degli attributi wsu:Id 'zombie' che quindi non possono essere ripuliti controllandoli con le reference.
// Per poter interoperare con tali implementazioni è possibile abilitare tale opzione
removeIdRefEncContent = true;
childToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
}
else{
String valoreRefEncElement = childToClean.getAttributeNS(WSS4JConstants.WSU_NS, "Id");
// fix: l'id puo' appartenere ad un altro header wssecurity con diverso actor/mustUnderstand. Controllo il valore.
//System.out.println("CHECK TYPE_ENCRYPT_ELEMENT ["+valoreRefEncElement+"] ["+reference.getReference()+"]");
if(valoreRefEncElement!=null && valoreRefEncElement.equals(reference.getReference())){
removeIdRefEncElement = true;
}
if(removeIdRefEncElement){
childToClean.removeAttributeNS(WSS4JConstants.WSU_NS, "Id");
}
}
prefixesToRemoveElement = new ArrayList<>();
prefixesElement = childToClean.getNamespacePrefixes();
while(prefixesElement.hasNext()){
String prefix = (String) prefixesElement.next();
String namespace = childToClean.getNamespaceURI(prefix);
if(namespace.equals(WSS4JConstants.WSU_NS)) {
if(removeIdRefEncElement){
prefixesToRemoveElement.add(prefix);
}
}
}
for(int y=0; y<prefixesToRemoveElement.size(); y++)
childToClean.removeNamespaceDeclaration(prefixesToRemoveElement.get(y));
}
}
break;
default:
break;
}
}
}
}catch(Exception e){
throw new MessageException(e.getMessage(),e);
}
}
/* Ws Security (SoapBox) */
@Override
public String getEncryptedDataHeaderBlockClass() {
return _getEncryptedDataHeaderBlockClass();
}
protected static String _getEncryptedDataHeaderBlockClass() {
return "com.sun.xml.wss.core.EncryptedDataHeaderBlock"; // usare la stringa per GPL clean
}
@Override
public String getProcessPartialEncryptedMessageClass() {
return _getProcessPartialEncryptedMessageClass();
}
protected static String _getProcessPartialEncryptedMessageClass() {
return "org.openspcoop2.security.message.soapbox.ProcessPartialEncryptedMessage";
}
@Override
public String getSignPartialMessageProcessorClass() {
return _getSignPartialMessageProcessorClass();
}
protected static String _getSignPartialMessageProcessorClass() {
return "org.openspcoop2.security.message.soapbox.SignPartialMessageProcessor";
}
}