mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Peter Major
19.53.2016 7c2b635c8f01e96595090906b14d5a64d3d20c92
OPENDJ-2923 Use JVM's keyManager by default in SSLContextBuilder
2 files modified
97 ■■■■ changed files
opendj-core/src/main/java/org/forgerock/opendj/ldap/KeyManagers.java 81 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/SSLContextBuilder.java 16 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/KeyManagers.java
@@ -38,6 +38,13 @@
/** This class contains methods for creating common types of key manager. */
public final class KeyManagers {
    private static final String KEY_STORE_PROVIDER = "javax.net.ssl.keyStoreProvider";
    private static final String KEY_STORE_TYPE = "javax.net.ssl.keyStoreType";
    private static final String KEY_STORE_FILE = "javax.net.ssl.keyStore";
    private static final String KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword";
    private static volatile X509KeyManager jvmKeyManager = null;
    /**
     * This class implements an X.509 key manager that will be used to wrap an
     * existing key manager and makes it possible to configure which
@@ -189,18 +196,51 @@
     */
    public static X509KeyManager useKeyStoreFile(final String file, final char[] password,
            final String format) throws GeneralSecurityException, IOException {
        return useKeyStoreFile(file, password, format, null);
    }
    /**
     * Creates a new {@code X509KeyManager} which will use the named key store
     * file for retrieving certificates. It will use the provided key store
     * format and password.
     *
     * @param file
     *            The key store file name.
     * @param password
     *            The key store password, which may be {@code null}.
     * @param format
     *            The key store format, which may be {@code null} to indicate that the default key store format for the
     *            JVM (e.g. {@code JKS}) should be used.
     * @param provider
     *            The key store provider, which may be {@code null} to indicate that the default key store provider for
     *            the JVM should be used.
     * @return A new {@code X509KeyManager} which will use the named key store file for retrieving certificates.
     * @throws GeneralSecurityException
     *            If the key store could not be loaded, perhaps due to incorrect format, or missing algorithms.
     * @throws IOException
     *            If the key store file could not be found or could not be read.
     * @throws NullPointerException
     *            If {@code file} was {@code null}.
     */
    public static X509KeyManager useKeyStoreFile(final String file, final char[] password,
            final String format, String provider) throws GeneralSecurityException, IOException {
        Reject.ifNull(file);
        final File keyStoreFile = new File(file);
        final String keyStoreFormat = format != null ? format : KeyStore.getDefaultType();
        final KeyStore keyStore = KeyStore.getInstance(keyStoreFormat);
        try (FileInputStream fos = new FileInputStream(keyStoreFile)) {
            keyStore.load(fos, password);
        final KeyStore keyStore;
        if (provider != null) {
            keyStore = KeyStore.getInstance(keyStoreFormat, provider);
        } else {
            keyStore = KeyStore.getInstance(keyStoreFormat);
        }
        final KeyManagerFactory kmf =
                KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        try (FileInputStream fis = new FileInputStream(keyStoreFile)) {
            keyStore.load(fis, password);
        }
        final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, password);
        X509KeyManager x509km = null;
@@ -257,6 +297,37 @@
    }
    /**
     * Creates a new {@code X509KeyManager} which will use the JVM's default keystore for retrieving certificates.
     *
     * @return A new {@code X509KeyManager} which will use the JVM's default keystore for retrieving certificates or
     *             {@code null} if the necessary JVM settings are missing.
     * @throws GeneralSecurityException
     *             If the key store could not be loaded, perhaps due to incorrect format, or missing algorithms.
     * @throws IOException
     *             If the key store file could not be found or could not be read.
     */
    public static X509KeyManager useJvmDefaultKeyStore() throws GeneralSecurityException, IOException {
        if (jvmKeyManager == null) {
            final String keyStoreFile = System.getProperty(KEY_STORE_FILE);
            if (keyStoreFile != null) {
                synchronized (KeyManagers.class) {
                    if (jvmKeyManager == null) {
                        final String keyStoreProvider = System.getProperty(KEY_STORE_PROVIDER);
                        final String keyStoreType = System.getProperty(KEY_STORE_TYPE, KeyStore.getDefaultType());
                        final String keyStorePassword = System.getProperty(KEY_STORE_PASSWORD);
                        jvmKeyManager = useKeyStoreFile(keyStoreFile,
                                keyStorePassword != null ? keyStorePassword.toCharArray() : null,
                                keyStoreType, keyStoreProvider);
                    }
                }
            }
        }
        return jvmKeyManager;
    }
    /**
     * Returns a new {@code X509KeyManager} which selects the named certificate
     * from the provided {@code X509KeyManager}.
     *
opendj-core/src/main/java/org/forgerock/opendj/ldap/SSLContextBuilder.java
@@ -16,6 +16,7 @@
 */
package org.forgerock.opendj.ldap;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.SecureRandom;
@@ -80,7 +81,11 @@
    /** Creates a new SSL context builder using default parameters. */
    public SSLContextBuilder() {
        // Do nothing.
        try {
            keyManager = KeyManagers.useJvmDefaultKeyStore();
        } catch (GeneralSecurityException | IOException ex) {
            keyManager = null;
        }
    }
    /**
@@ -101,7 +106,7 @@
        KeyManager[] km = null;
        if (keyManager != null) {
            km = new KeyManager[] { keyManager };
            km = new KeyManager[]{keyManager};
        }
        SSLContext sslContext;
@@ -118,12 +123,11 @@
    }
    /**
     * Sets the key manager which the SSL context should use. By default, no key
     * manager is specified indicating that no certificates will be used.
     * Sets the key manager which the SSL context should use. By default, the JVM's key manager is used.
     *
     * @param keyManager
     *            The key manager which the SSL context should use, which may be
     *            {@code null} indicating that no certificates will be used.
     *            The key manager which the SSL context should use, which may be {@code null} indicating that no
     *            certificates will be used.
     * @return This SSL context builder.
     */
    public SSLContextBuilder setKeyManager(final KeyManager keyManager) {