/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.wss4j.stax.impl.processor.input;

import java.security.Key;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Comment;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.ProcessingInstruction;

import org.apache.wss4j.binding.wss10.ObjectFactory;
import org.apache.wss4j.binding.wss10.SecurityTokenReferenceType;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.OpenSAMLUtil;
import org.apache.wss4j.common.saml.SamlAssertionWrapper;
import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
import org.apache.wss4j.stax.ext.WSSConstants;
import org.apache.wss4j.stax.ext.WSSSecurityProperties;
import org.apache.wss4j.stax.securityEvent.SamlTokenSecurityEvent;
import org.apache.wss4j.stax.securityEvent.SignedPartSecurityEvent;
import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
import org.apache.wss4j.stax.securityToken.SamlSecurityToken;
import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
import org.apache.wss4j.stax.utils.WSSUtils;
import org.apache.wss4j.stax.validate.SamlTokenValidator;
import org.apache.wss4j.stax.validate.SamlTokenValidatorImpl;
import org.apache.wss4j.stax.validate.TokenContext;
import org.apache.xml.security.binding.xmldsig.KeyInfoType;
import org.apache.xml.security.binding.xmldsig.KeyValueType;
import org.apache.xml.security.binding.xmldsig.X509DataType;
import org.apache.xml.security.binding.xmlenc.EncryptedKeyType;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.stax.config.JCEAlgorithmMapper;
import org.apache.xml.security.stax.ext.AbstractInputProcessor;
import org.apache.xml.security.stax.ext.AbstractInputSecurityHeaderHandler;
import org.apache.xml.security.stax.ext.InputProcessorChain;
import org.apache.xml.security.stax.ext.XMLSecurityConstants;
import org.apache.xml.security.stax.ext.XMLSecurityProperties;
import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
import org.apache.xml.security.stax.ext.stax.XMLSecNamespace;
import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
import org.apache.xml.security.stax.impl.XMLSecurityEventReader;
import org.apache.xml.security.stax.impl.securityToken.AbstractInboundSecurityToken;
import org.apache.xml.security.stax.impl.util.IDGenerator;
import org.apache.xml.security.stax.securityEvent.SecurityEvent;
import org.apache.xml.security.stax.securityEvent.SecurityEventListener;
import org.apache.xml.security.stax.securityEvent.SignedElementSecurityEvent;
import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
import org.apache.xml.security.stax.securityToken.SecurityToken;
import org.apache.xml.security.stax.securityToken.SecurityTokenConstants.TokenUsage;
import org.apache.xml.security.utils.XMLUtils;
import org.apache.xml.security.stax.securityToken.SecurityTokenFactory;
import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
import org.opensaml.security.credential.BasicCredential;
import org.opensaml.security.x509.BasicX509Credential;
import org.opensaml.xmlsec.signature.Signature;
import org.opensaml.xmlsec.signature.support.SignatureException;
import org.opensaml.xmlsec.signature.support.SignatureValidator;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Processor for the SAML Assertion XML Structure
 */
public class SAMLTokenInputHandler extends AbstractInputSecurityHeaderHandler {

