Search in sources :

Example 1 with TlsType

use of org.xipki.httpserver.v1.jaxb.TlsType in project xipki by xipki.

the class HttpServers method buildSslContext.

private SslContext buildSslContext(HttpserverType conf) throws Exception {
    TlsType tt = conf.getTls();
    if (tt == null) {
        return null;
    }
    KeystoreType kst = tt.getKeystore();
    SslContextBuilder builder;
    // key and certificate
    if (kst == null) {
        throw new IllegalArgumentException("no keystore is configured");
    } else {
        char[] kstPwd = passwordResolver.resolvePassword(kst.getPassword());
        KeyStore ks = loadKeyStore(kst.getType(), kst.getStore(), kstPwd);
        String alias = kst.getKeyAlias();
        if (alias != null) {
            if (!ks.isKeyEntry(alias)) {
                throw new Exception("'" + alias + "' is not a valid key alias");
            }
        } else {
            Enumeration<String> aliases = ks.aliases();
            while (aliases.hasMoreElements()) {
                String al = aliases.nextElement();
                if (ks.isKeyEntry(al)) {
                    alias = al;
                    break;
                }
            }
            if (alias == null) {
                throw new Exception("found no key entries in the keystore");
            }
        }
        char[] keypwd = (kst.getKeyPassword() == null) ? kstPwd : passwordResolver.resolvePassword(kst.getKeyPassword());
        PrivateKey key = (PrivateKey) ks.getKey(alias, keypwd);
        Certificate[] certs = ks.getCertificateChain(alias);
        X509Certificate[] keyCertChain = new X509Certificate[certs.length];
        for (int i = 0; i < certs.length; i++) {
            keyCertChain[i] = (X509Certificate) certs[i];
        }
        builder = SslContextBuilder.forServer(key, keyCertChain);
    }
    boolean opensslAvailable = OpenSsl.isAvailable();
    // providers
    SslProvider sslProvider;
    if (tt.getProvider() == null) {
        if (!opensslAvailable) {
            logOpenSslWarning();
        }
        sslProvider = SslContext.defaultServerProvider();
    } else {
        String providerStr = tt.getProvider();
        String providerStr0 = providerStr.toLowerCase().replaceAll("[^a-z0-9]+", "");
        if ("jdk".equals(providerStr0)) {
            sslProvider = SslProvider.JDK;
        } else if ("openssl".equals(providerStr0) || "opensslrefcnt".equals(providerStr0)) {
            if (!opensslAvailable) {
                logOpenSslWarning();
                throw new Exception("OpenSSL not available");
            }
            sslProvider = "openssl".equals(providerStr0) ? SslProvider.OPENSSL : SslProvider.OPENSSL_REFCNT;
        } else {
            throw new Exception("unknwon SSL provider " + providerStr);
        }
    }
    LOG.info("use SSL provider {}", sslProvider);
    builder.sslProvider(sslProvider);
    List<String> availableProtocols;
    List<String> availableCiphersuits;
    switch(sslProvider) {
        case JDK:
            SSLParameters sslParams = SSLContext.getDefault().getSupportedSSLParameters();
            availableProtocols = Arrays.asList(sslParams.getProtocols());
            availableCiphersuits = Arrays.asList(sslParams.getCipherSuites());
            break;
        case OPENSSL:
        case OPENSSL_REFCNT:
            // any way to get the supported protocols of OpenSSL?
            availableProtocols = Arrays.asList("TLSv1.1", "TLSv1.2");
            availableCiphersuits = new ArrayList<>(OpenSsl.availableJavaCipherSuites());
            break;
        default:
            throw new RuntimeException("should not reach here, unknown SssProvider " + sslProvider);
    }
    // protocols
    List<String> protocols;
    if (tt.getProtocols() != null) {
        protocols = tt.getProtocols().getProtocol();
    } else {
        protocols = Arrays.asList("TLSv1.1", "TLSv1.2");
    }
    final String[] strArray = new String[0];
    Set<String> usedProtocols = new HashSet<>();
    for (String protocol : protocols) {
        boolean added = false;
        for (String supported : availableProtocols) {
            if (protocol.equalsIgnoreCase(supported)) {
                usedProtocols.add(supported);
                added = true;
                break;
            }
        }
        if (!added) {
            LOG.warn("SSL Protocol {} unsupported, ignore it", protocol);
        }
    }
    if (usedProtocols.isEmpty()) {
        throw new Exception("None of the configured SSL protocols is supported");
    }
    LOG.info("use SSL protocols {}", usedProtocols);
    builder.protocols(usedProtocols.toArray(strArray));
    // canonicalize the cipher suites
    boolean cipherWithTls = availableCiphersuits.get(0).startsWith("TLS_");
    // cipher suites
    Set<String> usedCipherSuites = new HashSet<>();
    if (tt.getCiphersuites() != null) {
        for (String cipherSuite : tt.getCiphersuites().getCiphersuite()) {
            if (cipherSuite.length() < 5) {
                LOG.warn("cipher suite {} unsupported, ignore it", cipherSuite);
                continue;
            }
            String adaptedCipher;
            if (cipherWithTls == cipherSuite.startsWith("TLS_")) {
                adaptedCipher = cipherSuite;
            } else {
                if (cipherWithTls) {
                    adaptedCipher = "TLS_" + cipherSuite.substring(4);
                } else {
                    adaptedCipher = "SSL_" + cipherSuite.substring(4);
                }
            }
            boolean added = false;
            for (String supported : availableCiphersuits) {
                if (adaptedCipher.equalsIgnoreCase(supported)) {
                    usedCipherSuites.add(supported);
                    added = true;
                    break;
                }
            }
            if (!added) {
                LOG.warn("SSL cipher suite {} unsupported, ignore it", cipherSuite);
            }
        }
    } else {
        String[] excludeMiddlePatterns = { "_3DES", "_DES", "EMPTY", "EXPORT", "anno", "NULL" };
        String[] excludeEndPatterns = { "MD5", "SHA" };
        for (String cipherSuite : availableCiphersuits) {
            boolean add = true;
            for (String p : excludeMiddlePatterns) {
                if (cipherSuite.contains(p)) {
                    add = false;
                    break;
                }
            }
            if (add) {
                for (String p : excludeEndPatterns) {
                    if (cipherSuite.endsWith(p)) {
                        add = false;
                        break;
                    }
                }
            }
            if (add) {
                usedCipherSuites.add(cipherSuite);
            }
        }
    }
    LOG.info("use SSL cipher suites {}", usedCipherSuites);
    builder.ciphers(usedCipherSuites);
    // client authentication
    ClientAuth clientAuth;
    String str = tt.getClientauth();
    if ("none".equalsIgnoreCase(str)) {
        clientAuth = ClientAuth.NONE;
    } else if ("optional".equalsIgnoreCase(str)) {
        clientAuth = ClientAuth.OPTIONAL;
    } else if ("require".equalsIgnoreCase(str)) {
        clientAuth = ClientAuth.REQUIRE;
    } else {
        throw new Exception("invalid client authentication '" + str + "'");
    }
    builder.clientAuth(clientAuth);
    if (clientAuth != ClientAuth.NONE) {
        TruststoreType tst = tt.getTruststore();
        if (tst == null) {
            throw new Exception("Client authentication is activated, but no truststore is configured");
        }
        char[] pwd = passwordResolver.resolvePassword(tst.getPassword());
        KeyStore ks = loadKeyStore(tst.getType(), tst.getStore(), pwd);
        List<X509Certificate> trustcerts = new LinkedList<>();
        Enumeration<String> aliases = ks.aliases();
        while (aliases.hasMoreElements()) {
            String alias = aliases.nextElement();
            Certificate cert = ks.getCertificate(alias);
            trustcerts.add((X509Certificate) cert);
        }
        if (trustcerts.isEmpty()) {
            throw new Exception("No certificates found int the truststore. Please verify it via" + " JDK's keytool.");
        }
        builder.trustManager(trustcerts.toArray(new X509Certificate[0]));
    }
    return builder.build();
}
Also used : PrivateKey(java.security.PrivateKey) KeystoreType(org.xipki.httpserver.v1.jaxb.KeystoreType) ClientAuth(io.netty.handler.ssl.ClientAuth) SSLParameters(javax.net.ssl.SSLParameters) HashSet(java.util.HashSet) TlsType(org.xipki.httpserver.v1.jaxb.TlsType) KeyStore(java.security.KeyStore) KeyStoreException(java.security.KeyStoreException) IOException(java.io.IOException) CertificateException(java.security.cert.CertificateException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) X509Certificate(java.security.cert.X509Certificate) LinkedList(java.util.LinkedList) TruststoreType(org.xipki.httpserver.v1.jaxb.TruststoreType) SslContextBuilder(io.netty.handler.ssl.SslContextBuilder) SslProvider(io.netty.handler.ssl.SslProvider) X509Certificate(java.security.cert.X509Certificate) Certificate(java.security.cert.Certificate)

Aggregations

ClientAuth (io.netty.handler.ssl.ClientAuth)1 SslContextBuilder (io.netty.handler.ssl.SslContextBuilder)1 SslProvider (io.netty.handler.ssl.SslProvider)1 IOException (java.io.IOException)1 KeyStore (java.security.KeyStore)1 KeyStoreException (java.security.KeyStoreException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 PrivateKey (java.security.PrivateKey)1 Certificate (java.security.cert.Certificate)1 CertificateException (java.security.cert.CertificateException)1 X509Certificate (java.security.cert.X509Certificate)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 SSLParameters (javax.net.ssl.SSLParameters)1 KeystoreType (org.xipki.httpserver.v1.jaxb.KeystoreType)1 TlsType (org.xipki.httpserver.v1.jaxb.TlsType)1 TruststoreType (org.xipki.httpserver.v1.jaxb.TruststoreType)1