/*
 *
 * 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.Collection;
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());
                }
                int i = 1;
                for(Certificate trustedCaCert : readCertificates(sslDomain.getTrustedCaDb()))
                {
                    keystore.setCertificateEntry(caCertAlias + (i++), 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 && _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);
        }
    }

    Collection<? extends Certificate> readCertificates(String pemFile)
    {
        InputStream is = null;

        try
        {
            CertificateFactory cFactory = CertificateFactory.getInstance("X.509");
            is = new FileInputStream(pemFile);
            return cFactory.generateCertificates(is);
        }
        catch (CertificateException ce)
        {
            String msg = "Failed to load certificates [" + pemFile + "]";
            _logger.log(Level.SEVERE, msg, ce);
            throw new TransportException(msg, ce);
        }
        catch (FileNotFoundException e)
        {
            String msg = "Certificates 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
        }
    }
}