    @Override
    public void handle(final InputProcessorChain inputProcessorChain, final XMLSecurityProperties securityProperties,
                       Deque<XMLSecEvent> eventQueue, Integer index) throws XMLSecurityException {

        final Document samlTokenDocument = (Document) parseStructure(eventQueue, index, securityProperties);

        final WSSSecurityProperties wssSecurityProperties = (WSSSecurityProperties) securityProperties;
        final WSInboundSecurityContext wsInboundSecurityContext = (WSInboundSecurityContext) inputProcessorChain.getSecurityContext();
        final Element samlElement = samlTokenDocument.getDocumentElement();
        final SamlAssertionWrapper samlAssertionWrapper = new SamlAssertionWrapper(samlElement);

        SamlTokenValidator samlTokenValidator =
            wssSecurityProperties.getValidator(new QName(samlElement.getNamespaceURI(), samlElement.getLocalName()));
        if (samlTokenValidator == null) {
            samlTokenValidator = new SamlTokenValidatorImpl();
        }

        //important: check the signature before we do other processing...
        if (samlAssertionWrapper.isSigned()) {
            Signature signature = samlAssertionWrapper.getSignature();
            if (signature == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN,
                        "empty", new Object[] {"no signature to validate"});
            }

            int sigKeyInfoIdx = getSignatureKeyInfoIndex(eventQueue);
            if (sigKeyInfoIdx < 0) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "noKeyInSAMLToken");
            }
            InboundSecurityToken sigSecurityToken = parseKeyInfo(inputProcessorChain, securityProperties, eventQueue, sigKeyInfoIdx);

            if (sigSecurityToken == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "noKeyInSAMLToken");
            }

            samlTokenValidator.validate(sigSecurityToken, wssSecurityProperties);

            BasicCredential credential = null;
            if (sigSecurityToken.getX509Certificates() != null) {
                credential = new BasicX509Credential(sigSecurityToken.getX509Certificates()[0]);
            } else if (sigSecurityToken.getPublicKey() != null) {
                credential = new BasicCredential(sigSecurityToken.getPublicKey());
            } else {
                throw new WSSecurityException(
                        WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity",
                        new Object[] {"cannot get certificate or key"}
                );
            }
            try {
                SignatureValidator.validate(signature, credential);
            } catch (SignatureException ex) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE,
                        ex, "empty", new Object[] {"SAML signature validation failed"});
            }
        }

        final InboundSecurityToken subjectSecurityToken;

        List<String> methods = samlAssertionWrapper.getConfirmationMethods();
        boolean holderOfKey = false;
        if (methods != null) {
            for (String method : methods) {
                if (OpenSAMLUtil.isMethodHolderOfKey(method)) {
                    holderOfKey = true;
                    break;
                }
            }
        }

        if (holderOfKey) {
            int subjectKeyInfoIndex = getSubjectKeyInfoIndex(eventQueue);
            if (subjectKeyInfoIndex < 0) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "noKeyInSAMLToken");
            }

            subjectSecurityToken = parseKeyInfo(inputProcessorChain, securityProperties, eventQueue, subjectKeyInfoIndex);
            if (subjectSecurityToken == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "noKeyInSAMLToken");
            }
        } else {
            subjectSecurityToken = null;
        }

        final List<XMLSecEvent> xmlSecEvents = getResponsibleXMLSecEvents(eventQueue, index);
        final List<QName> elementPath = getElementPath(eventQueue);
        final TokenContext tokenContext =
            new TokenContext(wssSecurityProperties, wsInboundSecurityContext, xmlSecEvents, elementPath);

        final SamlSecurityToken samlSecurityToken =
                samlTokenValidator.validate(samlAssertionWrapper, subjectSecurityToken, tokenContext);

        SecurityTokenProvider<InboundSecurityToken> subjectSecurityTokenProvider =
                new SecurityTokenProvider<InboundSecurityToken>() {

            @Override
            public InboundSecurityToken getSecurityToken() throws XMLSecurityException {
                return (InboundSecurityToken)samlSecurityToken;
            }

            @Override
            public String getId() {
                return samlAssertionWrapper.getId();
            }
        };

        wsInboundSecurityContext.registerSecurityTokenProvider(samlAssertionWrapper.getId(), subjectSecurityTokenProvider);

        //fire a tokenSecurityEvent
        SamlTokenSecurityEvent samlTokenSecurityEvent = new SamlTokenSecurityEvent();
        samlTokenSecurityEvent.setSecurityToken((SamlSecurityToken)subjectSecurityTokenProvider.getSecurityToken());
        samlTokenSecurityEvent.setCorrelationID(samlAssertionWrapper.getId());
        wsInboundSecurityContext.registerSecurityEvent(samlTokenSecurityEvent);

        if (wssSecurityProperties.isValidateSamlSubjectConfirmation()) {
            boolean soap12 = false;
            if (elementPath.get(0) != null && WSSConstants.NS_SOAP12.equals(elementPath.get(0).getNamespaceURI())) {
                soap12 = true;
            }
            SAMLTokenVerifierInputProcessor samlTokenVerifierInputProcessor =
                    new SAMLTokenVerifierInputProcessor(
                            securityProperties, samlAssertionWrapper, subjectSecurityTokenProvider, subjectSecurityToken,
                            soap12);
            wsInboundSecurityContext.addSecurityEventListener(samlTokenVerifierInputProcessor);
            inputProcessorChain.addProcessor(samlTokenVerifierInputProcessor);
        }
    }

    private int getSubjectKeyInfoIndex(Deque<XMLSecEvent> eventQueue) {
        int idx = -1;
        Iterator<XMLSecEvent> xmlSecEventIterator = eventQueue.descendingIterator();
        while (xmlSecEventIterator.hasNext()) {
            XMLSecEvent xmlSecEvent = xmlSecEventIterator.next();
            idx++;
            switch (xmlSecEvent.getEventType()) {
                case XMLStreamConstants.START_ELEMENT:
                    QName elementName = xmlSecEvent.asStartElement().getName();
                    if (WSSConstants.TAG_dsig_KeyInfo.equals(elementName)) {
                        List<QName> elementPath = xmlSecEvent.asStartElement().getElementPath();
                        if (elementPath.size() >= 4) {
                            int lastIndex = elementPath.size() - 2;
                            if ("SubjectConfirmationData".equals(elementPath.get(lastIndex).getLocalPart())
                                && "SubjectConfirmation".equals(elementPath.get(lastIndex - 1).getLocalPart())
                                && "Subject".equals(elementPath.get(lastIndex - 2).getLocalPart())) {
                                return idx;
                            } else if ("SubjectConfirmation".equals(elementPath.get(lastIndex).getLocalPart())
                                && "Subject".equals(elementPath.get(lastIndex - 1).getLocalPart())) {
                                return idx;
                            }
                        }
                    }
            }
        }
        return idx;
    }

    private int getSignatureKeyInfoIndex(Deque<XMLSecEvent> eventQueue) {
        int idx = -1;
        Iterator<XMLSecEvent> xmlSecEventIterator = eventQueue.descendingIterator();
        while (xmlSecEventIterator.hasNext()) {
            XMLSecEvent xmlSecEvent = xmlSecEventIterator.next();
            idx++;
            switch (xmlSecEvent.getEventType()) {
                case XMLStreamConstants.START_ELEMENT:
                    QName elementName = xmlSecEvent.asStartElement().getName();
                    if (WSSConstants.TAG_dsig_KeyInfo.equals(elementName)) {
                        List<QName> elementPath = xmlSecEvent.asStartElement().getElementPath();
                        if (elementPath.size() >= 4) {
                            int lastIndex = elementPath.size() - 2;
                            if ("Signature".equals(elementPath.get(lastIndex).getLocalPart())
                                && "Assertion".equals(elementPath.get(lastIndex - 1).getLocalPart())) {
                                return idx;
                            }
                        }
                    }
            }
        }
        return idx;
    }

    private InboundSecurityToken parseKeyInfo(InputProcessorChain inputProcessorChain, XMLSecurityProperties securityProperties,
                                       Deque<XMLSecEvent> eventQueue, int index) throws XMLSecurityException {
        XMLSecEvent xmlSecEvent = null;
        int idx = 0;
        Iterator<XMLSecEvent> xmlSecEventIterator = eventQueue.descendingIterator();
        while (xmlSecEventIterator.hasNext() && idx <= index) {
            xmlSecEvent = xmlSecEventIterator.next();
            idx++;
        }
        //forward to next start element
        while (xmlSecEventIterator.hasNext()) {
            xmlSecEvent = xmlSecEventIterator.next();
            if (xmlSecEvent.isStartElement()) {
                break;
            }
            idx++;
        }
        if (xmlSecEvent == null || !xmlSecEvent.isStartElement()) {
            throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, "noKeyInSAMLToken");
        }

        final XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
        final QName elementName = xmlSecStartElement.getName();
        if (WSSConstants.TAG_WST_BINARY_SECRET.equals(elementName)
            || WSSConstants.TAG_WST0512_BINARY_SECRET.equals(elementName)) {

            final StringBuilder stringBuilder = new StringBuilder();
            loop:
            while (xmlSecEventIterator.hasNext()) {
                xmlSecEvent = xmlSecEventIterator.next();
                switch (xmlSecEvent.getEventType()) {
                    case XMLStreamConstants.END_ELEMENT:
                        if (xmlSecEvent.asEndElement().getName().equals(elementName)) {
                            break loop;
                        }
                        break;
                    case XMLStreamConstants.CHARACTERS:
                        stringBuilder.append(xmlSecEvent.asCharacters().getText());
                        break;
                }
            }

            return new AbstractInboundSecurityToken(
                    inputProcessorChain.getSecurityContext(), IDGenerator.generateID(null),
                    WSSecurityTokenConstants.KeyIdentifier_NoKeyInfo, true) {
                @Override
                public WSSecurityTokenConstants.TokenType getTokenType() {
                    return WSSecurityTokenConstants.DefaultToken;
                }

                @Override
                public boolean isAsymmetric() throws XMLSecurityException {
                    return false;
                }

                @Override
                protected Key getKey(String algorithmURI, XMLSecurityConstants.AlgorithmUsage algorithmUsage, String correlationID)
                        throws XMLSecurityException {
                    Key key = super.getKey(algorithmURI, algorithmUsage, correlationID);
                    if (key == null) {
                        String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
                        key = new SecretKeySpec(XMLUtils.decode(stringBuilder.toString()), algoFamily);
                        setSecretKey(algorithmURI, key);
                    }
                    return key;
                }
            };
        } else {
            Object object = null;
            try {
                Unmarshaller unmarshaller = WSSConstants.getJaxbUnmarshaller(securityProperties.isDisableSchemaValidation());
                object = unmarshaller.unmarshal(new XMLSecurityEventReader(eventQueue, idx));
            } catch (JAXBException e) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN, e);
            }

            if (object instanceof JAXBElement) {
                object = ((JAXBElement<?>) object).getValue();
            }

            KeyInfoType keyInfoType = null;
            if (object instanceof X509DataType) {
                JAXBElement<X509DataType> x509DataTypeJAXBElement =
                        new org.apache.xml.security.binding.xmldsig.ObjectFactory().createX509Data((X509DataType) object);
                keyInfoType = new KeyInfoType();
                SecurityTokenReferenceType securityTokenReferenceType = new SecurityTokenReferenceType();
                securityTokenReferenceType.getAny().add(x509DataTypeJAXBElement);
                JAXBElement<SecurityTokenReferenceType> securityTokenReferenceTypeJAXBElement =
                        new ObjectFactory().createSecurityTokenReference(securityTokenReferenceType);
                keyInfoType.getContent().add(securityTokenReferenceTypeJAXBElement);
            } else if (object instanceof EncryptedKeyType) {
                EncryptedKeyType encryptedKeyType = (EncryptedKeyType) object;

                WSSEncryptedKeyInputHandler encryptedKeyInputHandler = new WSSEncryptedKeyInputHandler();
                encryptedKeyInputHandler.handle(inputProcessorChain, encryptedKeyType, xmlSecStartElement, securityProperties);

                SecurityTokenProvider<? extends InboundSecurityToken> securityTokenProvider =
                    inputProcessorChain.getSecurityContext().getSecurityTokenProvider(encryptedKeyType.getId());
                if (securityTokenProvider != null) {
                    return securityTokenProvider.getSecurityToken();
                }

            } else if (object instanceof SecurityTokenReferenceType) {
                JAXBElement<SecurityTokenReferenceType> securityTokenReferenceTypeJAXBElement =
                        new ObjectFactory().createSecurityTokenReference((SecurityTokenReferenceType) object);
                keyInfoType = new KeyInfoType();
                keyInfoType.getContent().add(securityTokenReferenceTypeJAXBElement);
            } else if (object instanceof KeyValueType) {
                JAXBElement<KeyValueType> keyValueTypeJAXBElement =
                        new org.apache.xml.security.binding.xmldsig.ObjectFactory().createKeyValue((KeyValueType) object);
                keyInfoType = new KeyInfoType();
                keyInfoType.getContent().add(keyValueTypeJAXBElement);
            } else {
                throw new WSSecurityException(WSSecurityException.ErrorCode.UNSUPPORTED_SECURITY_TOKEN, "unsupportedKeyInfo");
            }

            return SecurityTokenFactory.getInstance().getSecurityToken(
                    keyInfoType, WSSecurityTokenConstants.KeyUsage_Signature_Verification,
                    securityProperties, inputProcessorChain.getSecurityContext());
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    protected <T> T parseStructure(Deque<XMLSecEvent> eventDeque, int index, XMLSecurityProperties securityProperties)
            throws XMLSecurityException {
        Document document = null;
        try {
            document = ((WSSSecurityProperties) securityProperties).getDocumentCreator().newDocument();
        } catch (ParserConfigurationException e) {
            throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN, e);
        }

        Iterator<XMLSecEvent> xmlSecEventIterator = eventDeque.descendingIterator();
        int curIdx = 0;
        while (curIdx++ < index) {
            xmlSecEventIterator.next();
        }

        Node currentNode = document;
        while (xmlSecEventIterator.hasNext()) {
            XMLSecEvent next = xmlSecEventIterator.next();
            currentNode = parseXMLEvent(next, currentNode, document);
        }
        return (T) document;
    }

    //todo custom SAML unmarshaller directly to XMLObject?
    public Node parseXMLEvent(XMLSecEvent xmlSecEvent, Node currentNode, Document document) throws WSSecurityException {
        switch (xmlSecEvent.getEventType()) {
            case XMLStreamConstants.START_ELEMENT:
                XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
                Element element = document.createElementNS(xmlSecStartElement.getName().getNamespaceURI(),
                        xmlSecStartElement.getName().getLocalPart());
                if (xmlSecStartElement.getName().getPrefix() != null && !xmlSecStartElement.getName().getPrefix().isEmpty()) {
                    element.setPrefix(xmlSecStartElement.getName().getPrefix());
                }
                currentNode = currentNode.appendChild(element);
                @SuppressWarnings("unchecked")
                Iterator<Namespace> namespaceIterator = xmlSecStartElement.getNamespaces();
                while (namespaceIterator.hasNext()) {
                    XMLSecNamespace next = (XMLSecNamespace)namespaceIterator.next();
                    parseXMLEvent(next, currentNode, document);
                }
                @SuppressWarnings("unchecked")
                Iterator<Attribute> attributesIterator = xmlSecStartElement.getAttributes();
                while (attributesIterator.hasNext()) {
                    XMLSecAttribute next = (XMLSecAttribute)attributesIterator.next();
                    parseXMLEvent(next, currentNode, document);
                }
                //add namespace which is not declared on current element but must be on a parent element:
                String elementNs = document.lookupNamespaceURI(xmlSecStartElement.getName().getPrefix());
                if (elementNs == null) {
                    parseXMLEvent(xmlSecStartElement.getElementNamespace(), currentNode, document);
                }
                break;
            case XMLStreamConstants.END_ELEMENT:
                if (currentNode.getParentNode() != null) {
                    currentNode = currentNode.getParentNode();
                }
                break;
            case XMLStreamConstants.PROCESSING_INSTRUCTION:
                Node piNode = document.createProcessingInstruction(
                        ((ProcessingInstruction) xmlSecEvent).getTarget(),
                        ((ProcessingInstruction) xmlSecEvent).getTarget()
                );
                currentNode.appendChild(piNode);
                break;
            case XMLStreamConstants.CHARACTERS:
                Node characterNode = document.createTextNode(xmlSecEvent.asCharacters().getData());
                currentNode.appendChild(characterNode);
                break;
            case XMLStreamConstants.COMMENT:
                Node commentNode = document.createComment(((Comment) xmlSecEvent).getText());
                currentNode.appendChild(commentNode);
                break;
            case XMLStreamConstants.START_DOCUMENT:
                break;
            case XMLStreamConstants.END_DOCUMENT:
                return currentNode;
            case XMLStreamConstants.ATTRIBUTE:
                final XMLSecAttribute xmlSecAttribute = (XMLSecAttribute) xmlSecEvent;
                Attr attributeNode = document.createAttributeNS(
                        xmlSecAttribute.getName().getNamespaceURI(),
                        xmlSecAttribute.getName().getLocalPart());
                attributeNode.setPrefix(xmlSecAttribute.getName().getPrefix());
                attributeNode.setValue(xmlSecAttribute.getValue());
                ((Element) currentNode).setAttributeNodeNS(attributeNode);

                //add namespace which is not declared on current element but must be on a parent element:
                String attrNs = document.lookupNamespaceURI(xmlSecAttribute.getName().getPrefix());
                if (attrNs == null) {
                    parseXMLEvent(xmlSecAttribute.getAttributeNamespace(), currentNode, document);
                }
                break;
            case XMLStreamConstants.DTD:
                //todo?:
                /*
                Node dtdNode = document.getDoctype().getEntities()
                ((DTD)xmlSecEvent).getDocumentTypeDeclaration():
                ((DTD)xmlSecEvent).getEntities()
                */
                break;
            case XMLStreamConstants.NAMESPACE:
                Namespace namespace = (Namespace) xmlSecEvent;
                Attr namespaceNode;
                String prefix = namespace.getPrefix();
                if (prefix == null || prefix.isEmpty()) {
                    namespaceNode = document.createAttributeNS(WSSConstants.NS_XML, "xmlns");
                } else {
                    namespaceNode = document.createAttributeNS(WSSConstants.NS_XML, "xmlns:" + prefix);
                }
                namespaceNode.setValue(namespace.getNamespaceURI());
                ((Element) currentNode).setAttributeNodeNS(namespaceNode);
                break;
            default:
                throw new WSSecurityException(
                        WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN,
                        "empty",
                        new Object[] {"Illegal XMLEvent received: " + xmlSecEvent.getEventType()});
        }
        return currentNode;
    }

    /**
     * Processor to check the holder-of-key or sender-vouches requirements against the received assertion
     * which can not be done until the whole soap-header is processed and we know that the whole soap-body
     * is signed.
     */
    static class SAMLTokenVerifierInputProcessor extends AbstractInputProcessor implements SecurityEventListener {

        private SamlAssertionWrapper samlAssertionWrapper;
        private SecurityTokenProvider<InboundSecurityToken> securityTokenProvider;
        private InboundSecurityToken subjectSecurityToken;
        private List<SignedElementSecurityEvent> samlTokenSignedElementSecurityEvents = new ArrayList<>();
        private SignedPartSecurityEvent bodySignedPartSecurityEvent;

        private final boolean soap12;
        private final List<QName> saml1TokenPath;
        private final List<QName> saml2TokenPath;

        SAMLTokenVerifierInputProcessor(XMLSecurityProperties securityProperties,
                                        SamlAssertionWrapper samlAssertionWrapper,
                                        SecurityTokenProvider<InboundSecurityToken> securityTokenProvider,
                                        InboundSecurityToken subjectSecurityToken,
                                        boolean soap12) {
            super(securityProperties);
            this.setPhase(XMLSecurityConstants.Phase.POSTPROCESSING);
            this.addAfterProcessor(OperationInputProcessor.class.getName());
            this.samlAssertionWrapper = samlAssertionWrapper;
            this.securityTokenProvider = securityTokenProvider;
            this.subjectSecurityToken = subjectSecurityToken;

            this.soap12 = soap12;
            if (soap12) {
                saml1TokenPath = new ArrayList<>(WSSConstants.SOAP_12_WSSE_SECURITY_HEADER_PATH);
                saml1TokenPath.add(WSSConstants.TAG_SAML_ASSERTION);
                saml2TokenPath = new ArrayList<>(WSSConstants.SOAP_12_WSSE_SECURITY_HEADER_PATH);
                saml2TokenPath.add(WSSConstants.TAG_SAML2_ASSERTION);
            } else {
                saml1TokenPath = new ArrayList<>(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
                saml1TokenPath.add(WSSConstants.TAG_SAML_ASSERTION);
                saml2TokenPath = new ArrayList<>(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
                saml2TokenPath.add(WSSConstants.TAG_SAML2_ASSERTION);
            }
        }

        @Override
        public void registerSecurityEvent(SecurityEvent securityEvent) throws XMLSecurityException {
            if (WSSecurityEventConstants.SIGNED_PART.equals(securityEvent.getSecurityEventType())) {
                SignedPartSecurityEvent signedPartSecurityEvent = (SignedPartSecurityEvent) securityEvent;

                List<QName> elementPath = signedPartSecurityEvent.getElementPath();
                if (soap12 && WSSUtils.pathMatches(WSSConstants.SOAP_12_BODY_PATH, elementPath)
                    || !soap12 && WSSUtils.pathMatches(WSSConstants.SOAP_11_BODY_PATH, elementPath)) {
                    bodySignedPartSecurityEvent = signedPartSecurityEvent;
                }
            } else if (WSSecurityEventConstants.SignedElement.equals(securityEvent.getSecurityEventType())) {
                SignedElementSecurityEvent signedPartSecurityEvent = (SignedElementSecurityEvent) securityEvent;

                List<QName> elementPath = signedPartSecurityEvent.getElementPath();
                if (WSSUtils.pathMatches(saml2TokenPath, elementPath)
                    || WSSUtils.pathMatches(saml1TokenPath, elementPath)) {
                    samlTokenSignedElementSecurityEvents.add(signedPartSecurityEvent);
                }
            }
        }

        @Override
        public XMLSecEvent processHeaderEvent(InputProcessorChain inputProcessorChain)
                throws XMLStreamException, XMLSecurityException {
            return inputProcessorChain.processHeaderEvent();
        }

        @Override
        public XMLSecEvent processEvent(InputProcessorChain inputProcessorChain)
                throws XMLStreamException, XMLSecurityException {

            XMLSecEvent xmlSecEvent = inputProcessorChain.processEvent();
            if (xmlSecEvent.getEventType() == XMLStreamConstants.START_ELEMENT) {
                XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
                List<QName> elementPath = xmlSecStartElement.getElementPath();
                if (elementPath.size() == 3 && WSSUtils.isInSOAPBody(elementPath)) {
                    inputProcessorChain.removeProcessor(this);
                    checkPossessionOfKey(inputProcessorChain, samlAssertionWrapper, subjectSecurityToken);
                }
            }
            return xmlSecEvent;
        }

        private void checkPossessionOfKey(
                InputProcessorChain inputProcessorChain, SamlAssertionWrapper samlAssertionWrapper,
                InboundSecurityToken subjectSecurityToken) throws WSSecurityException {

            boolean methodNotSatisfied = false;
            try {
                SecurityToken httpsSecurityToken = getHttpsSecurityToken(inputProcessorChain);

                List<SecurityTokenProvider<? extends InboundSecurityToken>> securityTokenProviders =
                        inputProcessorChain.getSecurityContext().getRegisteredSecurityTokenProviders();

                List<String> confirmationMethods = samlAssertionWrapper.getConfirmationMethods();
                for (int i = 0; i < confirmationMethods.size(); i++) {
                    String confirmationMethod = confirmationMethods.get(i);
                    if (OpenSAMLUtil.isMethodHolderOfKey(confirmationMethod)) {

                        X509Certificate[] subjectCertificates = subjectSecurityToken.getX509Certificates();
                        PublicKey subjectPublicKey = subjectSecurityToken.getPublicKey();
                        Key subjectSecretKey = null;
                        Map<String, Key> subjectKeyMap = subjectSecurityToken.getSecretKey();
                        if (!subjectKeyMap.isEmpty()) {
                            subjectSecretKey = subjectKeyMap.values().toArray(new Key[subjectKeyMap.size()])[0];
                        }

                        /**
                         * Check the holder-of-key requirements against the received assertion. The subject
                         * credential of the SAML Assertion must have been used to sign some portion of
                         * the message, thus showing proof-of-possession of the private/secret key. Alternatively,
                         * the subject credential of the SAML Assertion must match a client certificate credential
                         * when 2-way TLS is used.
                         */

                        //compare https token first:
                        if (httpsSecurityToken != null
                                && httpsSecurityToken.getX509Certificates() != null
                                && httpsSecurityToken.getX509Certificates().length > 0) {

                            X509Certificate httpsCertificate = httpsSecurityToken.getX509Certificates()[0];

                            //compare certificates:
                            if (subjectCertificates != null && subjectCertificates.length > 0
                                    && httpsCertificate.equals(subjectCertificates[0])) {
                                return;
                                //compare public keys:
                            } else if (httpsCertificate.getPublicKey().equals(subjectPublicKey)) {
                                return;
                            }
                        }

                        // Now try message signatures
                        for (int j = 0; j < securityTokenProviders.size(); j++) {
                            SecurityTokenProvider<? extends InboundSecurityToken> securityTokenProvider = securityTokenProviders.get(j);
                            InboundSecurityToken securityToken = securityTokenProvider.getSecurityToken();
                            // Don't compare to the original SAML Token credentials...
                            if (securityToken == httpsSecurityToken || securityToken == subjectSecurityToken
                                || !containsSignature(securityToken.getTokenUsages())) {
                                continue;
                            }
                            X509Certificate[] x509Certificates = securityToken.getX509Certificates();
                            PublicKey publicKey = securityToken.getPublicKey();
                            Map<String, Key> keyMap = securityToken.getSecretKey();
                            if (x509Certificates != null && x509Certificates.length > 0
                                && subjectCertificates != null && subjectCertificates.length > 0
                                && subjectCertificates[0].equals(x509Certificates[0])) {
                                return;
                            }
                            if (publicKey != null && publicKey.equals(subjectPublicKey)) {
                                return;
                            }
                            Iterator<Map.Entry<String, Key>> iterator = keyMap.entrySet().iterator();
                            while (iterator.hasNext()) {
                                Map.Entry<String, Key> next = iterator.next();
                                if (next.getValue().equals(subjectSecretKey)) {
                                    return;
                                }
                            }
                        }
                        methodNotSatisfied = true;
                    } else if (OpenSAMLUtil.isMethodSenderVouches(confirmationMethod)) {
                        /**
                         * Check the sender-vouches requirements against the received assertion. The SAML
                         * Assertion and the SOAP Body must be signed by the same signature.
                         */

                        //
                        // If we have a 2-way TLS connection, then we don't have to check that the
                        // assertion + SOAP body are signed
                        if (httpsSecurityToken != null
                                && httpsSecurityToken.getX509Certificates() != null
                                && httpsSecurityToken.getX509Certificates().length > 0) {
                            return;
                        }

                        SignedElementSecurityEvent samlTokenSignedElementSecurityEvent = null;
                        for (int j = 0; j < samlTokenSignedElementSecurityEvents.size(); j++) {
                            SignedElementSecurityEvent signedElementSecurityEvent = samlTokenSignedElementSecurityEvents.get(j);
                            if (securityTokenProvider.getSecurityToken().getXMLSecEvent()
                                == signedElementSecurityEvent.getXmlSecEvent()) {

                                samlTokenSignedElementSecurityEvent = signedElementSecurityEvent;
                            }
                        }
                        if (bodySignedPartSecurityEvent != null
                            && samlTokenSignedElementSecurityEvent != null
                            && bodySignedPartSecurityEvent.getSecurityToken()
                                == samlTokenSignedElementSecurityEvent.getSecurityToken()) {
                            return;
                        }
                        methodNotSatisfied = true;
                    }
                }
            } catch (XMLSecurityException e) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, e);
            }
            if (methodNotSatisfied) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION,
                    "empty",
                    new Object[] {"SAML proof-of-possession of the private/secret key failed"});
            }
        }

        private SecurityToken getHttpsSecurityToken(InputProcessorChain inputProcessorChain) throws XMLSecurityException {
            List<SecurityTokenProvider<? extends InboundSecurityToken>> securityTokenProviders =
                    inputProcessorChain.getSecurityContext().getRegisteredSecurityTokenProviders();
            for (int i = 0; i < securityTokenProviders.size(); i++) {
                SecurityTokenProvider<? extends InboundSecurityToken> securityTokenProvider = securityTokenProviders.get(i);
                SecurityToken securityToken = securityTokenProvider.getSecurityToken();
                if (WSSecurityTokenConstants.HTTPS_TOKEN.equals(securityToken.getTokenType())) {
                    return securityToken;
                }
            }
            return null;
        }

        private boolean containsSignature(List<TokenUsage> tokenUses) {
            return tokenUses.contains(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE)
                || tokenUses.contains(WSSecurityTokenConstants.TokenUsage_Signature)
                || tokenUses.contains(WSSecurityTokenConstants.TOKENUSAGE_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS)
                || tokenUses.contains(WSSecurityTokenConstants.TOKENUSAGE_ENDORSING_SUPPORTING_TOKENS)
                || tokenUses.contains(WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENDORSING_ENCRYPTED_SUPPORTING_TOKENS)
                || tokenUses.contains(WSSecurityTokenConstants.TOKENUSAGE_SIGNED_ENDORSING_SUPPORTING_TOKENS);
        }
    }
}
