/**
 * 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.common.saml;

import java.io.IOException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.List;

import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dom.DOMStructure;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial;

import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoType;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.util.XMLUtils;
import org.opensaml.saml.saml2.core.SubjectConfirmationData;
import org.w3c.dom.Element;

/**
 * Utility methods for SAML stuff
 */
public final class SAMLUtil {

    /**
     * This constant defines the maximum amount of child elements of a Signature KeyInfo, associated with a
     * signed SAML assertion. Any other child element will be ignored.
     */
    private static final int MAX_KEYINFO_CONTENT_LIST_SIZE = 3;

    /**
     * This constant defines the maximum amount of child elements of a X509Data KeyInfo, associated with a
     * signed SAML assertion. Any other child element will be ignored.
     */
    private static final int MAX_X509DATA_SIZE = 5;

    private static final String SIG_NS = "http://www.w3.org/2000/09/xmldsig#";

    private SAMLUtil() {
        // Complete
    }

    /**
     * Parse a SAML Assertion to obtain a SAMLKeyInfo object from
     * the Subject of the assertion
     *
     * @param samlAssertion The SAML Assertion
     * @param keyInfoProcessor A pluggable way to parse the KeyInfo
     * @return a SAMLKeyInfo object
     * @throws WSSecurityException
     */
    public static SAMLKeyInfo getCredentialFromSubject(
        SamlAssertionWrapper samlAssertion,
        SAMLKeyInfoProcessor keyInfoProcessor,
        Crypto sigCrypto,
        CallbackHandler callbackHandler
    ) throws WSSecurityException {
        if (samlAssertion.getSaml1() != null) {
            return getCredentialFromSubject(
                samlAssertion.getSaml1(), keyInfoProcessor, sigCrypto, callbackHandler
            );
        } else if (samlAssertion.getSaml2() != null) {
            return getCredentialFromSubject(
                samlAssertion.getSaml2(), keyInfoProcessor, sigCrypto, callbackHandler
            );
        }

        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                      new Object[] {"Cannot get credentials from an unknown SAML Assertion"});
    }

    /**
     * Get the SAMLKeyInfo object corresponding to the credential stored in the Subject of a
     * SAML 1.1 assertion
     * @param assertion The SAML 1.1 assertion
     * @param keyInfoProcessor A pluggable way to parse the KeyInfo
     * @param sigCrypto A Crypto instance
     * @param callbackHandler A CallbackHandler instance
     * @return The SAMLKeyInfo object obtained from the Subject
     * @throws WSSecurityException
     */
    public static SAMLKeyInfo getCredentialFromSubject(
        org.opensaml.saml.saml1.core.Assertion assertion,
        SAMLKeyInfoProcessor keyInfoProcessor,
        Crypto sigCrypto,
        CallbackHandler callbackHandler
    ) throws WSSecurityException {
        for (org.opensaml.saml.saml1.core.Statement stmt : assertion.getStatements()) {
            org.opensaml.saml.saml1.core.Subject samlSubject = null;
            if (stmt instanceof org.opensaml.saml.saml1.core.AttributeStatement) {
                org.opensaml.saml.saml1.core.AttributeStatement attrStmt =
                    (org.opensaml.saml.saml1.core.AttributeStatement) stmt;
                samlSubject = attrStmt.getSubject();
            } else if (stmt instanceof org.opensaml.saml.saml1.core.AuthenticationStatement) {
                org.opensaml.saml.saml1.core.AuthenticationStatement authStmt =
                    (org.opensaml.saml.saml1.core.AuthenticationStatement) stmt;
                samlSubject = authStmt.getSubject();
            } else {
                org.opensaml.saml.saml1.core.AuthorizationDecisionStatement authzStmt =
                    (org.opensaml.saml.saml1.core.AuthorizationDecisionStatement)stmt;
                samlSubject = authzStmt.getSubject();
            }

            if (samlSubject != null && samlSubject.getSubjectConfirmation() != null) {
                Element sub = samlSubject.getSubjectConfirmation().getDOM();
                Element keyInfoElement =
                    XMLUtils.getDirectChildElement(sub, "KeyInfo", SIG_NS);
                if (keyInfoElement != null) {
                    return getCredentialFromKeyInfo(
                        keyInfoElement, keyInfoProcessor, sigCrypto
                    );
                }
            }
        }

        return null;
    }

    /**
     * Get the SAMLKeyInfo object corresponding to the credential stored in the Subject of a
     * SAML 2 assertion
     * @param assertion The SAML 2 assertion
     * @param keyInfoProcessor A pluggable way to parse the KeyInfo
     * @param sigCrypto A Crypto instance
     * @param callbackHandler A CallbackHandler instance
     * @return The SAMLKeyInfo object obtained from the Subject
     * @throws WSSecurityException
     */
    public static SAMLKeyInfo getCredentialFromSubject(
        org.opensaml.saml.saml2.core.Assertion assertion,
        SAMLKeyInfoProcessor keyInfoProcessor,
        Crypto sigCrypto,
        CallbackHandler callbackHandler
    ) throws WSSecurityException {
        org.opensaml.saml.saml2.core.Subject samlSubject = assertion.getSubject();
        if (samlSubject != null) {
            List<org.opensaml.saml.saml2.core.SubjectConfirmation> subjectConfList =
                samlSubject.getSubjectConfirmations();
            for (org.opensaml.saml.saml2.core.SubjectConfirmation subjectConfirmation : subjectConfList) {
                SubjectConfirmationData subjConfData =
                    subjectConfirmation.getSubjectConfirmationData();
                if (subjConfData != null) {
                    Element sub = subjConfData.getDOM();
                    Element keyInfoElement =
                        XMLUtils.getDirectChildElement(sub, "KeyInfo", SIG_NS);
                    if (keyInfoElement != null) {
                        return getCredentialFromKeyInfo(
                            keyInfoElement, keyInfoProcessor, sigCrypto
                        );
                    }
                }
            }
        }

        return null;
    }

    /**
     * This method returns a SAMLKeyInfo corresponding to the credential found in the
     * KeyInfo (DOM Element) argument.
     * @param keyInfoElement The KeyInfo as a DOM Element
     * @param keyInfoProcessor A pluggable way to parse the KeyInfo
     * @param sigCrypto A Crypto instance
     * @return The credential (as a SAMLKeyInfo object)
     * @throws WSSecurityException
     */
    public static SAMLKeyInfo getCredentialFromKeyInfo(
        Element keyInfoElement,
        SAMLKeyInfoProcessor keyInfoProcessor,
        Crypto sigCrypto
    ) throws WSSecurityException {
        //
        // First try to find an EncryptedKey, BinarySecret or a SecurityTokenReference via DOM
        //
        if (keyInfoProcessor != null) {
            SAMLKeyInfo samlKeyInfo = keyInfoProcessor.processSAMLKeyInfo(keyInfoElement);
            if (samlKeyInfo != null) {
                return samlKeyInfo;
            }
        }

        //
        // Next marshal the KeyInfo DOM element into a javax KeyInfo object and get the
        // (public key) credential
        //
        KeyInfoFactory keyInfoFactory = null;
        try {
            keyInfoFactory = KeyInfoFactory.getInstance("DOM", "ApacheXMLDSig");
        } catch (NoSuchProviderException ex) {
            keyInfoFactory = KeyInfoFactory.getInstance("DOM");
        }
        XMLStructure keyInfoStructure = new DOMStructure(keyInfoElement);

        try {
            javax.xml.crypto.dsig.keyinfo.KeyInfo keyInfo =
                keyInfoFactory.unmarshalKeyInfo(keyInfoStructure);
            List<?> list = keyInfo.getContent();

            X509Certificate[] certs = null;
            PublicKey publicKey = null;
            for (int i = 0; i < list.size(); i++) {
                // Put a hard bound on how many child elements there can be of KeyInfo
                if (i >= MAX_KEYINFO_CONTENT_LIST_SIZE) {
                    break;
                }
                XMLStructure xmlStructure = (XMLStructure) list.get(i);
                if (xmlStructure instanceof KeyValue && publicKey == null) {
                    publicKey = ((KeyValue)xmlStructure).getPublicKey();
                } else if (xmlStructure instanceof X509Data) {
                    List<?> x509Data = ((X509Data)xmlStructure).getContent();
                    for (int j = 0; j < x509Data.size(); j++) {
                        // Put a hard bound on how many child elements there can be of X509Data
                        if (j >= MAX_X509DATA_SIZE || certs != null) {
                            break;
                        }
                        Object x509obj = x509Data.get(j);
                        if (x509obj instanceof X509Certificate) {
                            certs = new X509Certificate[1];
                            certs[0] = (X509Certificate)x509obj;
                        } else if (x509obj instanceof X509IssuerSerial) {
                            if (sigCrypto == null) {
                                throw new WSSecurityException(
                                    WSSecurityException.ErrorCode.FAILURE, "noSigCryptoFile"
                                );
                            }
                            CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ISSUER_SERIAL);
                            cryptoType.setIssuerSerial(
                                ((X509IssuerSerial)x509obj).getIssuerName(),
                                ((X509IssuerSerial)x509obj).getSerialNumber()
                            );
                            certs = sigCrypto.getX509Certificates(cryptoType);
                            if (certs == null || certs.length < 1) {
                                throw new WSSecurityException(
                                    WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity",
                                    new Object[] {"cannot get certificate or key"}
                                );
                            }
                        }
                    }
                }
            }

            if (certs != null || publicKey != null) {
                SAMLKeyInfo samlKeyInfo = new SAMLKeyInfo(certs);
                samlKeyInfo.setPublicKey(publicKey);
                return samlKeyInfo;
            }
        } catch (Exception ex) {
            throw new WSSecurityException(
                WSSecurityException.ErrorCode.FAILURE, ex, "invalidSAMLsecurity",
                new Object[] {"cannot get certificate or key"}
            );
        }
        return null;
    }

    public static void doSAMLCallback(
        CallbackHandler callbackHandler, SAMLCallback callback
    ) {
        // Create a new SAMLCallback with all of the information from the properties file.
        try {
            // Get the SAML source data using the currently configured callback implementation.
            callbackHandler.handle(new SAMLCallback[]{callback});
        } catch (IOException | UnsupportedCallbackException e) {
            throw new IllegalStateException(
                "Error while creating SAML assertion wrapper", e
            );
        }
    }

}
