/** * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: Message.java,v 1.3 2008/06/25 05:47:22 qcheng Exp $ * */ package com.sun.identity.liberty.ws.soapbinding; import java.lang.Object; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.StringReader; import java.util.ArrayList; import java.util.Iterator; import java.security.cert.X509Certificate; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import java.util.List; import javax.xml.soap.SOAPMessage; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.transform.stream.StreamSource; import com.sun.identity.liberty.ws.common.wsse.BinarySecurityToken; import com.sun.identity.liberty.ws.common.wsse.WSSEConstants; import com.sun.identity.liberty.ws.security.SecurityAssertion; import com.sun.identity.liberty.ws.security.SecurityUtils; import com.sun.identity.saml.common.SAMLConstants; import com.sun.identity.saml.common.SAMLException; import com.sun.identity.saml.common.SAMLUtils; import com.sun.identity.shared.xml.XMLUtils; /** * The Message class is used by web service client and server to * construct request or response. It will be sent over the SOAP connection. * The Message contains SOAP headers and bodies. The SOAP binding * defines the following headers: CorrelationHeader, * ProviderHeader, ConsentHeader, * UsageDirectiveHeader, ProcessingContextHeader * and ServiceInstanceUpdateHeader. * The first 2 are required and the others are optional. * Signing is mandatory for CorrelationHeader and SOAP Body * element which is the parent of the bodies. Other headers are optional, * so each header needs to have a flag to specify whether it needs to be * signed or not. For each header that needs to be signed, it must have an * id attribute in the top element. The constuctor will take a SAML assertion * or cert alias in order to sign. * * @supported.all.api */ public class Message { /** * anonymous profile is specified. */ public static final int ANONYMOUS = 0; /** * X509 Token profile is specified. */ public static final int X509_TOKEN = 1; /** * SAML Token profile is specified. */ public static final int SAML_TOKEN = 2; /** * Bearer Token profile is specified. */ public static final int BEARER_TOKEN = 3; /** * Authentication mechanism "urn:liberty:security:2003-08:null:null" */ public static final String NULL_NULL = "urn:liberty:security:2003-08:null:null"; /** * Authentication mechanism "urn:liberty:security:2003-08:null:X509" */ public static final String NULL_X509 = "urn:liberty:security:2003-08:null:X509"; /** * Authentication mechanism "urn:liberty:security:2003-08:null:SAML" */ public static final String NULL_SAML = "urn:liberty:security:2003-08:null:SAML"; /** * Authentication mechanism "urn:liberty:security:2004-04:null:Bearer" */ public static final String NULL_BEARER = "urn:liberty:security:2004-04:null:Bearer"; /** * Authentication mechanism "urn:liberty:security:2003-08:TLS:null" */ public static final String TLS_NULL = "urn:liberty:security:2003-08:TLS:null"; /** * Authentication mechanism "urn:liberty:security:2003-08:TLS:X509" */ public static final String TLS_X509 = "urn:liberty:security:2003-08:TLS:X509"; /** * Authentication mechanism "urn:liberty:security:2003-08:TLS:SAML" */ public static final String TLS_SAML = "urn:liberty:security:2003-08:TLS:SAML"; /** * Authentication mechanism "urn:liberty:security:2004-04:TLS:Bearer" */ public static final String TLS_BEARER = "urn:liberty:security:2004-04:TLS:Bearer"; /** * Authentication mechanism "urn:liberty:security:2003-08:ClientTLS:null" */ public static final String CLIENT_TLS_NULL = "urn:liberty:security:2003-08:ClientTLS:null"; /** * Authentication mechanism "urn:liberty:security:2003-08:ClientTLS:X509" */ public static final String CLIENT_TLS_X509 = "urn:liberty:security:2003-08:ClientTLS:X509"; /** * Authentication mechanism "urn:liberty:security:2003-08:ClientTLS:SAML" */ public static final String CLIENT_TLS_SAML = "urn:liberty:security:2003-08:ClientTLS:SAML"; /** * Authentication mechanism "urn:liberty:security:2004-04:ClientTLS:Bearer" */ public static final String CLIENT_TLS_BEARER = "urn:liberty:security:2004-04:ClientTLS:Bearer"; /** * Authentication mechanism "urn:liberty:security:2005-02:null:X509" */ public static final String NULL_X509_WSF11 = "urn:liberty:security:2005-02:null:X509"; /** * Authentication mechanism "urn:liberty:security:2005-02:TLS:X509" */ public static final String TLS_X509_WSF11 = "urn:liberty:security:2005-02:TLS:X509"; /** * Authentication mechanism "urn:liberty:security:2005-02:ClientTLS:X509" */ public static final String CLIENT_TLS_X509_WSF11 = "urn:liberty:security:2005-02:ClientTLS:X509"; /** * Authentication mechanism "urn:liberty:security:2005-02:null:SAML" */ public static final String NULL_SAML_WSF11 = "urn:liberty:security:2005-02:null:SAML"; /** * Authentication mechanism "urn:liberty:security:2005-02:TLS:SAML" */ public static final String TLS_SAML_WSF11 = "urn:liberty:security:2005-02:TLS:SAML"; /** * Authentication mechanism "urn:liberty:security:2005-02:ClientTLS:SAML" */ public static final String CLIENT_TLS_SAML_WSF11 = "urn:liberty:security:2005-02:ClientTLS:SAML"; /** * Authentication mechanism "urn:liberty:security:2005-02:null:Bearer" */ public static final String NULL_BEARER_WSF11 = "urn:liberty:security:2005-02:null:Bearer"; /** * Authentication mechanism "urn:liberty:security:2005-02:TLS:Bearer" */ public static final String TLS_BEARER_WSF11 = "urn:liberty:security:2005-02:TLS:Bearer"; /** * Authentication mechanism "urn:liberty:security:2005-02:ClientTLS:Bearer" */ public static final String CLIENT_TLS_BEARER_WSF11 = "urn:liberty:security:2005-02:ClientTLS:Bearer"; private int securityProfileType = ANONYMOUS; private CorrelationHeader correlationHeader = null; private ConsentHeader consentHeader = null; private List usageDirectiveHeaders = null; private ProviderHeader providerHeader = null; private ProcessingContextHeader processingContextHeader = null; private ServiceInstanceUpdateHeader serviceInstanceUpdateHeader = null; private List soapHeaders = null; private List soapBodies = null; private List securityHeaders = null; private List signingIds = null; private SOAPFault soapFault = null; private String ipAddress = null; private String protocol = "http"; private SecurityAssertion assertion = null; private BinarySecurityToken binarySecurityToken = null; private X509Certificate certificate = null; private X509Certificate messageCertificate = null; private Object token = null; private String bodyId = null; private boolean clientAuthentication = false; private String authenticationMechanism = null; private Document doc = null; private String wsfVersion = SOAPBindingConstants.WSF_11_VERSION; /** * Default Constructor. */ public Message() { correlationHeader = new CorrelationHeader(); securityProfileType = ANONYMOUS; } /** * The default constructor uses default cert alias defined in AMConfig for * signing. * * @param providerHeader ProviderHeader. * @throws SOAPBindingException if provider header is null. */ public Message(ProviderHeader providerHeader) throws SOAPBindingException { correlationHeader = new CorrelationHeader(); this.providerHeader = providerHeader; securityProfileType = ANONYMOUS; } /** * This constructor takes a SAML assertion for signing. * * @param providerHeader ProviderHeader * @param assertion a SAML assertion * @throws SOAPBindingException if an error occurs while processing * the SAML assertion or the provider * header is null */ public Message(ProviderHeader providerHeader,SecurityAssertion assertion) throws SOAPBindingException { if (assertion == null) { throw new SOAPBindingException( Utils.bundle.getString("SAMLAssertionNull")); } this.assertion = assertion; if (assertion.isBearer()) { securityProfileType = BEARER_TOKEN; } else { securityProfileType = SAML_TOKEN; messageCertificate = (X509Certificate)SecurityUtils.getCertificate(assertion); } correlationHeader = new CorrelationHeader(); this.providerHeader = providerHeader; } /** * This constructor takes a binary security token for signing. * * @param providerHeader ProviderHeader * @param token a binary security token * @throws SOAPBindingException if an error occurs while processing * the token or the provider header is null */ public Message(ProviderHeader providerHeader, BinarySecurityToken token) throws SOAPBindingException { if (token == null) { throw new SOAPBindingException( Utils.bundle.getString("binarySecurityTokenNull")); } binarySecurityToken = token; wsfVersion = binarySecurityToken.getWSFVersion(); messageCertificate = (X509Certificate)SecurityUtils.getCertificate(binarySecurityToken); correlationHeader = new CorrelationHeader(); this.providerHeader = providerHeader; securityProfileType = X509_TOKEN; } /** * This constructor is to create a SOAP fault message. * * @param soapFault SOAPFault */ public Message( SOAPFault soapFault) { this.soapFault = soapFault; correlationHeader = new CorrelationHeader(); } /** * This constructor takes an InputStream. * * @param inputStream an InputStream * @throws SOAPBindingException if an error occurs while parsing the input. */ public Message(InputStream inputStream) throws SOAPBindingException { try { doc = XMLUtils.toDOMDocument(inputStream, Utils.debug); parseDocument(doc); } catch (Exception ex) { Utils.debug.error("Message:Message", ex); throw new SOAPBindingException(ex.getMessage()); } } /** * This constructor takes a SOAP message which is received from a SOAP * connection. * * @param soapMessage a SOAP message * @throws SOAPBindingException if an error occurs while parsing the * SOAP message */ public Message(SOAPMessage soapMessage) throws SOAPBindingException,SOAPFaultException { try { ByteArrayOutputStream bop = new ByteArrayOutputStream(); soapMessage.writeTo(bop); ByteArrayInputStream bin = new ByteArrayInputStream(bop.toByteArray()); doc = XMLUtils.toDOMDocument(bin, Utils.debug); parseDocument(doc); } catch (Exception ex) { Utils.debug.error("Message:Message", ex); throw new SOAPBindingException(ex.getMessage()); } } /** * Gets security profile type. Possible values are ANONYMOUS, X509_TOKEN * and SAML_TOKEN. * * @return the Security Profile type */ public int getSecurityProfileType() { return securityProfileType; } /** * Sets security profile type. * * @param profileType Profile Type. Possible values are ANONYMOUS, * X509_TOKEN , SAML_TOKEN and BEARER_TOKEN */ public void setSecurityProfileType(int profileType) { securityProfileType = profileType; } /** * Sets a binary security token for this message. * * @param binaryToken a binary security token */ public void setBinarySecurityToken(BinarySecurityToken binaryToken) { binarySecurityToken = binaryToken; messageCertificate = (X509Certificate)SecurityUtils.getCertificate(binarySecurityToken); } /** * Gets authentication mechanism. * Possible values are NULL_NULL,NULL_X509, NULL_SAML, TLS_NULL, * TLS_X509, TLS_SAML, CLIENT_TLS_NULL,CLIENT_TLS_X509, CLIENT_TLS_SAML, * NULL_BEAER, TLS_BEARER, and CLIENT_TLS_BEARER. * * @return an authentication mechanism */ public String getAuthenticationMechanism() { if (authenticationMechanism != null) { return authenticationMechanism; } if (protocol.equalsIgnoreCase("https")) { if (certificate == null) { switch (securityProfileType) { case X509_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = TLS_X509_WSF11; } else { authenticationMechanism = TLS_X509; } return authenticationMechanism; case SAML_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = TLS_SAML_WSF11; } else { authenticationMechanism = TLS_SAML; } return authenticationMechanism; case BEARER_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = TLS_BEARER_WSF11; } else { authenticationMechanism = TLS_BEARER; } return authenticationMechanism; default: authenticationMechanism = TLS_NULL; return authenticationMechanism; } } else { switch (securityProfileType) { case X509_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = CLIENT_TLS_X509_WSF11; } else { authenticationMechanism = CLIENT_TLS_X509; } return authenticationMechanism; case SAML_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = CLIENT_TLS_SAML_WSF11; } else { authenticationMechanism = CLIENT_TLS_SAML; } return authenticationMechanism; case BEARER_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = CLIENT_TLS_BEARER_WSF11; } else { authenticationMechanism = CLIENT_TLS_BEARER; } return authenticationMechanism; default: authenticationMechanism = CLIENT_TLS_NULL; return authenticationMechanism; } } } else { switch (securityProfileType) { case X509_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = NULL_X509_WSF11; } else { authenticationMechanism = NULL_X509; } return authenticationMechanism; case SAML_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = NULL_SAML_WSF11; } else { authenticationMechanism = NULL_SAML; } return authenticationMechanism; case BEARER_TOKEN: if(SOAPBindingConstants.WSF_11_VERSION.equals( wsfVersion)) { authenticationMechanism = NULL_BEARER_WSF11; } else { authenticationMechanism = NULL_BEARER; } return authenticationMechanism; default: authenticationMechanism = NULL_NULL; return authenticationMechanism; } } } /** * Returns a boolean flag to determine if this Message will be sent to * a server that requires client authentication. * * @return true if this Message will be sent to a server that * requires client authentication */ public boolean isClientAuthentication() { return clientAuthentication; } /** * Returns the CorrelationHeader. * * @return the CorrelationHeader. */ public CorrelationHeader getCorrelationHeader() { return correlationHeader; } /** * Returns the ConsentHeader. * * @return the ConsentHeader. */ public ConsentHeader getConsentHeader() { return consentHeader; } /** * Returns a list of UsageDirectiveHeader. * * @return a list of UsageDirectiveHeader. */ public List getUsageDirectiveHeaders() { return usageDirectiveHeaders; } /** * Returns the ProviderHeader. * * @return the ProviderHeader. */ public ProviderHeader getProviderHeader() { return providerHeader; } /** * Returns the ProcessingContextHeader. * * @return the ProcessingContextHeader. */ public ProcessingContextHeader getProcessingContextHeader() { return processingContextHeader; } /** * Returns the ServiceInstanceUpdateHeader. * * @return the ServiceInstanceUpdateHeader. */ public ServiceInstanceUpdateHeader getServiceInstanceUpdateHeader() { return serviceInstanceUpdateHeader; } /** * Returns a list of SOAP headers except CorrelationHeader, * ConsentHeader, UsageDirectiveHeader and * Security header. Each entry will be a * org.w3c.dom.Element. * * @return a list of SOAP headers */ public List getOtherSOAPHeaders() { return soapHeaders; } /** * Returns the SOAPFault. * * @return the SOAPFault. */ public SOAPFault getSOAPFault() { return soapFault; } /** * Returns a list of SOAP bodies. * Each entry will be a org.w3c.dom.Element. * * @return a list of SOAP bodies */ public List getBodies() { return soapBodies; } /** * Returns a list of SOAP bodies. * Each entry will be a org.w3c.dom.Element with specified * namespace URI and local name. * * @param namespaceURI namspace URI * @param localName local name * @return a list of SOAP bodies */ public List getBodies( String namespaceURI, String localName) { ArrayList bodies = new ArrayList(); if (soapBodies != null && !soapBodies.isEmpty()) { Iterator iter = soapBodies.iterator(); while(iter.hasNext()) { Element bodyE = (Element)iter.next(); String ln = bodyE.getLocalName(); String ns = bodyE.getNamespaceURI(); if (((ns == null && namespaceURI == null) || (ns != null && ns.equals(namespaceURI))) && ln.equals(localName)) { bodies.add(bodyE); } } } return soapBodies; } /** * Returns a list of security header except the SAML assertion used in * SAML token profile or the binary security token used in X509 token * profile. Each entry will be a org.w3c.dom.Element. * * @return a list of security headers */ public List getOtherSecurityHeaders() { return securityHeaders; } /** * Returns the SAML assertion used for signing. * * @return the SAML assertion. */ public SecurityAssertion getAssertion() { return assertion; } /** * Returns a binary security token used for signing. * * @return a binary security token. */ public BinarySecurityToken getBinarySecurityToken() { return binarySecurityToken; } /** * Returns the X509 certificate used in client authentication. * * @return a X509 certificate */ public X509Certificate getPeerCertificate() { return certificate; } /** * Returns the X509 certificate used in message level authentication. * * @return a X509 certificate. */ public X509Certificate getMessageCertificate() { return messageCertificate; } /** * Returns a token for the sender of this Message. * * @return a token Object. */ public Object getToken() { return token; } /** * Returns the IP address of remote site of the SOAP connection. * * @return a IP address */ public String getIPAddress() { return ipAddress; } /** * Returns a list of id's for signing. * * @return a list of id's for signing. */ public List getSigningIds() { List ids = new ArrayList(); ids.add(correlationHeader.getId()); if (consentHeader != null) { String id = consentHeader.getId(); if (id != null) { ids.add(id); } } if (usageDirectiveHeaders != null && !usageDirectiveHeaders.isEmpty()) { Iterator iter = usageDirectiveHeaders.iterator(); while(iter.hasNext()) { String id = ((UsageDirectiveHeader)iter.next()).getId(); if (id != null) { ids.add(id); } } } if (providerHeader != null) { String id = providerHeader.getId(); if (id != null) { ids.add(id); } } if (processingContextHeader != null) { String id = processingContextHeader.getId(); if (id != null) { ids.add(id); } } if (serviceInstanceUpdateHeader != null) { String id = serviceInstanceUpdateHeader.getId(); if (id != null) { ids.add(id); } } if (signingIds != null && !signingIds.isEmpty()) { ids.addAll(signingIds); } if (bodyId == null) { bodyId = SAMLUtils.generateID(); } ids.add(bodyId); return ids; } /** * Sets the CorrelationHeader. * * @param correlationHeader CorrelationHeader */ public void setCorrelationHeader(CorrelationHeader correlationHeader) { if (correlationHeader != null) { this.correlationHeader = correlationHeader; } } /** * Sets ConsentHeader. * * @param consentHeader the ConsentHeader. */ public void setConsentHeader(ConsentHeader consentHeader) { this.consentHeader = consentHeader; } /** * Sets a list of UsageDirectiveHeader. * * @param usageDirectiveHeaders a list of UsageDirectiveHeader. */ public void setUsageDirectiveHeaders(List usageDirectiveHeaders) { this.usageDirectiveHeaders = usageDirectiveHeaders; } /** * Sets ProviderHeader if it is not null. * * @param providerHeader the ProviderHeader. */ public void setProviderHeader(ProviderHeader providerHeader) { this.providerHeader = providerHeader; } /** * Sets the ProcessingContextHeader. * * @param processingContextHeader ProcessingContextHeader */ public void setProcessingContextHeader( ProcessingContextHeader processingContextHeader) { this.processingContextHeader = processingContextHeader; } /** * Sets the ServiceInstanceUpdateHeader. * * @param serviceInstanceUpdateHeader * the ServiceInstanceUpdateHeader */ public void setServiceInstanceUpdateHeader( ServiceInstanceUpdateHeader serviceInstanceUpdateHeader) { this.serviceInstanceUpdateHeader = serviceInstanceUpdateHeader; } /** * Sets a list of SOAP headers except CorrelationHeader, * ConsentHeader, UsageDirectiveHeader and * 'Security' header. Each entry will be a org.w3c.dom.Element. * * @param headers a list of SOAP headers. * @param signingIds a list of values of id attribute for * signing */ public void setOtherSOAPHeaders(List headers, List signingIds) { soapHeaders = headers; this.signingIds = signingIds; } /** * Sets a SOAP header except CorrelationHeader, * ConsentHeader and UsageDirectiveHeader. * * @param header a org.w3c.dom.Element * @param signingId the value of id attribute for signing. * A value null value for this attribute is assumed as no signing. */ public void setOtherSOAPHeader(Element header, String signingId) { soapHeaders = new ArrayList(1); soapHeaders.add(header); if (signingId != null) { signingIds = new ArrayList(1); signingIds.add(signingId); } } /** * Sets a list of security headers. Each entry will be a * org.w3c.dom.Element. * * @param headers a list of security headers. */ public void setOtherSecurityHeaders(List headers) { securityHeaders = headers; } /** * Sets a security header. * * @param header the security header element. */ public void setOtherSecurityHeader(Element header) { securityHeaders = new ArrayList(1); securityHeaders.add(header); } /** * Sets the SOAPFault. * * @param soapFault the SOAPFault. */ public void setSOAPFault(SOAPFault soapFault) { this.soapFault = soapFault; } /** * Sets a list of SOAP bodies. Each entry will be a * org.w3c.dom.Element. To send a SOAP Fault, please use * method setSOAPFault. * * @param bodies a list of SOAP bodies. */ public void setSOAPBodies(List bodies) { soapBodies = bodies; } /** * Sets a SOAP body. To send a SOAP Fault, please use method * setSOAPFault. * * @param body a org.w3c.dom.Element */ public void setSOAPBody(Element body) { soapBodies = new ArrayList(1); soapBodies.add(body); } /** * Sets the IP address of remote site of the SOAP connection. * * @param ipAddress a IP address */ void setIPAddress( String ipAddress) { this.ipAddress = ipAddress; } /** * Sets the protocol value . The expected * value is either http or https. * * @param protocol the protocol value. */ void setProtocol( String protocol) { if (protocol == null) { this.protocol = "http"; } else { this.protocol = protocol; } } /** * Sets the X509 certificate used in client authentication. * * @param cert a X509 certificate */ void setPeerCertificate(X509Certificate cert) { certificate = cert; clientAuthentication = (certificate != null); } /** * Sets a boolean flag. If the flag is true, this Message will be sent to * a server that requires client authentication. * * @param clientAuthentication a boolean flag */ public void setClientAuthentication( boolean clientAuthentication) { this.clientAuthentication = clientAuthentication; } /** * Sets a token for the sender of this Message. The accual type * will be the same as the type of the Object retured from * WebServiceAuthenticator.authenticate. * * @param Object a token Object */ void setToken( Object token) { this.token = token; } /** * Returns the SOAP message in String format. * * @return the SOAP message in String format. */ public String toString() { try { return XMLUtils.print(toDocument(true).getDocumentElement()); } catch (Exception ex) { Utils.debug.error("Message.toString", ex); return ""; } } /** * Returns the SOAP message in org.w3c.dom.Document format. * * @return the SOAP message in org.w3c.dom.Document format. * @throws SOAPBindingException if an error occurs while constructing * a document. */ public Document toDocument() throws SOAPBindingException { return toDocument(false); } /** * Returns the SOAP message in org.w3c.dom.Document format. * * @param refresh true to reconstruct a document, false to reuse a * previous document. If previous document doesn't exist, * it will construct a new document. * @return the SOAP message in org.w3c.dom.Document format. * @throws SOAPBindingException if an error occurs while constructing * the org.w3c.dom.Document. */ public Document toDocument( boolean refresh) throws SOAPBindingException { if (!refresh && doc != null) { return doc; } try { doc = XMLUtils.newDocument(); } catch (Exception ex) { Utils.debug.error("Message:toDocument", ex); throw new SOAPBindingException(ex.getMessage()); } String wsseNS = WSSEConstants.NS_WSSE_WSF11; String wsuNS = WSSEConstants.NS_WSU_WSF11; if(SOAPBindingConstants.WSF_10_VERSION.equals(wsfVersion)) { wsseNS = WSSEConstants.NS_WSSE; wsuNS = WSSEConstants.NS_WSU; } Element envelopeE = doc.createElementNS(SOAPBindingConstants.NS_SOAP, SOAPBindingConstants.PTAG_ENVELOPE); envelopeE.setAttributeNS(SOAPBindingConstants.NS_XML, SOAPBindingConstants.XMLNS_SOAP, SOAPBindingConstants.NS_SOAP); envelopeE.setAttributeNS(SOAPBindingConstants.NS_XML, SOAPBindingConstants.XMLNS_SOAP_BINDING, SOAPBindingConstants.NS_SOAP_BINDING); envelopeE.setAttributeNS(SOAPBindingConstants.NS_XML, SOAPBindingConstants.XMLNS_SOAP_BINDING_11, SOAPBindingConstants.NS_SOAP_BINDING_11); envelopeE.setAttributeNS(SOAPBindingConstants.NS_XML, WSSEConstants.TAG_XML_WSU, wsuNS); doc.appendChild(envelopeE); Element headerE = doc.createElementNS(SOAPBindingConstants.NS_SOAP, SOAPBindingConstants.PTAG_HEADER); envelopeE.appendChild(headerE); if (correlationHeader != null) { correlationHeader.addToParent(headerE); } if (consentHeader != null) { consentHeader.addToParent(headerE); } if (usageDirectiveHeaders != null && !usageDirectiveHeaders.isEmpty()) { Iterator iter = usageDirectiveHeaders.iterator(); while(iter.hasNext()) { ((UsageDirectiveHeader)iter.next()).addToParent(headerE); } } if (providerHeader != null) { providerHeader.addToParent(headerE); } if (processingContextHeader != null) { processingContextHeader.addToParent(headerE); } if (serviceInstanceUpdateHeader != null) { serviceInstanceUpdateHeader.addToParent(headerE); } if (soapHeaders != null && !soapHeaders.isEmpty()) { if (Utils.debug.messageEnabled()) { Utils.debug.message("Message.toDocument: adding headers "); } Iterator iter = soapHeaders.iterator(); while(iter.hasNext()) { Element soapHeaderE = (Element)iter.next(); headerE.appendChild(doc.importNode(soapHeaderE, true)); } } boolean hasSecurityHeaders = (securityHeaders != null && !securityHeaders.isEmpty()); if (securityProfileType != ANONYMOUS || hasSecurityHeaders) { if (Utils.debug.messageEnabled()) { Utils.debug.message( "Message.toDocument: adding security headers "); } Element securityE = doc.createElementNS(wsseNS, WSSEConstants.TAG_WSSE + ":" + WSSEConstants.TAG_SECURITYT); securityE.setAttributeNS(SOAPBindingConstants.NS_XML, WSSEConstants.TAG_XML_WSSE, wsseNS); headerE.appendChild(securityE); if (assertion != null) { Document assertionDoc = XMLUtils.toDOMDocument(assertion.toString(true, true), Utils.debug); if (assertionDoc == null) { String msg = Utils.bundle.getString("cannotProcessSAMLAssertion"); Utils.debug.error("Message.Message: " + msg); throw new SOAPBindingException(msg); } Element assertionE = assertionDoc.getDocumentElement(); securityE.appendChild(doc.importNode(assertionE, true)); } else if (binarySecurityToken != null) { Document bstDoc = XMLUtils.toDOMDocument(binarySecurityToken.toString(), Utils.debug); if (bstDoc == null) { String msg = Utils.bundle.getString( "cannotProcessBinarySecurityToken"); Utils.debug.error("Message.Message: " + msg); throw new SOAPBindingException(msg); } Element binarySecurityTokenE = bstDoc.getDocumentElement(); securityE.appendChild(doc.importNode(binarySecurityTokenE, true)); } if (hasSecurityHeaders) { Iterator iter = securityHeaders.iterator(); while(iter.hasNext()) { securityE.appendChild(doc.importNode((Node)iter.next(), true)); } } } Element bodyE = null; if (soapFault != null) { if (Utils.debug.messageEnabled()) { Utils.debug.message("Message.toDocument: adding soapFault "); } bodyE = doc.createElementNS(SOAPBindingConstants.NS_SOAP, SOAPBindingConstants.PTAG_BODY); envelopeE.appendChild(bodyE); soapFault.addToParent(bodyE); } if (soapBodies != null && !soapBodies.isEmpty()){ if (Utils.debug.messageEnabled()) { Utils.debug.message("Message.toDocument: adding bodies "); } if (bodyE == null) { bodyE = doc.createElementNS(SOAPBindingConstants.NS_SOAP, SOAPBindingConstants.PTAG_BODY); bodyE.setAttributeNS(SOAPBindingConstants.NS_XML, SOAPBindingConstants.XMLNS_SOAP, SOAPBindingConstants.NS_SOAP); envelopeE.appendChild(bodyE); } Iterator iter = soapBodies.iterator(); while(iter.hasNext()) { Element soapBodyE = (Element)iter.next(); bodyE.appendChild(doc.importNode(soapBodyE, true)); } if (bodyId == null) { bodyId = SAMLUtils.generateID(); } if (SOAPBindingConstants.WSF_10_VERSION.equals(wsfVersion)) { bodyE.setAttributeNS(null, SOAPBindingConstants.ATTR_id, bodyId); } else { bodyE.setAttributeNS(wsuNS, WSSEConstants.WSU_ID, bodyId); } } return doc; } /** * Returns the SOAP message in SOAPMessage format. * * @return the SOAP message in SOAPMessage format. * @throws SOAPBindingException if an error occurs while converting * this object to a SOAP message. */ SOAPMessage toSOAPMessage() throws SOAPBindingException { return Utils.DocumentToSOAPMessage(toDocument(true)); } /** * Parses a org.w3c.dom.Document to construct this object. * * @param doc a org.w3c.dom.Document. * @throws SOAPBindingException if an error occurs while parsing * the document */ private void parseDocument( Document doc) throws SOAPBindingException { Element envelopeE = doc.getDocumentElement(); if (Utils.debug.messageEnabled()) { Utils.debug.message("Message.parseDocument: doc = " + XMLUtils.print(envelopeE)); } NodeList nl = envelopeE.getChildNodes(); int length = nl.getLength(); if (length == 0) { String msg = Utils.bundle.getString("soapEnvelopeMissingChildren"); Utils.debug.error("Message.parseDocument: " + msg); throw new SOAPBindingException(msg); } Element headerE = null; Element bodyE = null; for(int i = 0; i < length; i++) { Node child = nl.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element)child; String localName = element.getLocalName(); String namespaceURI = element.getNamespaceURI(); if (SOAPBindingConstants.NS_SOAP.equals(namespaceURI)) { if (SOAPBindingConstants.TAG_HEADER.equals(localName)) { headerE = element; } else if(SOAPBindingConstants.TAG_BODY.equals(localName)){ bodyE = element; } } } } Element securityE = null; soapHeaders = new ArrayList(); // parsing Header element if (headerE != null) { nl = headerE.getChildNodes(); length = nl.getLength(); for (int i = 0; i < length; i++) { Node child = nl.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element)child; String localName = element.getLocalName(); String ns = element.getNamespaceURI(); if (SOAPBindingConstants.NS_SOAP_BINDING.equals(ns)) { if (SOAPBindingConstants.TAG_CORRELATION .equals(localName)) { correlationHeader = new CorrelationHeader(element); } else if (SOAPBindingConstants.TAG_CONSENT .equals(localName)) { consentHeader = new ConsentHeader(element); } else if(SOAPBindingConstants.TAG_USAGE_DIRECTIVE .equals(localName)){ if (usageDirectiveHeaders == null) { usageDirectiveHeaders = new ArrayList(); } usageDirectiveHeaders.add( new UsageDirectiveHeader(element)); } else if (SOAPBindingConstants.TAG_PROVIDER .equals(localName)) { providerHeader = new ProviderHeader(element); } else if (SOAPBindingConstants.TAG_PROCESSING_CONTEXT .equals(localName)) { processingContextHeader = new ProcessingContextHeader(element); } else { soapHeaders.add(element); } } else if (SOAPBindingConstants.NS_SOAP_BINDING_11 .equals(ns) && SOAPBindingConstants .TAG_SERVICE_INSTANCE_UPDATE .equals(localName)) { serviceInstanceUpdateHeader = new ServiceInstanceUpdateHeader(element); } else if (WSSEConstants.NS_WSSE.equals(ns) || WSSEConstants.NS_WSSE_WSF11.equals(ns)) { if (WSSEConstants.TAG_SECURITYT.equals(localName)) { securityE = element; } else { soapHeaders.add(element); } } else { soapHeaders.add(element); } } } parseSecurityElement(securityE); } if (soapHeaders.isEmpty()) { soapHeaders = null; } // parsing Body element if (bodyE != null) { nl = bodyE.getChildNodes(); length = nl.getLength(); for(int i = 0; i < length; i++) { Node child = nl.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { Element childE = (Element)child; String localName = childE.getLocalName(); String ns = childE.getNamespaceURI(); if (soapFault == null && SOAPBindingConstants.NS_SOAP.equals(ns) && SOAPBindingConstants.TAG_FAULT.equals(localName)) { soapFault = new SOAPFault(childE); } else { if (soapBodies == null) { soapBodies = new ArrayList(); } soapBodies.add(child); } } } } } /** * Sets security profile type by parsing a security element. * * @param se a security element * @throws SOAPBindingException if an error occurs while parsing * the security element */ private void parseSecurityElement(Element securityE) throws SOAPBindingException { if (securityE == null) { securityProfileType = ANONYMOUS; return; } String wsseNS = securityE.getNamespaceURI(); if (wsseNS == null) { securityProfileType = ANONYMOUS; return; } String wsuNS = null; if (wsseNS.equals(WSSEConstants.NS_WSSE_WSF11)) { wsfVersion = SOAPBindingConstants.WSF_11_VERSION; wsuNS = WSSEConstants.NS_WSU_WSF11; } else if(wsseNS.equals(WSSEConstants.NS_WSSE)) { wsfVersion = SOAPBindingConstants.WSF_10_VERSION; wsuNS = WSSEConstants.NS_WSU; } else { securityProfileType = ANONYMOUS; return; } NodeList nl = securityE.getElementsByTagNameNS(wsseNS, SAMLConstants.TAG_SECURITYTOKENREFERENCE); Element securityTokenRefE = null; String uri = null; if (nl != null && nl.getLength() > 0) { securityTokenRefE = (Element)nl.item(0); List list = XMLUtils.getElementsByTagNameNS1(securityTokenRefE, wsseNS, SAMLConstants.TAG_REFERENCE); if (!list.isEmpty()) { Element referenceE = (Element)list.get(0); uri = XMLUtils.getNodeAttributeValue(referenceE, SAMLConstants.TAG_URI); if (uri != null && uri.length() > 1 && uri.startsWith("#")) { uri = uri.substring(1); } else { String msg = Utils.bundle.getString("invalidReferenceURI"); Utils.debug.error("Message.parseSecurityElement: " + msg); throw new SOAPBindingException(msg); } if (Utils.debug.messageEnabled()) { Utils.debug.message("Message.parseSecurityElement: " + "SecurityTokenReference Reference URI = " + uri); } } } securityProfileType = ANONYMOUS; securityHeaders = new ArrayList(); nl = securityE.getChildNodes(); int length = nl.getLength(); for(int i = 0; i < length; i++) { Node child = nl.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { String localName = child.getLocalName(); String ns = child.getNamespaceURI(); if (securityProfileType != ANONYMOUS) { securityHeaders.add(child); continue; } if (SAMLConstants.BINARYSECURITYTOKEN.equals(localName) && wsseNS.equals(ns)) { Element binarySecurityTokenE = (Element)child; String valuetype = XMLUtils.getNodeAttributeValue( binarySecurityTokenE, "ValueType"); Utils.debug.message("ValueType: "+valuetype); if ((valuetype != null) && valuetype.endsWith("ServiceSessionContext")) { securityHeaders.add(child); continue; } if (uri != null) { String id = XMLUtils.getNodeAttributeValueNS( binarySecurityTokenE, wsuNS, SAMLConstants.TAG_ID); if (!uri.equals(id)) { securityHeaders.add(child); continue; } } try { binarySecurityToken = new BinarySecurityToken(binarySecurityTokenE); messageCertificate = (X509Certificate)SecurityUtils.getCertificate( binarySecurityToken); } catch (Exception ex) { String msg = Utils.bundle.getString( "cannotProcessBinarySecurityToken"); Utils.debug.error("Message.parseSecurityElement: "+ msg); throw new SOAPBindingException(msg); } if (Utils.debug.messageEnabled()) { Utils.debug.message("Message.parseSecurityElement:" + " found binary security token"); } securityProfileType = X509_TOKEN; } else if (SAMLConstants.TAG_ASSERTION.equals(localName) && SAMLConstants.assertionSAMLNameSpaceURI.equals(ns)){ Element assertionE = (Element)child; if (uri != null) { String assertionID = XMLUtils.getNodeAttributeValue( assertionE, SAMLConstants.TAG_ASSERTION_ID); if (!uri.equals(assertionID)) { securityHeaders.add(child); continue; } } try { assertion = new SecurityAssertion(assertionE); } catch (SAMLException ex) { String msg = Utils.bundle.getString( "cannotProcessSAMLAssertion"); Utils.debug.error("Message.parseSecurityElement: " + msg); throw new SOAPBindingException(msg); } if (Utils.debug.messageEnabled()) { Utils.debug.message("Message.parseSecurityElement:" + " found security assertion, " + "isBearer = " + assertion.isBearer()); } if (assertion.isBearer()) { securityProfileType = BEARER_TOKEN; } else { securityProfileType = SAML_TOKEN; messageCertificate = (X509Certificate)SecurityUtils.getCertificate( assertion); } } else { securityHeaders.add(child); } } } if (securityHeaders.isEmpty()) { securityHeaders = null; } } /** * Returns the web services version of the message. * * @return the web services version. */ public String getWSFVersion() { return wsfVersion; } /** * Sets the web services version to the message. * * @param version the web services framework version. */ public void setWSFVersion(String version) { this.wsfVersion = version; } }