From 7c2b635c8f01e96595090906b14d5a64d3d20c92 Mon Sep 17 00:00:00 2001
From: Peter Major <peter.major@forgerock.com>
Date: Fri, 06 May 2016 06:43:59 +0000
Subject: [PATCH] OPENDJ-2923 Use JVM's keyManager by default in SSLContextBuilder
---
opendj-core/src/main/java/org/forgerock/opendj/ldap/KeyManagers.java | 81 ++++++++++++++++++++++++++++++++++++++--
opendj-core/src/main/java/org/forgerock/opendj/ldap/SSLContextBuilder.java | 16 +++++---
2 files changed, 86 insertions(+), 11 deletions(-)
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/KeyManagers.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/KeyManagers.java
index 39f5573..9957447 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/KeyManagers.java
+++ b/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}.
*
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/SSLContextBuilder.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/SSLContextBuilder.java
index 169d966..fbacf49 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/SSLContextBuilder.java
+++ b/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) {
--
Gitblit v1.10.0