/**
 * 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.dom.util;

import org.apache.wss4j.common.ext.Attachment;
import org.apache.wss4j.common.ext.AttachmentRequestCallback;
import org.apache.wss4j.common.ext.AttachmentResultCallback;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.util.AttachmentUtils;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.WSDataRef;
import org.apache.wss4j.dom.WSDocInfo;
import org.apache.wss4j.dom.callback.CallbackLookup;
import org.apache.xml.security.algorithms.JCEMapper;
import org.apache.xml.security.encryption.Serializer;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.encryption.XMLEncryptionException;
import org.apache.xml.security.parser.XMLParserException;
import org.apache.xml.security.utils.JavaUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.parsers.ParserConfigurationException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.util.List;

public final class EncryptionUtils {

    private EncryptionUtils() {
        // complete
    }

    /**
     * Look up the encrypted data. First try Id="someURI". If no such Id then try
     * wsu:Id="someURI".
     *
     * @param doc The document in which to find EncryptedData
     * @param wsDocInfo The WSDocInfo object to use
     * @param dataRefURI The URI of EncryptedData
     * @return The EncryptedData element
     * @throws WSSecurityException if the EncryptedData element referenced by dataRefURI is
     * not found
     */
    public static Element
    findEncryptedDataElement(
        Document doc,
        WSDocInfo wsDocInfo,
        String dataRefURI
    ) throws WSSecurityException {
        CallbackLookup callbackLookup = wsDocInfo.getCallbackLookup();
        Element encryptedDataElement =
            callbackLookup.getElement(dataRefURI, null, true);
        if (encryptedDataElement == null) {
            throw new WSSecurityException(
                WSSecurityException.ErrorCode.INVALID_SECURITY, "dataRef",
                new Object[] {dataRefURI});
        }
        if (encryptedDataElement.getLocalName().equals(WSConstants.ENCRYPTED_HEADER)
            && encryptedDataElement.getNamespaceURI().equals(WSConstants.WSSE11_NS)) {
            Node child = encryptedDataElement.getFirstChild();
            while (child != null && child.getNodeType() != Node.ELEMENT_NODE) {
                child = child.getNextSibling();
            }
            return (Element)child;
        }
        return encryptedDataElement;
    }

    /**
     * Decrypt the EncryptedData argument using a SecretKey.
     * @param doc The (document) owner of EncryptedData
     * @param dataRefURI The URI of EncryptedData
     * @param encData The EncryptedData element
     * @param symmetricKey The SecretKey with which to decrypt EncryptedData
     * @param symEncAlgo The symmetric encryption algorithm to use
     * @param attachmentCallbackHandler The CallbackHandler from which to get attachments
     * @throws WSSecurityException
     */
    public static WSDataRef
    decryptEncryptedData(
        Document doc,
        String dataRefURI,
        Element encData,
        SecretKey symmetricKey,
        String symEncAlgo,
        CallbackHandler attachmentCallbackHandler
    ) throws WSSecurityException {
        return decryptEncryptedData(doc, dataRefURI, encData, symmetricKey,
                                    symEncAlgo, attachmentCallbackHandler, null);

    }
    /**
     * Decrypt the EncryptedData argument using a SecretKey.
     * @param doc The (document) owner of EncryptedData
     * @param dataRefURI The URI of EncryptedData
     * @param encData The EncryptedData element
     * @param symmetricKey The SecretKey with which to decrypt EncryptedData
     * @param symEncAlgo The symmetric encryption algorithm to use
     * @param attachmentCallbackHandler The CallbackHandler from which to get attachments
     * @throws WSSecurityException
     */
    public static WSDataRef
    decryptEncryptedData(
        Document doc,
        String dataRefURI,
        Element encData,
        SecretKey symmetricKey,
        String symEncAlgo,
        CallbackHandler attachmentCallbackHandler,
        Serializer encryptionSerializer
    ) throws WSSecurityException {

        // See if it is an attachment, and handle that differently
        String typeStr = encData.getAttributeNS(null, "Type");
        String xopURI = getXOPURIFromEncryptedData(encData);
        if (typeStr != null
            && (WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_CONTENT_ONLY.equals(typeStr)
                || WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr))) {

            Element cipherData = XMLUtils.getDirectChildElement(encData, "CipherData", WSConstants.ENC_NS);
            if (cipherData == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
            }
            Element cipherReference = XMLUtils.getDirectChildElement(cipherData, "CipherReference", WSConstants.ENC_NS);
            if (cipherReference == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
            }
            String uri = cipherReference.getAttributeNS(null, "URI");

            return decryptAttachment(dataRefURI, uri, encData, symmetricKey, symEncAlgo, attachmentCallbackHandler);
        }

        WSDataRef dataRef = new WSDataRef();
        dataRef.setEncryptedElement(encData);
        dataRef.setWsuId(dataRefURI);
        dataRef.setAlgorithm(symEncAlgo);

        boolean content = X509Util.isContent(encData);
        dataRef.setContent(content);

        Element encDataOrig = encData;
        Node parent = encData.getParentNode();
        Node previousSibling = encData.getPreviousSibling();
        if (content) {
            encData = (Element) encData.getParentNode();
            parent = encData.getParentNode();
        }

        XMLCipher xmlCipher = null;
        try {
            if (encryptionSerializer != null) {
                xmlCipher = XMLCipher.getInstance(symEncAlgo, encryptionSerializer);
            } else {
                xmlCipher = XMLCipher.getInstance(symEncAlgo);
            }
            xmlCipher.setSecureValidation(true);
            xmlCipher.init(XMLCipher.DECRYPT_MODE, symmetricKey);
        } catch (XMLEncryptionException ex) {
            throw new WSSecurityException(
                    WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, ex
            );
        }

        Node decryptedNode = null;
        try {
            if (xopURI != null) {
                Element tempEncData;

                //if content == true, use encDataOrig (i.e., actual EncryptedData element instead of parent)
                //We will replace the EncryptedData element itself with the decrypted data found in attachment
                if (content) {
                    tempEncData = encDataOrig;
                } else {
                    tempEncData = encData;
                }
                decryptedNode = decryptXopAttachment(symmetricKey, symEncAlgo, attachmentCallbackHandler,
                                                     xopURI, tempEncData);
            } else {
                //in this case, the XMLCipher knows how to handle encData when it's the parent node
                // (i.e., when content == true)
                xmlCipher.doFinal(doc, encData, content);
            }
        } catch (Exception ex) {
            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
        }

        if (parent.getLocalName().equals(WSConstants.ENCRYPTED_HEADER)
            && parent.getNamespaceURI().equals(WSConstants.WSSE11_NS)
            || parent.getLocalName().equals(WSConstants.ENCRYPED_ASSERTION_LN)
            && parent.getNamespaceURI().equals(WSConstants.SAML2_NS)) {

            Node decryptedHeader = parent.getFirstChild();
            Node soapHeader = parent.getParentNode();
            soapHeader.replaceChild(decryptedHeader, parent);

            dataRef.setProtectedElement((Element)decryptedHeader);
            dataRef.setXpath(getXPath(decryptedHeader));
        } else if (content) {
            dataRef.setProtectedElement(encData);
            dataRef.setXpath(getXPath(encData));
        } else {
            if (decryptedNode == null) {
                if (previousSibling == null) {
                    decryptedNode = parent.getFirstChild();
                } else {
                    decryptedNode = previousSibling.getNextSibling();
                }
            }
            if (decryptedNode != null && Node.ELEMENT_NODE == decryptedNode.getNodeType()) {
                dataRef.setProtectedElement((Element)decryptedNode);
            }
            dataRef.setXpath(getXPath(decryptedNode));
        }

        return dataRef;
    }

    private static String getXOPURIFromEncryptedData(Element encData) {
        Element cipherValue = getCipherValueFromEncryptedData(encData);
        if (cipherValue != null) {
            return getXOPURIFromCipherValue(cipherValue);
        }

        return null;
    }

    public static Element getCipherValueFromEncryptedData(Element encData) {
        Element cipherData = XMLUtils.getDirectChildElement(encData, "CipherData", WSConstants.ENC_NS);
        if (cipherData != null) {
            return XMLUtils.getDirectChildElement(cipherData, "CipherValue", WSConstants.ENC_NS);
        }

        return null;
    }

    public static String getXOPURIFromCipherValue(Element cipherValue) {
        if (cipherValue != null) {
            Element cipherValueChild =
                XMLUtils.getDirectChildElement(cipherValue, "Include", WSConstants.XOP_NS);
            if (cipherValueChild != null && cipherValueChild.hasAttributeNS(null, "href")) {
                return cipherValueChild.getAttributeNS(null, "href");
            }
        }

        return null;
    }


    private static WSDataRef
    decryptAttachment(
        String dataRefURI,
        String uri,
        Element encData,
        SecretKey symmetricKey,
        String symEncAlgo,
        CallbackHandler attachmentCallbackHandler
    ) throws WSSecurityException {
        WSDataRef dataRef = new WSDataRef();
        dataRef.setWsuId(dataRefURI);
        dataRef.setAlgorithm(symEncAlgo);

        try {
            if (uri == null || uri.length() < 5 || !uri.startsWith("cid:")) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
            }
            dataRef.setWsuId(uri);
            dataRef.setAttachment(true);

            if (attachmentCallbackHandler == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
            }

            final String attachmentId = AttachmentUtils.getAttachmentId(uri);

            AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
            attachmentRequestCallback.setAttachmentId(attachmentId);

            attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
            List<Attachment> attachments = attachmentRequestCallback.getAttachments();
            if (attachments == null || attachments.isEmpty() || !attachmentId.equals(attachments.get(0).getId())) {
                throw new WSSecurityException(
                        WSSecurityException.ErrorCode.INVALID_SECURITY,
                        "empty", new Object[] {"Attachment not found"}
                );
            }
            Attachment attachment = attachments.get(0);

            final String encAlgo = X509Util.getEncAlgo(encData);
            final String jceAlgorithm =
                    JCEMapper.translateURItoJCEID(encAlgo);
            final Cipher cipher = Cipher.getInstance(jceAlgorithm);

            InputStream attachmentInputStream =
                    AttachmentUtils.setupAttachmentDecryptionStream(
                            encAlgo, cipher, symmetricKey, attachment.getSourceStream());

            Attachment resultAttachment = new Attachment();
            resultAttachment.setId(attachment.getId());
            resultAttachment.setMimeType(encData.getAttributeNS(null, "MimeType"));
            resultAttachment.setSourceStream(attachmentInputStream);
            resultAttachment.addHeaders(attachment.getHeaders());

            String typeStr = encData.getAttributeNS(null, "Type");
            if (WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr)) {
                AttachmentUtils.readAndReplaceEncryptedAttachmentHeaders(
                        resultAttachment.getHeaders(), attachmentInputStream);
            }

            AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
            attachmentResultCallback.setAttachment(resultAttachment);
            attachmentResultCallback.setAttachmentId(resultAttachment.getId());
            attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});

        } catch (UnsupportedCallbackException | IOException
            | NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new WSSecurityException(
                    WSSecurityException.ErrorCode.FAILED_CHECK, e);
        }

        dataRef.setContent(true);
        // Remove this EncryptedData from the security header to avoid processing it again
        encData.getParentNode().removeChild(encData);

        return dataRef;
    }


    private static Node decryptXopAttachment(
       SecretKey symmetricKey, String symEncAlgo, CallbackHandler attachmentCallbackHandler,
       String xopURI, Element encData
   ) throws WSSecurityException, IOException, UnsupportedCallbackException, NoSuchAlgorithmException,
        NoSuchPaddingException, ParserConfigurationException, XMLParserException {

        if (attachmentCallbackHandler == null) {
            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
        }
        final String attachmentId = AttachmentUtils.getAttachmentId(xopURI);

        AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
        attachmentRequestCallback.setAttachmentId(attachmentId);

        attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
        List<Attachment> attachments = attachmentRequestCallback.getAttachments();
        if (attachments == null || attachments.isEmpty() || !attachmentId.equals(attachments.get(0).getId())) {
            throw new WSSecurityException(
                    WSSecurityException.ErrorCode.INVALID_SECURITY,
                    "empty", new Object[] {"Attachment not found"}
            );
        }
        Attachment attachment = attachments.get(0);

        final String jceAlgorithm =
                JCEMapper.translateURItoJCEID(symEncAlgo);
        final Cipher cipher = Cipher.getInstance(jceAlgorithm);

        InputStream attachmentInputStream =
                AttachmentUtils.setupAttachmentDecryptionStream(
                        symEncAlgo, cipher, symmetricKey, attachment.getSourceStream());

        // For the xop:Include case, we need to replace the xop:Include Element with the
        // decrypted Element
        byte[] bytes = JavaUtils.getBytesFromStream(attachmentInputStream);

        Document document = null;
        try {
            document = org.apache.xml.security.utils.XMLUtils.read(new ByteArrayInputStream(bytes), true);
        } catch (XMLParserException ex) {
            if (ex.getCause() instanceof SAXException) {
                // A prefix may not have been bound, try to fix the DOM Element in this case.
                String fixedElementStr = setParentPrefixes(encData, new String(bytes));
                document = org.apache.xml.security.utils.XMLUtils.read(
                    new ByteArrayInputStream(fixedElementStr.getBytes()), true);
            }
        }

        Node decryptedNode =
            encData.getOwnerDocument().importNode(document.getDocumentElement(), true);
        encData.getParentNode().appendChild(decryptedNode);
        encData.getParentNode().removeChild(encData);
        return decryptedNode;
    }

    /**
     * Set the parent prefix definitions on the "String" (representation of the Element to be parsed)
     */
    private static String setParentPrefixes(Element target, String str) {
        Node parent = target;

        // Get the point at where to insert new prefix definitions
        int insertionIndex = str.indexOf('>');
        StringBuilder prefix = new StringBuilder(str.substring(0, insertionIndex));
        StringBuilder suffix = new StringBuilder(str.substring(insertionIndex, str.length()));

        // Don't add more than 20 prefixes
        int prefixAddedCount = 0;
        while (parent.getParentNode() != null && prefixAddedCount < 20
            && !(Node.DOCUMENT_NODE == parent.getParentNode().getNodeType())) {
            parent = parent.getParentNode();
            NamedNodeMap attributes = parent.getAttributes();
            int length = attributes.getLength();
            for (int i = 0; i < length; i++) {
                Node attribute = attributes.item(i);
                String attrDef = "xmlns:" + attribute.getLocalName();
                if (WSConstants.XMLNS_NS.equals(attribute.getNamespaceURI()) && !prefix.toString().contains(attrDef)) {
                    attrDef += "=\"" + attribute.getNodeValue() + "\"";
                    prefix.append(" " + attrDef);
                    prefixAddedCount++;
                }
                if (prefixAddedCount >= 20) {
                    break;
                }
            }
        }

        return prefix.toString() + suffix.toString();
    }

    /**
     * @param decryptedNode the decrypted node
     * @return a fully built xpath
     *        (eg. &quot;/soapenv:Envelope/soapenv:Body/ns:decryptedElement&quot;)
     *        if the decryptedNode is an Element or an Attr node and is not detached
     *        from the document. <code>null</code> otherwise
     */
    public static String getXPath(Node decryptedNode) {
        if (decryptedNode == null) {
            return null;
        }

        String result = "";
        if (Node.ELEMENT_NODE == decryptedNode.getNodeType()) {
            result = decryptedNode.getNodeName();
            result = prependFullPath(result, decryptedNode.getParentNode());
        } else if (Node.ATTRIBUTE_NODE == decryptedNode.getNodeType()) {
            result = "@" + decryptedNode.getNodeName();
            result = prependFullPath(result, ((Attr)decryptedNode).getOwnerElement());
        } else {
            return null;
        }

        return result;
    }


    /**
     * Recursively build an absolute xpath (starting with the root &quot;/&quot;)
     *
     * @param xpath the xpath expression built so far
     * @param node the current node whose name is to be prepended
     * @return a fully built xpath
     */
    private static String prependFullPath(String xpath, Node node) {
        if (node == null) {
            // probably a detached node... not really useful
            return null;
        } else if (Node.ELEMENT_NODE == node.getNodeType()) {
            xpath = node.getNodeName() + "/" + xpath;
            return prependFullPath(xpath, node.getParentNode());
        } else if (Node.DOCUMENT_NODE == node.getNodeType()) {
            return "/" + xpath;
        } else {
            return prependFullPath(xpath, node.getParentNode());
        }
    }

    public static String getDigestAlgorithm(Node encBodyData) throws WSSecurityException {
        Element tmpE =
            XMLUtils.getDirectChildElement(
                encBodyData, "EncryptionMethod", WSConstants.ENC_NS
            );
        if (tmpE != null) {
            Element digestElement =
                XMLUtils.getDirectChildElement(tmpE, "DigestMethod", WSConstants.SIG_NS);
            if (digestElement != null) {
                return digestElement.getAttributeNS(null, "Algorithm");
            }
        }
        return null;
    }

    public static String getMGFAlgorithm(Node encBodyData) throws WSSecurityException {
        Element tmpE =
            XMLUtils.getDirectChildElement(
                        encBodyData, "EncryptionMethod", WSConstants.ENC_NS
                );
        if (tmpE != null) {
            Element mgfElement =
                XMLUtils.getDirectChildElement(tmpE, "MGF", WSConstants.ENC11_NS);
            if (mgfElement != null) {
                return mgfElement.getAttributeNS(null, "Algorithm");
            }
        }
        return null;
    }

    public static byte[] getPSource(Node encBodyData) throws WSSecurityException {
        Element tmpE =
            XMLUtils.getDirectChildElement(
                        encBodyData, "EncryptionMethod", WSConstants.ENC_NS
                );
        if (tmpE != null) {
            Element pSourceElement =
                XMLUtils.getDirectChildElement(tmpE, "OAEPparams", WSConstants.ENC_NS);
            if (pSourceElement != null) {
                return getDecodedBase64EncodedData(pSourceElement);
            }
        }
        return null;
    }

    /**
     * Method getDecodedBase64EncodedData
     *
     * @param element
     * @return a byte array containing the decoded data
     * @throws WSSecurityException
     */
    public static byte[] getDecodedBase64EncodedData(Element element) throws WSSecurityException {
        String text = XMLUtils.getElementText(element);
        if (text == null) {
            return null;
        }
        return org.apache.xml.security.utils.XMLUtils.decode(text);
    }
}
