449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings/*
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * The contents of this file are subject to the terms of the Common Development and
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Distribution License (the License). You may not use this file except in compliance with the
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * License.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * specific language governing permission and limitations under the License.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * When distributing Covered Software, include this CDDL Header Notice in each file and include
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Header, with the fields enclosed by brackets [] replaced by your own identifying
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * information: "Portions copyright [year] [name of copyright owner]".
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Copyright 2015 ForgeRock AS.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingspackage com.sun.identity.saml2.common;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport com.sun.identity.saml.common.SAMLConstants;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport com.sun.identity.shared.debug.Debug;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport com.sun.identity.shared.xml.XMLUtils;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport org.forgerock.openam.utils.StringUtils;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport org.w3c.dom.Document;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport org.w3c.dom.Element;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport org.w3c.dom.Node;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport org.w3c.dom.NodeList;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.servlet.http.HttpServletRequest;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.Detail;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.MessageFactory;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.MimeHeaders;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.SOAPConnection;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.SOAPConnectionFactory;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.SOAPConstants;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.SOAPElement;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.SOAPEnvelope;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.SOAPException;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.SOAPFault;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport javax.xml.soap.SOAPMessage;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport java.io.ByteArrayInputStream;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport java.io.ByteArrayOutputStream;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport java.io.IOException;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport java.io.InputStream;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport java.util.Enumeration;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingsimport java.util.StringTokenizer;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings/**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * The SOAPCommunicator is a utility package to assist in SAML2 communication over SOAP.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbingspublic class SOAPCommunicator {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings private static final Debug debug = Debug.getInstance("libSAML2");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings private SOAPConnectionFactory soapConnectionFactory; // TODO: use Guice
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings private MessageFactory messageFactory; // TODO: use Guice
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings private static SOAPCommunicator instance = new SOAPCommunicator(); // TODO: use Guice
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings private SOAPCommunicator() {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings try {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings soapConnectionFactory = SOAPConnectionFactory.newInstance();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings messageFactory = MessageFactory.newInstance();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings } catch (SOAPException se) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator: Unable to create SOAP MessageFactory", se);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Gets the singleton instance of the SOAPCommunicator.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return the SOAPCommunicator instance.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public static SOAPCommunicator getInstance() {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return instance;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Opens a SOAP Connection.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return a new <code>SOAPConnection</code>
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @throws if there was an exception creating the
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * <code>SOAPConnection</code> object.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public SOAPConnection openSOAPConnection() throws SOAPException {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return soapConnectionFactory.createConnection();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Creates <code>SOAPMessage</code> with the input XML String
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * as message body.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param xmlString XML string to be put into <code>SOAPMessage</code> body.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param isClientMessage true if the message is sent from SOAP client to
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * server.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return newly created <code>SOAPMessage</code>.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @throws SOAPException if it cannot create the
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * <code>SOAPMessage</code>.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public SOAPMessage createSOAPMessage(final String xmlString,
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings final boolean isClientMessage)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throws SOAPException, SAML2Exception {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return createSOAPMessage(null, xmlString, isClientMessage);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Creates <code>SOAPMessage</code> with the input XML String
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * as message header and body.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param header XML string to be put into <code>SOAPMessage</code> header.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param body XML string to be put into <code>SOAPMessage</code> body.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param isClientMessage true if the message is sent from SOAP client to
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * server.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return newly created <code>SOAPMessage</code>.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @throws SOAPException if it cannot create the <code>SOAPMessage</code>.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public SOAPMessage createSOAPMessage(final String header,
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings final String body,
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings final boolean isClientMessage)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throws SOAPException, SAML2Exception {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings try {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings MimeHeaders mimeHeaders = new MimeHeaders();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings mimeHeaders.addHeader("Content-Type", "text/xml");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (isClientMessage) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings mimeHeaders.addHeader("SOAPAction", "\"\"");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (debug.messageEnabled()) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.createSOAPMessage: header = " +
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings header + ", body = " + body);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings StringBuilder sb = new StringBuilder(500);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings sb.append("<").append(SAMLConstants.SOAP_ENV_PREFIX)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(":Envelope").append(SAMLConstants.SPACE)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append("xmlns:").append(SAMLConstants.SOAP_ENV_PREFIX)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append("=\"").append(SAMLConstants.SOAP_URI).append("\">");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (header != null) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings sb.append("<")
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(SAMLConstants.SOAP_ENV_PREFIX).append(":Header>")
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(header)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(SAMLConstants.START_END_ELEMENT)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(SAMLConstants.SOAP_ENV_PREFIX)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(":Header>");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (body != null) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings sb.append("<")
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(SAMLConstants.SOAP_ENV_PREFIX).append(":Body>")
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(body)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(SAMLConstants.START_END_ELEMENT)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(SAMLConstants.SOAP_ENV_PREFIX)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(":Body>");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings sb.append(SAMLConstants.START_END_ELEMENT)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(SAMLConstants.SOAP_ENV_PREFIX)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings .append(":Envelope>").append(SAMLConstants.NL);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (debug.messageEnabled()) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.createSOAPMessage: soap message = " +
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings sb.toString());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return messageFactory.createMessage(mimeHeaders, new ByteArrayInputStream(
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings sb.toString().getBytes(SAML2Constants.DEFAULT_ENCODING)));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings } catch (IOException io) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.createSOAPMessage: IOE", io);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(io.getMessage());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Returns SOAP body as DOM Element from SOAPMessage.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param message SOAPMessage object.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return SOAP body, return null if unable to get the SOAP body element.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public Element getSOAPBody(final SOAPMessage message)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throws SAML2Exception {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.getSOAPBody : start");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings // check the SOAP message for any SOAP
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings // related errors before passing control to SAML processor
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings try {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings message.writeTo(byteArrayOut);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings } catch (IOException ie) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.getSOAPBody : writeTo IO", ie);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(ie.getMessage());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings } catch (SOAPException se) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.getSOAPBody : writeTo SOAP", se);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(se.getMessage());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings ByteArrayInputStream byteArrayIn = new ByteArrayInputStream(byteArrayOut.toByteArray());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings Document doc = XMLUtils.toDOMDocument(byteArrayIn, debug);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings Element root = doc.getDocumentElement();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (debug.messageEnabled()) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.getSOAPBody : soap body =\n"
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings + XMLUtils.print((Node) root));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings String rootName = doc.getDocumentElement().getLocalName();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (StringUtils.isEmpty(rootName)) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.getSOAPBody : no local name");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(SAML2Utils.bundle.getString("missingLocalName"));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (!(rootName.equals("Envelope")) ||
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings (!(SAMLConstants.SOAP_URI.equals(root.getNamespaceURI())))) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.getSOAPBody : either root " +
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings "element is not Envelope or invalid name space or prefix");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSOAPElement"));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings NodeList nodeList = root.getChildNodes();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings int length = nodeList.getLength();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (length <= 0) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.getSOAPBody: no msg body");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(SAML2Utils.bundle.getString("missingSOAPBody"));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings for (int i = 0; i < length; i++) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings Node child = nodeList.item(i);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (child.getNodeType() != Node.ELEMENT_NODE) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.getSOAPBody: " + child);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings continue;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings String childName = child.getLocalName();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (debug.messageEnabled()) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.getSOAPBody: local name= " + childName);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (childName.equals("Body") && SAMLConstants.SOAP_URI.equals(child.getNamespaceURI())) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings // found the Body element
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return (Element) child;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(SAML2Utils.bundle.getString(
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings "missingSOAPBody"));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Forms a SOAP Fault and puts it in the SOAP Message Body.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param faultCode Fault code.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param faultString Fault string.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param detail Fault details.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return SOAP Fault in the SOAP Message Body or null if unable to generate the message.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public SOAPMessage createSOAPFault(final String faultCode,
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings final String faultString,
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings final String detail) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings try {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings SOAPMessage message = messageFactory.createMessage();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings SOAPFault fault = envelope.getBody().addFault();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings fault.setFaultCode(envelope.createName(faultCode, null, SOAPConstants.URI_NS_SOAP_ENVELOPE));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings fault.setFaultString(SAML2Utils.bundle.getString(faultString));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (StringUtils.isNotEmpty(detail)) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings Detail faultDetail = fault.addDetail();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings SOAPElement faultDetailEntry = (SOAPElement) faultDetail.addDetailEntry(envelope.createName(
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings "Problem"));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings faultDetailEntry.addAttribute(envelope.createName("details"), SAML2Utils.bundle.getString(detail));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return message;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings } catch (SOAPException e) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("createSOAPFault:", e);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return null;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Returns SOAP Message from <code>HttpServletRequest</code>.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param request <code>HttpServletRequest</code> includes SOAP Message.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return SOAPMessage if request include any soap message in the header.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @throws IOException if error in creating input stream.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @throws SOAPException if error in creating soap message.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public SOAPMessage getSOAPMessage(final HttpServletRequest request)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throws IOException, SOAPException {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings // Get all the headers from the HTTP request
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings MimeHeaders headers = getHeaders(request);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings // Get the body of the HTTP request
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings InputStream is = request.getInputStream();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings // Create a SOAPMessage
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return messageFactory.createMessage(headers, is);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Send SOAP Message to specified url and returns message from peer.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param xmlMessage <code>String</code> will be sent.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param soapUrl URL the mesaage send to.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param isClientMessage true if the message is sent from SOAP client to
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * server.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return SOAPMessage if the peer send back any reply.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @throws SOAPException if error in creating soap message.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @throws SAML2Exception if error in creating soap message.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public SOAPMessage sendSOAPMessage(final String xmlMessage,
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings final String soapUrl,
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings final boolean isClientMessage)
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throws SOAPException, SAML2Exception {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings SOAPConnection con = soapConnectionFactory.createConnection();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings SOAPMessage msg = createSOAPMessage(xmlMessage, isClientMessage);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return con.call(msg, soapUrl);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Converts a <code>SOAPMessage</code> to a <code>String</code>.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param message SOAPMessage object.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return the <code>String</code> converted from the
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * <code>SOAPMessage</code> or null if an error ocurred.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public String soapMessageToString(final SOAPMessage message) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings try {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings ByteArrayOutputStream bop = new ByteArrayOutputStream();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings message.writeTo(bop);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return new String(bop.toByteArray());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings } catch (IOException ie) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.soapMessageToString:", ie);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return null;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings } catch (SOAPException soapex) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.soapMessageToString:", soapex);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return null;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Returns first Element with given local name in samlp name space inside
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * SOAP message.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param message SOAP message.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param localName local name of the Element to be returned.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return first Element matching the local name.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @throws SAML2Exception if the Element could not be found or there is
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * SOAP Fault present.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public Element getSamlpElement(final SOAPMessage message,
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings final String localName) throws SAML2Exception {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings Element body = getSOAPBody(message);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings NodeList bodyChildNodes = body.getChildNodes();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings int childNodeLength = bodyChildNodes.getLength();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (childNodeLength <= 0) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.error("SOAPCommunicator.getSamlpElement: empty body");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(SAML2SDKUtils.bundle.getString("missingBody"));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings Element returnElement = null;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings Node node;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings for (int i = 0; i < childNodeLength; i++) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings node = bodyChildNodes.item(i);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (node.getNodeType() != Node.ELEMENT_NODE) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings continue;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings String nlName = node.getLocalName();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (debug.messageEnabled()) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.getSamlpElement: node={}, nsURI={}",
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings nlName, node.getNamespaceURI());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (nlName.equals("Fault")) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(SAML2Utils.bundle.getString(
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings "soapFaultInSOAPResponse"));
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings } else if (nlName.equals(localName) &&
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings SAML2Constants.PROTOCOL_NAMESPACE.equals(
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings node.getNamespaceURI())) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings returnElement = (Element) node;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings break;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (returnElement == null) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings throw new SAML2Exception(SAML2SDKUtils.bundle.getString("elementNotFound") +
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings localName);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return returnElement;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings /**
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * Returns mime headers in HTTP servlet request.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings *
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @param req HTTP servlet request.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings * @return mime headers in HTTP servlet request.
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings */
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings public MimeHeaders getHeaders(final HttpServletRequest req) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings Enumeration<String> e = req.getHeaderNames();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings MimeHeaders headers = new MimeHeaders();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings while (e.hasMoreElements()) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings String headerName = e.nextElement();
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings String headerValue = req.getHeader(headerName);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.getHeaders: Header name={}, value={}",
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings headerName, headerValue);
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings StringTokenizer values =
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings new StringTokenizer(headerValue, ",");
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings while (values.hasMoreTokens()) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings headers.addHeader(
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings headerName, values.nextToken().trim());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings if (debug.messageEnabled()) {
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings debug.message("SOAPCommunicator.getHeaders: Header=" + headers.toString());
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings return headers;
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings }
449854c2a07b50ea64d9d6a8b03d18d4afeeee43Ken Stubbings}