/*
 *
 * 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.server.transport.network.security.ssl;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.URL;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SNIHostName;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.StandardConstants;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.bytebuffer.QpidByteBuffer;
import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.transport.TransportException;
import org.apache.qpid.server.util.Strings;

public class SSLUtil
{
    private static final Logger LOGGER = LoggerFactory.getLogger(SSLUtil.class);

    private static final Integer DNS_NAME_TYPE = 2;
    private static final String[] TLS_PROTOCOL_PREFERENCES = new String[]{"TLSv1.2", "TLSv1.1", "TLS", "TLSv1"};


    private static final SecureRandom RANDOM = new SecureRandom();


    private static final Constructor<?> CONSTRUCTOR;
    private static final Method GENERATE_METHOD;
    private static final Method GET_PRIVATE_KEY_METHOD;
    private static final Method GET_SELF_CERTIFICATE_METHOD;
    private static final Constructor<?> X500_NAME_CONSTRUCTOR;
    private static final Constructor<?> DNS_NAME_CONSTRUCTOR;
    private static final Constructor<?> IP_ADDR_NAME_CONSTRUCTOR;
    private static final Constructor<?> GENERAL_NAMES_CONSTRUCTOR;
    private static final Constructor<?> GENERAL_NAME_CONSTRUCTOR;
    private static final Method ADD_NAME_TO_NAMES_METHOD;
    private static final Constructor<?> ALT_NAMES_CONSTRUCTOR;
    private static final Constructor<?> CERTIFICATE_EXTENSIONS_CONSTRUCTOR;
    private static final Method SET_EXTENSION_METHOD;
    private static final Method EXTENSION_GET_NAME_METHOD;
    private static final boolean CAN_GENERATE_CERTS;


    static
    {

        Constructor<?> constructor = null;
        Method generateMethod = null;
        Method getPrivateKeyMethod = null;
        Method getSelfCertificateMethod = null;
        Constructor<?> x500NameConstructor = null;
        Constructor<?> dnsNameConstructor = null;
        Constructor<?> ipAddrNameConstructor = null;
        Constructor<?> generalNamesConstructor = null;
        Constructor<?> generalNameConstructor = null;
        Method addNameToNamesMethod = null;
        Constructor<?> altNamesConstructor = null;
        Constructor<?> certificateExtensionsConstructor = null;
        Method setExtensionMethod = null;
        Method extensionGetNameMethod = null;
        boolean canGenerateCerrts = false;

        try
        {
            Class<?> certAndKeyGenClass;
            try
            {
                certAndKeyGenClass = Class.forName("sun.security.x509.CertAndKeyGen");
            }
            catch (ClassNotFoundException e)
            {
                certAndKeyGenClass = Class.forName("sun.security.tools.keytool.CertAndKeyGen");
            }

            final Class<?> x500NameClass = Class.forName("sun.security.x509.X500Name");
            final Class<?> certificateExtensionsClass = Class.forName("sun.security.x509.CertificateExtensions");
            final Class<?> generalNamesClass = Class.forName("sun.security.x509.GeneralNames");
            final Class<?> generalNameClass = Class.forName("sun.security.x509.GeneralName");
            final Class<?> extensionClass = Class.forName("sun.security.x509.SubjectAlternativeNameExtension");

            constructor = certAndKeyGenClass.getConstructor(String.class, String.class);
            generateMethod = certAndKeyGenClass.getMethod("generate", Integer.TYPE);
            getPrivateKeyMethod = certAndKeyGenClass.getMethod("getPrivateKey");
            getSelfCertificateMethod = certAndKeyGenClass.getMethod("getSelfCertificate", x500NameClass,
                                                                    Date.class, Long.TYPE, certificateExtensionsClass);
            x500NameConstructor = x500NameClass.getConstructor(String.class);
            dnsNameConstructor = Class.forName("sun.security.x509.DNSName").getConstructor(String.class);
            ipAddrNameConstructor = Class.forName("sun.security.x509.IPAddressName").getConstructor(String.class);
            generalNamesConstructor = generalNamesClass.getConstructor();
            generalNameConstructor = generalNameClass.getConstructor(Class.forName("sun.security.x509.GeneralNameInterface"));
            addNameToNamesMethod = generalNamesClass.getMethod("add", generalNameClass);
            altNamesConstructor = extensionClass.getConstructor(generalNamesClass);
            certificateExtensionsConstructor = certificateExtensionsClass.getConstructor();
            setExtensionMethod = certificateExtensionsClass.getMethod("set", String.class, Object.class);
            extensionGetNameMethod = extensionClass.getMethod("getName");
            canGenerateCerrts = true;

        }
        catch (ClassNotFoundException | LinkageError | NoSuchMethodException e)
        {
            // ignore
        }
        GET_SELF_CERTIFICATE_METHOD = getSelfCertificateMethod;
        CONSTRUCTOR = constructor;
        GENERATE_METHOD = generateMethod;
        GET_PRIVATE_KEY_METHOD = getPrivateKeyMethod;
        X500_NAME_CONSTRUCTOR = x500NameConstructor;
        DNS_NAME_CONSTRUCTOR = dnsNameConstructor;
        IP_ADDR_NAME_CONSTRUCTOR = ipAddrNameConstructor;
        GENERAL_NAMES_CONSTRUCTOR = generalNamesConstructor;
        GENERAL_NAME_CONSTRUCTOR = generalNameConstructor;
        ADD_NAME_TO_NAMES_METHOD = addNameToNamesMethod;
        ALT_NAMES_CONSTRUCTOR = altNamesConstructor;
        CERTIFICATE_EXTENSIONS_CONSTRUCTOR = certificateExtensionsConstructor;
        SET_EXTENSION_METHOD = setExtensionMethod;
        EXTENSION_GET_NAME_METHOD = extensionGetNameMethod;
        CAN_GENERATE_CERTS = canGenerateCerrts;
    }


    private SSLUtil()
    {
    }

    public static void verifyHostname(SSLEngine engine,String hostnameExpected)
    {
        try
        {
            Certificate cert = engine.getSession().getPeerCertificates()[0];
            if (cert instanceof X509Certificate)
            {
                verifyHostname(hostnameExpected, (X509Certificate) cert);
            }
            else
            {
                throw new TransportException("Cannot verify peer's hostname as peer does not present a X509Certificate. "
                                             + "Presented certificate : " + cert);
            }
        }
        catch(SSLPeerUnverifiedException e)
        {
            throw new TransportException("Failed to verify peer's hostname", e);
        }
    }

    public static void verifyHostname(final String hostnameExpected, final X509Certificate cert)
    {

        try
        {
            SortedSet<String> names = getNamesFromCert(cert);

            if (names.isEmpty())
            {
                throw new TransportException("SSL hostname verification failed. Certificate for did not contain CN or DNS subjectAlt");
            }

            boolean match = verifyHostname(hostnameExpected, names);
            if (!match)
            {
                throw new TransportException("SSL hostname verification failed." +
                                             " Expected : " + hostnameExpected +
                                             " Found in cert : " + names);
            }

        }
        catch (InvalidNameException e)
        {
            Principal p = cert.getSubjectDN();
            String dn = p.getName();
            throw new TransportException("SSL hostname verification failed. Could not parse name " + dn, e);
        }
        catch (CertificateParsingException e)
        {
            throw new TransportException("SSL hostname verification failed. Could not parse certificate:  " + e.getMessage(), e);
        }
    }

    public static boolean checkHostname(String hostname, X509Certificate cert)
    {
        try
        {
            return verifyHostname(hostname, getNamesFromCert(cert));
        }
        catch (InvalidNameException | CertificateParsingException e)
        {
            return false;
        }
    }

    private static boolean verifyHostname(final String hostnameExpected, final SortedSet<String> names)
    {
        boolean match = false;

        final String hostName = hostnameExpected.trim().toLowerCase();
        for (String cn : names)
        {

            boolean doWildcard = cn.startsWith("*.") &&
                                 cn.lastIndexOf('.') >= 3 &&
                                 !cn.matches("\\*\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");


            match = doWildcard
                    ? hostName.endsWith(cn.substring(1)) && hostName.indexOf(".") == (1 + hostName.length() - cn.length())
                    : hostName.equals(cn);

            if (match)
            {
                break;
            }

        }
        return match;
    }

    private static SortedSet<String> getNamesFromCert(final X509Certificate cert)
            throws InvalidNameException, CertificateParsingException
    {
        Principal p = cert.getSubjectDN();
        String dn = p.getName();
        SortedSet<String> names = new TreeSet<>();
        LdapName ldapName = new LdapName(dn);
        for (Rdn part : ldapName.getRdns())
        {
            if (part.getType().equalsIgnoreCase("CN"))
            {
                names.add(part.getValue().toString());
                break;
            }
        }

        if(cert.getSubjectAlternativeNames() != null)
        {
            for (List<?> entry : cert.getSubjectAlternativeNames())
            {
                if (DNS_NAME_TYPE.equals(entry.get(0)))
                {
                    names.add((String) entry.get(1));
                }
            }
        }
        return names;
    }

    public static String getIdFromSubjectDN(String dn)
    {
        String cnStr = null;
        String dcStr = null;
        if(dn == null)
        {
            return "";
        }
        else
        {
            try
            {
                LdapName ln = new LdapName(dn);
                for(Rdn rdn : ln.getRdns())
                {
                    if("CN".equalsIgnoreCase(rdn.getType()))
                    {
                        cnStr = rdn.getValue().toString();
                    }
                    else if("DC".equalsIgnoreCase(rdn.getType()))
                    {
                        if(dcStr == null)
                        {
                            dcStr = rdn.getValue().toString();
                        }
                        else
                        {
                            dcStr = rdn.getValue().toString() + '.' + dcStr;
                        }
                    }
                }
                return cnStr == null || cnStr.length()==0 ? "" : dcStr == null ? cnStr : cnStr + '@' + dcStr;
            }
            catch (InvalidNameException e)
            {
                LOGGER.warn("Invalid name: '{}'", dn);
                return "";
            }
        }
    }


    public static String retrieveIdentity(SSLEngine engine)
    {
        String id = "";
        Certificate cert = engine.getSession().getLocalCertificates()[0];
        Principal p = ((X509Certificate)cert).getSubjectDN();
        String dn = p.getName();
        try
        {
            id = SSLUtil.getIdFromSubjectDN(dn);
        }
        catch (Exception e)
        {
            LOGGER.info("Exception received while trying to retrieve client identity from SSL cert", e);
        }
        LOGGER.debug("Extracted Identity from client certificate : {}", id);
        return id;
    }

    public static KeyStore getInitializedKeyStore(String storePath, String storePassword, String keyStoreType) throws GeneralSecurityException, IOException
    {
        KeyStore ks = KeyStore.getInstance(keyStoreType);
        InputStream in = null;
        try
        {
            File f = new File(storePath);
            if (f.exists())
            {
                in = new FileInputStream(f);
            }
            else
            {
                in = Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath);
            }
            if (in == null && !"PKCS11".equalsIgnoreCase(keyStoreType)) // PKCS11 will not require an explicit path
            {
                throw new IOException("Unable to load keystore resource: " + storePath);
            }

            char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();

            ks.load(in, storeCharPassword);
        }
        finally
        {
            if (in != null)
            {
                //noinspection EmptyCatchBlock
                try
                {
                    in.close();
                }
                catch (IOException ignored)
                {
                }
            }
        }
        return ks;
    }

    public static KeyStore getInitializedKeyStore(URL storePath, String storePassword, String keyStoreType) throws GeneralSecurityException, IOException
    {
        KeyStore ks = KeyStore.getInstance(keyStoreType);
        try(InputStream in = storePath.openStream())
        {
            if (in == null && !"PKCS11".equalsIgnoreCase(keyStoreType)) // PKCS11 will not require an explicit path
            {
                throw new IOException("Unable to load keystore resource: " + storePath);
            }

            char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();

            ks.load(in, storeCharPassword);
        }
        catch (IOException ioe)
        {
            if (ioe.getCause() instanceof GeneralSecurityException)
            {
                throw ((GeneralSecurityException) ioe.getCause());
            }
            else
            {
                throw ioe;
            }
        }
        return ks;
    }

    public static X509Certificate[] readCertificates(URL certFile)
            throws IOException, GeneralSecurityException
    {
        try (InputStream is = certFile.openStream())
        {
            return readCertificates(is);
        }
    }

    public static X509Certificate[] readCertificates(InputStream input)
            throws IOException, GeneralSecurityException
    {
        List<X509Certificate> crt = new ArrayList<>();
        try
        {
            do
            {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                crt.add( (X509Certificate) cf.generateCertificate(input));
            } while(input.available() != 0);
        }
        catch(CertificateException e)
        {
            if(crt.isEmpty())
            {
                throw e;
            }
        }
        return crt.toArray(new X509Certificate[crt.size()]);
    }

    public static PrivateKey readPrivateKey(final URL url)
            throws IOException, GeneralSecurityException
    {
        try (InputStream urlStream = url.openStream())
        {
            return readPrivateKey(urlStream);
        }
    }

    public static PrivateKey readPrivateKey(InputStream input)
            throws IOException, GeneralSecurityException
    {
        byte[] content = toByteArray(input);
        String contentAsString = new String(content, StandardCharsets.US_ASCII);
        if(contentAsString.contains("-----BEGIN ") && contentAsString.contains(" PRIVATE KEY-----"))
        {
            BufferedReader lineReader = new BufferedReader(new StringReader(contentAsString));

            String line;
            do
            {
                line = lineReader.readLine();
            } while(line != null && !(line.startsWith("-----BEGIN ") && line.endsWith(" PRIVATE KEY-----")));

            if(line != null)
            {
                StringBuilder keyBuilder = new StringBuilder();

                while((line = lineReader.readLine()) != null)
                {
                    if(line.startsWith("-----END ") && line.endsWith(" PRIVATE KEY-----"))
                    {
                        break;
                    }
                    keyBuilder.append(line);
                }

                content = Strings.decodeBase64(keyBuilder.toString());
            }
        }
        return readPrivateKey(content, "RSA");
    }

    private static byte[] toByteArray(final InputStream input) throws IOException
    {
        try(ByteArrayOutputStream buffer = new ByteArrayOutputStream())
        {

            byte[] tmp = new byte[1024];
            int read;
            while((read=input.read(tmp))!=-1)

            {
                buffer.write(tmp, 0, read);
            }

            return buffer.toByteArray();
        }
    }

    public static PrivateKey readPrivateKey(final byte[] content, final String algorithm)
            throws NoSuchAlgorithmException, InvalidKeySpecException
    {
        PrivateKey key;
        try
        {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(content);
            KeyFactory kf = KeyFactory.getInstance(algorithm);
            key = kf.generatePrivate(keySpec);
        }
        catch(InvalidKeySpecException e)
        {
            // not in PCKS#8 format - try parsing as PKCS#1
            RSAPrivateCrtKeySpec keySpec = getRSAKeySpec(content);
            KeyFactory kf = KeyFactory.getInstance(algorithm);
            try
            {
                key = kf.generatePrivate(keySpec);
            }
            catch(InvalidKeySpecException e2)
            {
                throw new InvalidKeySpecException("Cannot parse the provided key as either PKCS#1 or PCKS#8 format");
            }

        }
        return key;
    }

    private static RSAPrivateCrtKeySpec getRSAKeySpec(byte[] keyBytes) throws InvalidKeySpecException
    {

        ByteBuffer buffer = ByteBuffer.wrap(keyBytes);
        try
        {
            // PKCS#1 is encoded as a DER sequence of:
            // (version, modulus, publicExponent, privateExponent, primeP, primeQ,
            //  primeExponentP, primeExponentQ, crtCoefficient)

            int tag = ((int)buffer.get()) & 0xff;

            // check tag is that of a sequence
            if(((tag & 0x20) != 0x20) || ((tag & 0x1F) != 0x10))
            {
                throw new InvalidKeySpecException("Unable to parse key as PKCS#1 format");
            }

            int length = getLength(buffer);

            buffer = buffer.slice();
            buffer.limit(length);

            // first tlv is version - which we'll ignore
            byte versionTag = buffer.get();
            int versionLength = getLength(buffer);
            buffer.position(buffer.position()+versionLength);


            RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(
                    getInteger(buffer), getInteger(buffer), getInteger(buffer), getInteger(buffer), getInteger(buffer),
                    getInteger(buffer), getInteger(buffer), getInteger(buffer));

            return keySpec;
        }
        catch(BufferUnderflowException e)
        {
            throw new InvalidKeySpecException("Unable to parse key as PKCS#1 format");
        }
    }

    private static int getLength(ByteBuffer buffer)
    {

        int i = ((int) buffer.get()) & 0xff;

        // length 0 <= i <= 127 encoded as a single byte
        if ((i & ~0x7F) == 0)
        {
            return i;
        }

        // otherwise the first octet gives us the number of octets needed to read the length
        byte[] bytes = new byte[i & 0x7f];
        buffer.get(bytes);

        return new BigInteger(1, bytes).intValue();
    }

    private static BigInteger getInteger(ByteBuffer buffer) throws InvalidKeySpecException
    {
        int tag = ((int) buffer.get()) & 0xff;
        // 0x02 indicates an integer type
        if((tag & 0x1f) != 0x02)
        {
            throw new InvalidKeySpecException("Unable to parse key as PKCS#1 format");
        }
        byte[] num = new byte[getLength(buffer)];
        buffer.get(num);
        return new BigInteger(num);
    }

    public static void updateEnabledTlsProtocols(final SSLEngine engine,
                                                 final List<String> protocolWhiteList,
                                                 final List<String> protocolBlackList)
    {
        String[] filteredProtocols = filterEnabledProtocols(engine.getEnabledProtocols(),
                                                            engine.getSupportedProtocols(),
                                                            protocolWhiteList,
                                                            protocolBlackList);
        engine.setEnabledProtocols(filteredProtocols);
    }

    public static void updateEnabledTlsProtocols(final SSLSocket socket,
                                             final List<String> protocolWhiteList,
                                             final List<String> protocolBlackList)
    {
        String[] filteredProtocols = filterEnabledProtocols(socket.getEnabledProtocols(),
                                                            socket.getSupportedProtocols(),
                                                            protocolWhiteList,
                                                            protocolBlackList);
        socket.setEnabledProtocols(filteredProtocols);
    }

    public static String[] filterEnabledProtocols(final String[] enabledProtocols,
                                                  final String[] supportedProtocols,
                                                  final List<String> protocolWhiteList,
                                                  final List<String> protocolBlackList)
    {
        return filterEntries(enabledProtocols, supportedProtocols, protocolWhiteList, protocolBlackList);
    }

    public static String[] filterEnabledCipherSuites(final String[] enabledCipherSuites,
                                                     final String[] supportedCipherSuites,
                                                     final List<String> cipherSuiteWhiteList,
                                                     final List<String> cipherSuiteBlackList)
    {
        return filterEntries(enabledCipherSuites, supportedCipherSuites, cipherSuiteWhiteList, cipherSuiteBlackList);
    }


    public static void updateEnabledCipherSuites(final SSLEngine engine,
                                                 final List<String> cipherSuitesWhiteList,
                                                 final List<String> cipherSuitesBlackList)
    {
        String[] filteredCipherSuites = filterEntries(engine.getEnabledCipherSuites(),
                                                      engine.getSupportedCipherSuites(),
                                                      cipherSuitesWhiteList,
                                                      cipherSuitesBlackList);
        engine.setEnabledCipherSuites(filteredCipherSuites);
    }

    public static void updateEnabledCipherSuites(final SSLSocket socket,
                                                 final List<String> cipherSuitesWhiteList,
                                                 final List<String> cipherSuitesBlackList)
    {
        String[] filteredCipherSuites = filterEntries(socket.getEnabledCipherSuites(),
                                                      socket.getSupportedCipherSuites(),
                                                      cipherSuitesWhiteList,
                                                      cipherSuitesBlackList);
        socket.setEnabledCipherSuites(filteredCipherSuites);
    }

    static String[] filterEntries(final String[] enabledEntries,
                                  final String[] supportedEntries,
                                  final List<String> whiteList,
                                  final List<String> blackList)
    {
        List<String> filteredList;
        if (whiteList != null && !whiteList.isEmpty())
        {
            filteredList = new ArrayList<>();
            List<String> supportedList = new ArrayList<>(Arrays.asList(supportedEntries));
            // the outer loop must be over the white list to preserve its order
            for (String whiteListedRegEx : whiteList)
            {
                Iterator<String> supportedIter = supportedList.iterator();
                while (supportedIter.hasNext())
                {
                    String supportedEntry = supportedIter.next();
                    if (supportedEntry.matches(whiteListedRegEx))
                    {
                        filteredList.add(supportedEntry);
                        supportedIter.remove();
                    }
                }
            }
        }
        else
        {
            filteredList = new ArrayList<>(Arrays.asList(enabledEntries));
        }

        if (blackList != null && !blackList.isEmpty())
        {
            for (String blackListedRegEx : blackList)
            {
                Iterator<String> entriesIter = filteredList.iterator();
                while (entriesIter.hasNext())
                {
                    if (entriesIter.next().matches(blackListedRegEx))
                    {
                        entriesIter.remove();
                    }
                }
            }
        }

        return filteredList.toArray(new String[filteredList.size()]);
    }

    public static SSLContext tryGetSSLContext() throws NoSuchAlgorithmException
    {
        return tryGetSSLContext(TLS_PROTOCOL_PREFERENCES);
    }

    public static SSLContext tryGetSSLContext(final String[] protocols) throws NoSuchAlgorithmException
    {
        for (String protocol : protocols)
        {
            try
            {
                return SSLContext.getInstance(protocol);
            }
            catch (NoSuchAlgorithmException e)
            {
                // pass and try the next protocol in the list
            }
        }
        throw new NoSuchAlgorithmException(String.format("Could not create SSLContext with one of the requested protocols: %s",
                                                         Arrays.toString(protocols)));
    }

    public static boolean isSufficientToDetermineClientSNIHost(QpidByteBuffer buffer)
    {
        if(buffer.remaining() < 6)
        {
            return false;
        }
        else if(looksLikeSSLv3ClientHello(buffer))
        {
            final int position = buffer.position();
            final int recordSize = 5 + (((buffer.get(position + 3) & 0xFF) << 8) | (buffer.get(position + 4) & 0xFF));
            return buffer.remaining() >= recordSize;
        }
        else
        {
            return true;
        }
    }

    private static boolean looksLikeSSLv3ClientHello(QpidByteBuffer buffer)
    {
        int contentType = buffer.get(buffer.position()+0);
        int majorVersion = buffer.get(buffer.position()+1);
        int minorVersion = buffer.get(buffer.position()+2);
        int messageType = buffer.get(buffer.position()+5);

        return contentType == 22 && // SSL Handshake
                   (majorVersion == 3 && // SSL 3.0 / TLS 1.x
                    (minorVersion == 0 || // SSL 3.0
                     minorVersion == 1 || // TLS 1.0
                     minorVersion == 2 || // TLS 1.1
                     minorVersion == 3)) && // TLS1.2
                   (messageType == 1); // client_hello
    }

    public final static String getServerNameFromTLSClientHello(QpidByteBuffer source)
    {
        try (QpidByteBuffer input = source.duplicate())
        {

            // Do we have a complete header?
            if (!isSufficientToDetermineClientSNIHost(source))
            {
                throw new IllegalArgumentException("Source buffer does not contain enough data to determine the SNI name");
            }
            else if(!looksLikeSSLv3ClientHello(source))
            {
                return null;
            }

            byte contentType = input.get();
            byte majorVersion = input.get();
            byte minorVersion = input.get();
            if (minorVersion != 0x00) // not supported for SSL 3.0
            {

                int recordLength = input.getUnsignedShort();
                int messageType = input.get();
                // 24-bit length field
                int length = (input.getUnsignedByte() << 16) | (input.getUnsignedByte() << 8) | input.getUnsignedByte();
                if(input.remaining() < length)
                {
                    return null;
                }
                input.limit(length + input.position());

                input.position(input.position() + 34);  // hello minor/major version + random
                int skip = (int) input.get(); // session-id
                input.position(input.position() + skip);
                skip = input.getUnsignedShort(); // cipher suites
                input.position(input.position() + skip);
                skip = (int) input.get(); // compression methods
                input.position(input.position() + skip);

                if (input.hasRemaining())
                {

                    int remaining = input.getUnsignedShort();

                    if(input.remaining() < remaining)
                    {
                        // invalid remaining length
                        return null;
                    }

                    input.limit(input.position()+remaining);
                    while (input.hasRemaining())
                    {
                        int extensionType = input.getUnsignedShort();

                        int extensionLength = input.getUnsignedShort();

                        if (extensionType == 0x00)
                        {

                            int extensionDataRemaining = extensionLength;
                            if (extensionDataRemaining >= 2)
                            {
                                int listLength = input.getUnsignedShort();     // length of server_name_list
                                if (listLength + 2 != extensionDataRemaining)
                                {
                                    // invalid format
                                    return null;
                                }

                                extensionDataRemaining -= 2;
                                while (extensionDataRemaining > 0)
                                {
                                    int code = input.get();
                                    int serverNameLength = input.getUnsignedShort();
                                    if (serverNameLength > extensionDataRemaining)
                                    {
                                        // invalid format;
                                        return null;
                                    }
                                    byte[] encoded = new byte[serverNameLength];
                                    input.get(encoded);

                                    if (code == StandardConstants.SNI_HOST_NAME)
                                    {
                                        return new SNIHostName(encoded).getAsciiName();
                                    }
                                    extensionDataRemaining -= serverNameLength + 3;
                                }
                            }
                            return null;
                        }
                        else
                        {
                            if(input.remaining() < extensionLength)
                            {
                                return null;
                            }
                            input.position(input.position() + extensionLength);
                        }
                    }
                }

            }
            return null;
        }
    }

    public static SSLContext createSslContext(final org.apache.qpid.server.model.KeyStore keyStore,
                                              final Collection<TrustStore> trustStores,
                                              final String portName)
    {
        SSLContext sslContext;
        try
        {
            sslContext = tryGetSSLContext();
            KeyManager[] keyManagers = keyStore.getKeyManagers();

            TrustManager[] trustManagers;
            if(trustStores == null || trustStores.isEmpty())
            {
                trustManagers = null;
            }
            else if(trustStores.size() == 1)
            {
                trustManagers = trustStores.iterator().next().getTrustManagers();
            }
            else
            {
                Collection<TrustManager> trustManagerList = new ArrayList<>();
                final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager();

                for(TrustStore ts : trustStores)
                {
                    TrustManager[] managers = ts.getTrustManagers();
                    if(managers != null)
                    {
                        for(TrustManager manager : managers)
                        {
                            if(manager instanceof X509TrustManager)
                            {
                                mulTrustManager.addTrustManager((X509TrustManager)manager);
                            }
                            else
                            {
                                trustManagerList.add(manager);
                            }
                        }
                    }
                }
                if(!mulTrustManager.isEmpty())
                {
                    trustManagerList.add(mulTrustManager);
                }
                trustManagers = trustManagerList.toArray(new TrustManager[trustManagerList.size()]);
            }
            sslContext.init(keyManagers, trustManagers, null);
        }
        catch (GeneralSecurityException e)
        {
            throw new IllegalArgumentException(String.format("Cannot configure TLS on port '%s'", portName), e);
        }
        return sslContext;
    }

    public static boolean canGenerateCerts()
    {
        return CAN_GENERATE_CERTS;
    }

    public static KeyCertPair generateSelfSignedCertificate(final String keyAlgorithm,
                                                            final String signatureAlgorithm,
                                                            final int keyLength,
                                                            long startTime,
                                                            long duration,
                                                            String x500Name,
                                                            Set<String> dnsNames,
                                                            Set<InetAddress> addresses)
            throws IllegalAccessException, InvocationTargetException, InstantiationException
    {
        Object certAndKeyGen = CONSTRUCTOR.newInstance(keyAlgorithm, signatureAlgorithm);
        GENERATE_METHOD.invoke(certAndKeyGen, keyLength);
        final PrivateKey _privateKey = (PrivateKey) GET_PRIVATE_KEY_METHOD.invoke(certAndKeyGen);

        Object generalNames = GENERAL_NAMES_CONSTRUCTOR.newInstance();

        for(String dnsName : dnsNames)
        {
            if(dnsName.matches("[\\w&&[^\\d]][\\w\\d.-]*"))
            {
                ADD_NAME_TO_NAMES_METHOD.invoke(generalNames,
                                                GENERAL_NAME_CONSTRUCTOR.newInstance(DNS_NAME_CONSTRUCTOR.newInstance(
                                                        dnsName)));
            }
        }

        for(InetAddress inetAddress : addresses)
        {
            ADD_NAME_TO_NAMES_METHOD.invoke(generalNames, GENERAL_NAME_CONSTRUCTOR.newInstance(IP_ADDR_NAME_CONSTRUCTOR.newInstance(inetAddress.getHostAddress())));
        }
        Object certificateExtensions;
        if(dnsNames.isEmpty() && addresses.isEmpty())
        {
            certificateExtensions = null;
        }
        else
        {
            Object altNamesExtension = ALT_NAMES_CONSTRUCTOR.newInstance(generalNames);
            certificateExtensions = CERTIFICATE_EXTENSIONS_CONSTRUCTOR.newInstance();
            SET_EXTENSION_METHOD.invoke(certificateExtensions,
                                        EXTENSION_GET_NAME_METHOD.invoke(altNamesExtension),
                                        altNamesExtension);
        }

        final X509Certificate _certificate = (X509Certificate) GET_SELF_CERTIFICATE_METHOD.invoke(certAndKeyGen,
                                                                                                  X500_NAME_CONSTRUCTOR
                                                                                                          .newInstance(x500Name),
                                                                                                  new Date(startTime),
                                                                                                  duration,
                                                                                                  certificateExtensions);

        return new KeyCertPair()
        {
            @Override
            public PrivateKey getPrivateKey()
            {
                return _privateKey;
            }

            @Override
            public X509Certificate getCertificate()
            {
                return _certificate;
            }
        };

    }

    public static Collection<Certificate> getCertificates(final KeyStore ks) throws KeyStoreException
    {
        List<Certificate> certificates = new ArrayList<>();
        Enumeration<String> aliases = ks.aliases();
        while (aliases.hasMoreElements())
        {
            String alias = aliases.nextElement();
            if (ks.isCertificateEntry(alias))
            {
                certificates.add(ks.getCertificate(alias));
            }
        }
        return certificates;
    }

    public interface KeyCertPair
    {
        PrivateKey getPrivateKey();
        X509Certificate getCertificate();
    }
}
