/*
 *
 * 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.qpid.proton.engine.impl.ssl;

import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.KeyManagementException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.apache.qpid.proton.engine.SslDomain;
import org.apache.qpid.proton.engine.SslPeerDetails;
import org.apache.qpid.proton.engine.TransportException;

public class SslEngineFacadeFactory
{
    private static final Logger _logger = Logger.getLogger(SslEngineFacadeFactory.class.getName());

    /**
     * The protocol name used to create an {@link SSLContext}, taken from Java's list of
     * standard names at http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html
     *
     * TODO allow the protocol name to be overridden somehow
     */
    private static final String TLS_PROTOCOL = "TLS";

    // BouncyCastle Reflection Helpers
    private static final Constructor<?> pemParserCons;
    private static final Method         pemReadMethod;

    private static final Constructor<?> JcaPEMKeyConverterCons;
    private static final Class<?>       PEMKeyPairClass;
    private static final Method         getKeyPairMethod;
    private static final Method         getPrivateKeyMethod;

    private static final Class<?>       PEMEncryptedKeyPairClass;
    private static final Method         decryptKeyPairMethod;

    private static final Constructor<?> JcePEMDecryptorProviderBuilderCons;
    private static final Method         builderMethod;

    private static final Class<?>       PrivateKeyInfoClass;
    private static final Exception      bouncyCastleSetupException;

    static
    {
        // Setup BouncyCastle Reflection artifacts
        Constructor<?> pemParserConsResult = null;
        Method         pemReadMethodResult = null;
        Constructor<?> JcaPEMKeyConverterConsResult = null;
        Class<?>       PEMKeyPairClassResult = null;
        Method         getKeyPairMethodResult = null;
        Method         getPrivateKeyMethodResult = null;
        Class<?>       PEMEncryptedKeyPairClassResult = null;
        Method         decryptKeyPairMethodResult = null;
        Constructor<?> JcePEMDecryptorProviderBuilderConsResult = null;
        Method         builderMethodResult = null;
        Class<?>       PrivateKeyInfoClassResult = null;
        Exception      bouncyCastleSetupExceptionResult = null;

        try
        {
            final Class<?> pemParserClass = Class.forName("org.bouncycastle.openssl.PEMParser");
            pemParserConsResult = pemParserClass.getConstructor(Reader.class);
            pemReadMethodResult = pemParserClass.getMethod("readObject");

            final Class<?> jcaPEMKeyConverterClass = Class.forName("org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter");
            JcaPEMKeyConverterConsResult = jcaPEMKeyConverterClass.getConstructor();
            PEMKeyPairClassResult = Class.forName("org.bouncycastle.openssl.PEMKeyPair");
            getKeyPairMethodResult = jcaPEMKeyConverterClass.getMethod("getKeyPair", PEMKeyPairClassResult);

            final Class<?> PEMDecrypterProvider = Class.forName("org.bouncycastle.openssl.PEMDecryptorProvider");

            PEMEncryptedKeyPairClassResult = Class.forName("org.bouncycastle.openssl.PEMEncryptedKeyPair");
            decryptKeyPairMethodResult = PEMEncryptedKeyPairClassResult.getMethod("decryptKeyPair", PEMDecrypterProvider);

            final Class<?> jcePEMDecryptorProviderBuilderClass = Class.forName(
                    "org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder");
            JcePEMDecryptorProviderBuilderConsResult = jcePEMDecryptorProviderBuilderClass.getConstructor();
            builderMethodResult = jcePEMDecryptorProviderBuilderClass.getMethod("build", char[].class);

            PrivateKeyInfoClassResult = Class.forName("org.bouncycastle.asn1.pkcs.PrivateKeyInfo");
            getPrivateKeyMethodResult = jcaPEMKeyConverterClass.getMethod("getPrivateKey", PrivateKeyInfoClassResult);

            registerBouncyCastleProvider();
        }
        catch (Exception e)
        {
            bouncyCastleSetupExceptionResult = e;
        }
        finally {
            pemParserCons = pemParserConsResult;
            pemReadMethod = pemReadMethodResult;
            JcaPEMKeyConverterCons = JcaPEMKeyConverterConsResult;
            PEMKeyPairClass = PEMKeyPairClassResult;
            getKeyPairMethod = getKeyPairMethodResult;
            getPrivateKeyMethod = getPrivateKeyMethodResult;
            PEMEncryptedKeyPairClass = PEMEncryptedKeyPairClassResult;
            decryptKeyPairMethod = decryptKeyPairMethodResult;
            JcePEMDecryptorProviderBuilderCons = JcePEMDecryptorProviderBuilderConsResult;
            builderMethod = builderMethodResult;
            PrivateKeyInfoClass = PrivateKeyInfoClassResult;
            bouncyCastleSetupException = bouncyCastleSetupExceptionResult;
        }
    }

    static void registerBouncyCastleProvider()
            throws ClassNotFoundException, InstantiationException, IllegalAccessException,
                   InvocationTargetException, NoSuchMethodException
    {
        // Try loading BC as a provider
        Class<?> klass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");

        Provider bouncyCastleProvider = (Provider) klass.getConstructor().newInstance();
        synchronized (Security.class)
        {
            if(Security.getProvider(bouncyCastleProvider.getName()) == null)
            {
                Security.addProvider(bouncyCastleProvider);
            }
        }
    }

    SslEngineFacadeFactory()
    {
    }

    /**
     * This is a list of all anonymous cipher suites supported by Java 6, excluding those that
     * use MD5.  These are all supported by both Oracle's and IBM's Java 6 implementation.
     */
    private static final List<String> ANONYMOUS_CIPHER_SUITES = Arrays.asList(
            "TLS_DH_anon_WITH_AES_128_CBC_SHA",
            "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
            "SSL_DH_anon_WITH_DES_CBC_SHA",
            "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA");

    /** lazily initialized */
    private SSLContext _sslContext;


    /**
     * Returns a {@link ProtonSslEngine}. May cache the domain's settings so callers should invoke
     * {@link #resetCache()} if the domain changes.
     *
     * @param peerDetails may be used to return an engine that supports SSL resume.
     */
    public ProtonSslEngine createProtonSslEngine(SslDomain domain, SslPeerDetails peerDetails)
    {
        SSLEngine engine = createAndInitialiseSslEngine(domain, peerDetails);
        if(_logger.isLoggable(Level.FINE))
        {
            _logger.fine("Created SSL engine: " + engineToString(engine));
        }
        return new DefaultSslEngineFacade(engine);
    }


    /**
     * Guarantees that no cached settings are used in subsequent calls to
     * {@link #createProtonSslEngine(SslDomain, SslPeerDetails)}.
     */
    public void resetCache()
    {
        _sslContext = null;
    }


    private SSLEngine createAndInitialiseSslEngine(SslDomain domain, SslPeerDetails peerDetails)
    {
        SslDomain.Mode mode = domain.getMode();

        SSLContext sslContext = getOrCreateSslContext(domain);
        SSLEngine sslEngine = createSslEngine(sslContext, peerDetails);

        if (domain.getPeerAuthentication() == SslDomain.VerifyMode.ANONYMOUS_PEER)
        {
            addAnonymousCipherSuites(sslEngine);
        }
        else
        {
            if (mode == SslDomain.Mode.SERVER)
            {
                sslEngine.setNeedClientAuth(true);
            }
        }

        if(_logger.isLoggable(Level.FINE))
        {
            _logger.log(Level.FINE, mode + " Enabled cipher suites " + Arrays.asList(sslEngine.getEnabledCipherSuites()));
        }

        boolean useClientMode = mode == SslDomain.Mode.CLIENT ? true : false;
        sslEngine.setUseClientMode(useClientMode);

        removeSSLv3Support(sslEngine);

        return sslEngine;
    }

    private static final String SSLV3_PROTOCOL = "SSLv3";

    private static void removeSSLv3Support(final SSLEngine engine)
    {
        List<String> enabledProtocols = Arrays.asList(engine.getEnabledProtocols());
        if(enabledProtocols.contains(SSLV3_PROTOCOL))
        {
            List<String> allowedProtocols = new ArrayList<String>(enabledProtocols);
            allowedProtocols.remove(SSLV3_PROTOCOL);
            engine.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()]));
        }
    }

    /**
     * @param sslPeerDetails is allowed to be null. A non-null value is used to hint that SSL resumption
     * should be attempted
     */
    private SSLEngine createSslEngine(SSLContext sslContext, SslPeerDetails sslPeerDetails)
    {
        final SSLEngine sslEngine;
        if(sslPeerDetails == null)
        {
            sslEngine = sslContext.createSSLEngine();
        }
        else
        {
            sslEngine = sslContext.createSSLEngine(sslPeerDetails.getHostname(), sslPeerDetails.getPort());
        }
        return sslEngine;
    }

    private SSLContext getOrCreateSslContext(SslDomain sslDomain)
    {
        if(_sslContext == null && sslDomain.getSslContext() != null)
        {
            _sslContext = sslDomain.getSslContext();
        }
        else if(_sslContext == null)
        {
            if(_logger.isLoggable(Level.FINE))
            {
                _logger.fine("lazily creating new SSLContext using domain " + sslDomain);
            }

            final char[] dummyPassword = "unused-passphrase".toCharArray(); // Dummy password required by KeyStore and KeyManagerFactory, but never referred to again

            try
            {
                SSLContext sslContext = SSLContext.getInstance(TLS_PROTOCOL);
                KeyStore ksKeys = createKeyStoreFrom(sslDomain, dummyPassword);

                KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                kmf.init(ksKeys, dummyPassword);

                final TrustManager[] trustManagers;
                if (sslDomain.getPeerAuthentication() == SslDomain.VerifyMode.ANONYMOUS_PEER)
                {
                    trustManagers = new TrustManager[] { new AlwaysTrustingTrustManager() };
                }
                else
                {
                    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                    tmf.init(ksKeys);
                    trustManagers = tmf.getTrustManagers();
                }

                sslContext.init(kmf.getKeyManagers(), trustManagers, null);
                _sslContext = sslContext;
            }
            catch (NoSuchAlgorithmException e)
            {
                throw new TransportException("Unexpected exception creating SSLContext", e);
            }
            catch (KeyStoreException e)
            {
                throw new TransportException("Unexpected exception creating SSLContext", e);
            }
            catch (UnrecoverableKeyException e)
            {
                throw new TransportException("Unexpected exception creating SSLContext", e);
            }
            catch (KeyManagementException e)
            {
                throw new TransportException("Unexpected exception creating SSLContext", e);
            }
        }
        return _sslContext;
    }

    private KeyStore createKeyStoreFrom(SslDomain sslDomain, char[] dummyPassword)
    {
        try
        {
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            keystore.load(null, null);

            if (sslDomain.getTrustedCaDb() != null)
            {
                String caCertAlias = "cacert";

                if(_logger.isLoggable(Level.FINE))
                {
                    _logger.log(Level.FINE, "_sslParams.getTrustedCaDb() : " + sslDomain.getTrustedCaDb());
                }
                Certificate trustedCaCert = readCertificate(sslDomain.getTrustedCaDb());
                keystore.setCertificateEntry(caCertAlias, trustedCaCert);
            }

            if (sslDomain.getCertificateFile() != null
                    && sslDomain.getPrivateKeyFile() != null)
            {
                String clientPrivateKeyAlias = "clientPrivateKey";

                Certificate clientCertificate = (Certificate) readCertificate(sslDomain.getCertificateFile());
                PrivateKey clientPrivateKey = readPrivateKey(sslDomain.getPrivateKeyFile(), sslDomain.getPrivateKeyPassword());

                keystore.setKeyEntry(clientPrivateKeyAlias, clientPrivateKey,
                        dummyPassword, new Certificate[] { clientCertificate });
            }

            return keystore;
        }
        catch (KeyStoreException e)
        {
           throw new TransportException("Unexpected exception creating keystore", e);
        }
        catch (NoSuchAlgorithmException e)
        {
            throw new TransportException("Unexpected exception creating keystore", e);
        }
        catch (CertificateException e)
        {
            throw new TransportException("Unexpected exception creating keystore", e);
        }
        catch (IOException e)
        {
            throw new TransportException("Unexpected exception creating keystore", e);
        }
    }

    private void addAnonymousCipherSuites(SSLEngine sslEngine)
    {
        List<String> supportedSuites = Arrays.asList(sslEngine.getSupportedCipherSuites());
        List<String> currentEnabledSuites = Arrays.asList(sslEngine.getEnabledCipherSuites());

        List<String> enabledSuites = buildEnabledSuitesIncludingAnonymous(ANONYMOUS_CIPHER_SUITES, supportedSuites, currentEnabledSuites);
        sslEngine.setEnabledCipherSuites(enabledSuites.toArray(new String[0]));
    }

    private List<String> buildEnabledSuitesIncludingAnonymous(
            List<String> anonymousCipherSuites, List<String> supportedSuites, List<String> currentEnabled)
    {
        List<String> newEnabled = new ArrayList<String>(currentEnabled);

        int addedAnonymousCipherSuites = 0;
        for (String anonymousCipherSuiteName : anonymousCipherSuites)
        {
            if (supportedSuites.contains(anonymousCipherSuiteName))
            {
                newEnabled.add(anonymousCipherSuiteName);
                addedAnonymousCipherSuites++;
            }
        }

        if (addedAnonymousCipherSuites == 0)
        {
            throw new TransportException
                ("None of " + anonymousCipherSuites
                 + " anonymous cipher suites are within the supported list "
                 + supportedSuites);
        }

        if(_logger.isLoggable(Level.FINE))
        {
            _logger.fine("There are now " + newEnabled.size()
                    + " cipher suites enabled (previously " + currentEnabled.size()
                    + "), including " + addedAnonymousCipherSuites + " out of the "
                    + anonymousCipherSuites.size() + " requested anonymous ones." );
        }

        return newEnabled;
    }

    private String engineToString(SSLEngine engine)
    {
        return new StringBuilder("[ " )
            .append(engine)
            .append(", needClientAuth=").append(engine.getNeedClientAuth())
            .append(", useClientMode=").append(engine.getUseClientMode())
            .append(", peerHost=").append(engine.getPeerHost())
            .append(", peerPort=").append(engine.getPeerPort())
            .append(" ]").toString();
    }

    Certificate readCertificate(String pemFile)
    {
        InputStream is = null;

        try
        {
            CertificateFactory cFactory = CertificateFactory.getInstance("X.509");
            is = new FileInputStream(pemFile);
            return cFactory.generateCertificate(is);
        }
        catch (CertificateException ce)
        {
            String msg = "Failed to load certificate [" + pemFile + "]";
            _logger.log(Level.SEVERE, msg, ce);
            throw new TransportException(msg, ce);
        }
        catch (FileNotFoundException e)
        {
            String msg = "Certificate file not found [" + pemFile + "]";
            _logger.log(Level.SEVERE, msg);
            throw new TransportException(msg, e);
        }
        finally
        {
            closeSafely(is);
        }
    }

    PrivateKey readPrivateKey(String pemFile, String password)
    {
        if (bouncyCastleSetupException != null)
        {
            throw new TransportException("BouncyCastle failed to load", bouncyCastleSetupException);
        }

        final Object pemObject = readPemObject(pemFile);
        PrivateKey privateKey = null;

        try
        {
            Object keyConverter = JcaPEMKeyConverterCons.newInstance();
            setProvider(keyConverter, "BC");

            if (PEMEncryptedKeyPairClass.isInstance(pemObject))
            {
                Object decryptorBuilder = JcePEMDecryptorProviderBuilderCons.newInstance();

                // Build a PEMDecryptProvider
                Object decryptProvider = builderMethod.invoke(decryptorBuilder, password.toCharArray());

                Object decryptedKeyPair = decryptKeyPairMethod.invoke(pemObject, decryptProvider);
                KeyPair keyPair = (KeyPair) getKeyPairMethod.invoke(keyConverter, decryptedKeyPair);

                privateKey = keyPair.getPrivate();
            }
            else if (PEMKeyPairClass.isInstance(pemObject))
            {
                // It's a KeyPair but not encrypted.
                KeyPair keyPair = (KeyPair) getKeyPairMethod.invoke(keyConverter, pemObject);
                privateKey = keyPair.getPrivate();
            }
            else if (PrivateKeyInfoClass.isInstance(pemObject))
            {
                // It's an unencrypted private key
                privateKey = (PrivateKey) getPrivateKeyMethod.invoke(keyConverter, pemObject);
            }
            else
            {
                final String msg = "Unable to load PrivateKey, Unpexected Object [" + pemObject.getClass().getName()
                        + "]";
                _logger.log(Level.SEVERE, msg);
                throw new TransportException(msg);
            }
        }
        catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException | NoSuchMethodException | SecurityException e)
        {
            final String msg = "Failed to process key file [" + pemFile + "] - " + e.getMessage();
            throw new TransportException(msg, e);
        }

        return privateKey;
    }

    private Object readPemObject(String pemFile)
    {
        Reader reader = null;
        Object pemParser = null;
        Object pemObject = null;

        try
        {
            reader = new FileReader(pemFile);
            pemParser = pemParserCons.newInstance(reader); // = new PEMParser(reader);
            pemObject = pemReadMethod.invoke(pemParser); // = pemParser.readObject();
        }
        catch (IOException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e)
        {
            _logger.log(Level.SEVERE, "Unable to read PEM object. Perhaps you need the unlimited strength libraries in <java-home>/jre/lib/security/ ?", e);
            throw new TransportException("Unable to read PEM object from file " + pemFile, e);
        }
        finally
        {
            closeSafely(reader);
        }

        return pemObject;
    }

    private void setProvider(Object obj, String provider) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException
    {
        final Class<?> aClz = obj.getClass();
        final Method setProvider = aClz.getMethod("setProvider", String.class);
        setProvider.invoke(obj, provider);
    }

    private void closeSafely(Closeable c)
    {
        if (c != null)
        {
            try
            {
                c.close();
            }
            catch (IOException e)
            {
               // Swallow
            }
        }
    }

    private static final class AlwaysTrustingTrustManager implements X509TrustManager
    {
        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            return null;
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException
        {
            // Do not check certificate
        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws CertificateException
        {
            // Do not check certificate
        }
    }
}
