From 2cf46088b7e69b4f424a821291607afe6faa7e4f Mon Sep 17 00:00:00 2001
From: Yuriy Movchan <Yuriy.Movchan@gmail.com>
Date: Fri, 30 Jul 2021 14:08:39 +0000
Subject: [PATCH] Add FIPS support (#176)
---
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java | 3
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CryptoManagerConfiguration.xml | 4
opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedTrustManagerProvider.java | 12
opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java | 15 +
opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java | 60 ++++-
opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java | 3
opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/PKCS11TrustManagerProviderConfiguration.xml | 52 ++++
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java | 69 ++++++
opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ApplicationTrustManager.java | 5
opendj-server-legacy/src/main/java/org/opends/server/extensions/PKCS11TrustManagerProvider.java | 188 +++++++++++++++++
opendj-server-legacy/src/main/java/org/opends/server/config/ConfigurationHandler.java | 11
opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java | 30 ++
opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/Utils.java | 3
opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java | 14 +
opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java | 33 ++
opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/DSConfig.java | 3
opendj-server-legacy/src/main/java/org/opends/quicksetup/util/ServerController.java | 11
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/SetupLauncher.java | 4
opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPServerFilter.java | 11 +
opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties | 2
opendj-server-legacy/src/messages/org/opends/messages/extension.properties | 3
opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java | 52 ++++
opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java | 18 +
opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java | 17 +
opendj-server-legacy/src/main/java/org/forgerock/opendj/reactive/LDAPConnectionHandler2.java | 10
opendj-core/pom.xml | 16 +
26 files changed, 616 insertions(+), 33 deletions(-)
diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
index 3c70009..f9e3344 100644
--- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
+++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
@@ -34,12 +34,15 @@
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
@@ -63,6 +66,8 @@
import org.forgerock.opendj.ldap.requests.Requests;
import org.forgerock.util.Options;
+import com.forgerock.opendj.util.StaticUtils;
+
/** A connection factory designed for use with command line tools. */
public final class ConnectionFactoryProvider {
/** The Logger. */
@@ -356,7 +361,10 @@
* If an SSL context could not be created.
*/
public static List<String> getDefaultProtocols() throws NoSuchAlgorithmException {
- List<String> enabled = Arrays.asList(SSLContext.getDefault().createSSLEngine().getEnabledProtocols());
+ return getDefaultProtocols(SSLContext.getDefault());
+ }
+ public static List<String> getDefaultProtocols(SSLContext sslContext) throws NoSuchAlgorithmException {
+ List<String> enabled = Arrays.asList(sslContext.createSSLEngine().getEnabledProtocols());
final String property = System.getProperty("org.opends.ldaps.protocols");
final List<String> defaults = new ArrayList<>();
if (property != null && property.length() != 0) {
@@ -445,6 +453,8 @@
if (akm != null && clientAlias != null) {
keyManager = KeyManagers.useSingleCertificate(clientAlias, akm);
+ } else {
+ keyManager = akm;
}
sslContext =
@@ -462,7 +472,7 @@
try {
options.set(SSL_CONTEXT, sslContext)
.set(SSL_USE_STARTTLS, useStartTLSArg.isPresent())
- .set(SSL_ENABLED_PROTOCOLS, getDefaultProtocols());
+ .set(SSL_ENABLED_PROTOCOLS, getDefaultProtocols(sslContext));
} catch (NoSuchAlgorithmException e) {
throw new ArgumentException(ERR_LDAP_CONN_CANNOT_INITIALIZE_SSL.get(e.toString()), e);
}
@@ -694,9 +704,10 @@
* If a problem occurs while loading with the key store.
* @throws CertificateException
* If a problem occurs while loading with the key store.
+ * @throws UnrecoverableKeyException
*/
public X509KeyManager getKeyManager(String keyStoreFile) throws KeyStoreException,
- IOException, NoSuchAlgorithmException, CertificateException {
+ IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException {
if (keyStoreFile == null) {
// Lookup the file name through the JDK property.
keyStoreFile = getKeyStore();
@@ -712,11 +723,29 @@
keyStorePIN = keyStorePass.toCharArray();
}
- final KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
- try (final FileInputStream fos = new FileInputStream(keyStoreFile)) {
- keystore.load(fos, keyStorePIN);
+ boolean isFips = StaticUtils.isFips();
+ final String keyStoreType = KeyStore.getDefaultType();
+ final KeyStore keystore = KeyStore.getInstance(keyStoreType);
+ if (isFips) {
+ keystore.load(null, keyStorePIN);
+ } else {
+ try (final FileInputStream fos = new FileInputStream(keyStoreFile)) {
+ keystore.load(fos, keyStorePIN);
+ }
}
+ if (isFips) {
+ String keyManagerAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(keyManagerAlgorithm);
+ keyManagerFactory.init(keystore, keyStorePIN);
+
+ for (final KeyManager km : keyManagerFactory.getKeyManagers()) {
+ if (km instanceof X509KeyManager) {
+ return (X509KeyManager) km;
+ }
+ }
+ }
+
return new ApplicationKeyManager(keystore, keyStorePIN);
}
@@ -802,16 +831,25 @@
return TrustManagers.trustAll();
}
+ boolean isFips = StaticUtils.isFips();
X509TrustManager tm = null;
if (trustStorePathArg.isPresent() && trustStorePathArg.getValue().length() > 0) {
- tm = TrustManagers.checkValidityDates(TrustManagers.checkHostName(hostNameArg.getValue(),
- TrustManagers.checkUsingTrustStore(trustStorePathArg.getValue(), getTrustStorePIN(), null)));
+ if (isFips) {
+ tm = TrustManagers.checkUsingTrustStore(trustStorePathArg.getValue(), getTrustStorePIN(), null);
+ } else {
+ tm = TrustManagers.checkValidityDates(TrustManagers.checkHostName(hostNameArg.getValue(),
+ TrustManagers.checkUsingTrustStore(trustStorePathArg.getValue(), getTrustStorePIN(), null)));
+ }
} else if (getTrustStore() != null) {
- tm = TrustManagers.checkValidityDates(TrustManagers.checkHostName(hostNameArg.getValue(),
- TrustManagers.checkUsingTrustStore(getTrustStore(), getTrustStorePIN(), null)));
+ if (isFips) {
+ tm = TrustManagers.checkUsingTrustStore(getTrustStore(), getTrustStorePIN(), null);
+ } else {
+ tm = TrustManagers.checkValidityDates(TrustManagers.checkHostName(hostNameArg.getValue(),
+ TrustManagers.checkUsingTrustStore(getTrustStore(), getTrustStorePIN(), null)));
+ }
}
- if (app != null && !app.isQuiet()) {
+ if (app != null && !app.isQuiet() && !isFips) {
return new PromptingTrustManager(app, tm);
}
diff --git a/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java b/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java
index a4d48f0..0e3658f 100644
--- a/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java
+++ b/opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java
@@ -29,6 +29,8 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
+import java.security.Provider;
+import java.security.Security;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
@@ -729,4 +731,5 @@
public static LocalizableMessage conflictingArgsErrorMessage(final Argument arg1, final Argument arg2) {
return ERR_TOOL_CONFLICTING_ARGS.get(arg1.getLongIdentifier(), arg2.getLongIdentifier());
}
+
}
diff --git a/opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/DSConfig.java b/opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/DSConfig.java
index fcba0db..44abe97 100644
--- a/opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/DSConfig.java
+++ b/opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/DSConfig.java
@@ -28,6 +28,8 @@
import static org.forgerock.opendj.config.PropertyOption.*;
import static org.forgerock.opendj.config.dsconfig.ArgumentExceptionFactory.*;
+import static com.forgerock.opendj.util.StaticUtils.registerBcProvider;
+
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
@@ -1053,6 +1055,7 @@
private int run(String[] args) {
// Register global arguments and sub-commands.
try {
+ registerBcProvider();
initializeGlobalArguments();
initializeSubCommands();
} catch (ArgumentException e) {
diff --git a/opendj-core/pom.xml b/opendj-core/pom.xml
index 7413f11..a40b4db 100644
--- a/opendj-core/pom.xml
+++ b/opendj-core/pom.xml
@@ -90,10 +90,26 @@
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</dependency>
+
+ <!-- BC FIPS Provider libs -->
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bc-fips</artifactId>
+ <version>${bc.fips.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bctls-fips</artifactId>
+ <version>${bctls.fips.version}</version>
+ </dependency>
</dependencies>
<properties>
+ <bc.fips.version>1.0.2.1</bc.fips.version>
+ <bctls.fips.version>1.0.9</bctls.fips.version>
+
<opendj.osgi.import.additional>
com.sun.security.auth*;resolution:=optional
</opendj.osgi.import.additional>
diff --git a/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java b/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java
index b60cb2a..2a48a1a 100644
--- a/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java
+++ b/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java
@@ -42,6 +42,9 @@
import org.forgerock.util.Reject;
import org.forgerock.util.Utils;
+import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_PROVIDER_REGISTER;
+import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_PROVIDER_REGISTERED_ALREADY;
+
/**
* Common utility methods.
*/
@@ -786,4 +789,31 @@
}
}
+ public static boolean isFips() {
+ java.security.Provider[] providers = java.security.Security.getProviders();
+ for (int i = 0; i < providers.length; i++) {
+ if (providers[i].getName().toLowerCase().contains("fips"))
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void registerBcProvider()
+ {
+ if (!isFips()) {
+ return;
+ }
+
+ org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider bouncyCastleProvider = (org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider) java.security.Security.getProvider(org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider.PROVIDER_NAME);
+ if (bouncyCastleProvider == null) {
+ logger.info(INFO_BC_PROVIDER_REGISTER.get());
+
+ bouncyCastleProvider = new org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider();
+ java.security.Security.insertProviderAt(bouncyCastleProvider, 1);
+ } else {
+ logger.info(INFO_BC_PROVIDER_REGISTERED_ALREADY.get());
+ }
+ }
+
}
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java
index ad3335c..42cc7d0 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java
@@ -24,6 +24,8 @@
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
@@ -498,7 +500,10 @@
Reject.ifNull(file);
final File trustStoreFile = new File(file);
- final String trustStoreFormat = format != null ? format : KeyStore.getDefaultType();
+
+ boolean isFips = isFips();
+ final String defaultType = isFips ? "JKS" : KeyStore.getDefaultType();
+ final String trustStoreFormat = format != null ? format : defaultType;
final KeyStore keyStore = KeyStore.getInstance(trustStoreFormat);
try (FileInputStream fos = new FileInputStream(trustStoreFile)) {
@@ -517,6 +522,16 @@
throw new NoSuchAlgorithmException();
}
+ public static boolean isFips() {
+ Provider[] providers = Security.getProviders();
+ for (int i = 0; i < providers.length; i++) {
+ if (providers[i].getName().toLowerCase().contains("fips"))
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Wraps the provided {@code X509TrustManager} by adding additional
* validation which rejects certificate chains containing certificates which
diff --git a/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties b/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
index f5ec2c8..fd4eb60 100644
--- a/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
+++ b/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -616,6 +616,8 @@
INFO_RESULT_OFFSET_RANGE_ERROR=Offset Range Error
INFO_RESULT_VIRTUAL_LIST_VIEW_ERROR=Virtual List View Error
INFO_RESULT_NO_OPERATION=No Operation
+INFO_BC_PROVIDER_REGISTER=Registering Bouncy Castle Provider
+INFO_BC_PROVIDER_REGISTERED_ALREADY=Bouncy Castle Provider was registered already
#
# Protocol messages
#
diff --git a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
index bd638bb..8e7fb69 100644
--- a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
+++ b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
@@ -87,6 +87,8 @@
import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
import org.glassfish.grizzly.ssl.SSLFilter;
+import com.forgerock.opendj.util.StaticUtils;
+
/** LDAP connection implementation. */
final class GrizzlyLDAPConnection implements LDAPConnectionImpl, TimeoutEventListener {
static final int LDAP_V3 = 3;
@@ -95,12 +97,15 @@
* config. This prevents Grizzly from needlessly using JVM defaults which
* may be incorrectly configured.
*/
- private static final SSLEngineConfigurator DUMMY_SSL_ENGINE_CONFIGURATOR;
+ private static SSLEngineConfigurator DUMMY_SSL_ENGINE_CONFIGURATOR = null;
static {
try {
- DUMMY_SSL_ENGINE_CONFIGURATOR =
- new SSLEngineConfigurator(new SSLContextBuilder().setTrustManager(
- TrustManagers.distrustAll()).getSSLContext());
+ // We need to use FIPS compatible Trust Manasger in FIPS mode
+ if (!StaticUtils.isFips()) {
+ DUMMY_SSL_ENGINE_CONFIGURATOR =
+ new SSLEngineConfigurator(new SSLContextBuilder().setTrustManager(
+ TrustManagers.distrustAll()).getSSLContext());
+ }
} catch (GeneralSecurityException e) {
// This should never happen.
throw new IllegalStateException("Unable to create Dummy SSL Engine Configurator", e);
@@ -823,14 +828,30 @@
sslEngineConfigurator.setEnabledCipherSuites(cipherSuites.isEmpty() ? null : cipherSuites
.toArray(new String[cipherSuites.size()]));
sslEngineConfigurator.setCipherConfigured(true);
- final SSLFilter sslFilter = new SSLFilter(DUMMY_SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator);
+
+ SSLEngineConfigurator serverSslEngineConfigurator = buildServerSSLEngineConfigurator(sslContext);
+ final SSLFilter sslFilter = new SSLFilter(serverSslEngineConfigurator, sslEngineConfigurator);
sslFilter.setHandshakeTimeout(getLongProperty("org.forgerock.opendj.grizzly.handshakeTimeout", sslFilter.getHandshakeTimeout(TimeUnit.MILLISECONDS)), TimeUnit.MILLISECONDS);
installFilter(sslFilter);
sslFilter.handshake(connection, completionHandler);
}
}
- private LdapException adaptRequestIOException(final IOException e) {
+ private SSLEngineConfigurator buildServerSSLEngineConfigurator(SSLContext sslContext) {
+ if (DUMMY_SSL_ENGINE_CONFIGURATOR != null) {
+ return DUMMY_SSL_ENGINE_CONFIGURATOR;
+ }
+
+ if (sslContext == null) {
+ throw new IllegalStateException("SSL context should be defined in FIPS mode");
+ }
+
+ SSLEngineConfigurator sslEngineConfigurator = new SSLEngineConfigurator(sslContext);
+
+ return sslEngineConfigurator;
+ }
+
+ private LdapException adaptRequestIOException(final IOException e) {
// FIXME: what other sort of IOExceptions can be thrown?
// FIXME: Is this the best result code?
final Result errorResult = Responses.newResult(ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
diff --git a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPServerFilter.java b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPServerFilter.java
index e2bf6a7..a50834d 100644
--- a/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPServerFilter.java
+++ b/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPServerFilter.java
@@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.Properties;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@@ -71,6 +72,7 @@
import org.glassfish.grizzly.filterchain.FilterChainBuilder;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.filterchain.NextAction;
+import org.glassfish.grizzly.ssl.SSLContextConfigurator;
import org.glassfish.grizzly.ssl.SSLFilter;
import org.glassfish.grizzly.ssl.SSLUtils;
import org.reactivestreams.Publisher;
@@ -386,6 +388,15 @@
return false;
}
SSLUtils.setSSLEngine(connection, sslEngine);
+
+ Properties props = System.getProperties();
+
+ // Workaround for PKCS11
+ String keyStoreFile = props.getProperty(SSLContextConfigurator.KEY_STORE_FILE);
+ if ("none".equalsIgnoreCase(keyStoreFile)) {
+ System.setProperty(SSLContextConfigurator.TRUST_STORE_FILE, "NONE");
+ }
+
SSLFilter sslFilter = new SSLFilter();
sslFilter.setHandshakeTimeout(getLongProperty("org.forgerock.opendj.grizzly.handshakeTimeout", sslFilter.getHandshakeTimeout(TimeUnit.MILLISECONDS)), TimeUnit.MILLISECONDS);
installFilter(startTls ? new StartTLSFilter(sslFilter) : sslFilter);
diff --git a/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/Utils.java b/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/Utils.java
index d0eb549..54651f3 100644
--- a/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/Utils.java
+++ b/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/Utils.java
@@ -26,6 +26,8 @@
import static com.forgerock.opendj.ldap.tools.LDAPToolException.newToolParamException;
import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
+import static com.forgerock.opendj.util.StaticUtils.registerBcProvider;
+
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -463,6 +465,7 @@
@VisibleForTesting
static int runTool(final ToolConsoleApplication tool, final String... args) {
try {
+ registerBcProvider();
return tool.run(args);
} catch (final LDAPToolException e) {
e.printErrorMessage(tool);
diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CryptoManagerConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CryptoManagerConfiguration.xml
index 9629cb6..5a93a89 100644
--- a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CryptoManagerConfiguration.xml
+++ b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/CryptoManagerConfiguration.xml
@@ -48,7 +48,7 @@
</adm:requires-admin-action>
<adm:default-behavior>
<adm:defined>
- <adm:value>SHA-1</adm:value>
+ <adm:value>SHA-256</adm:value>
</adm:defined>
</adm:default-behavior>
<adm:syntax>
@@ -75,7 +75,7 @@
</adm:requires-admin-action>
<adm:default-behavior>
<adm:defined>
- <adm:value>HmacSHA1</adm:value>
+ <adm:value>HmacSHA256</adm:value>
</adm:defined>
</adm:default-behavior>
<adm:syntax>
diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/PKCS11TrustManagerProviderConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/PKCS11TrustManagerProviderConfiguration.xml
new file mode 100644
index 0000000..d21bc63
--- /dev/null
+++ b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/PKCS11TrustManagerProviderConfiguration.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ The contents of this file are subject to the terms of the Common Development and
+ Distribution License (the License). You may not use this file except in compliance with the
+ License.
+
+ You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ specific language governing permission and limitations under the License.
+
+ When distributing Covered Software, include this CDDL Header Notice in each file and include
+ the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ Header, with the fields enclosed by brackets [] replaced by your own identifying
+ information: "Portions Copyright [year] [name of copyright owner]".
+
+ Copyright 2007-2008 Sun Microsystems, Inc.
+ Portions Copyright 2011 ForgeRock AS.
+ ! -->
+<adm:managed-object name="pkcs11-trust-manager-provider"
+ plural-name="pkcs11-trust-manager-providers"
+ package="org.forgerock.opendj.server.config" extends="trust-manager-provider"
+ xmlns:adm="http://opendj.forgerock.org/admin"
+ xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
+ <adm:synopsis>
+ The
+ <adm:user-friendly-name />
+ enables the server to access the private
+ key information through the PKCS11 interface.
+ </adm:synopsis>
+ <adm:description>
+ This standard interface is used by cryptographic accelerators and
+ hardware security modules.
+ </adm:description>
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:name>ds-cfg-pkcs11-trust-manager-provider</ldap:name>
+ <ldap:superior>ds-cfg-trust-manager-provider</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:property-override name="java-class" advanced="true">
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>
+ org.opends.server.extensions.PKCS11TrustManagerProvider
+ </adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ </adm:property-override>
+ <adm:property-reference name="trust-store-pin" />
+ <adm:property-reference name="trust-store-pin-property" />
+ <adm:property-reference name="trust-store-pin-environment-variable" />
+ <adm:property-reference name="trust-store-pin-file" />
+</adm:managed-object>
diff --git a/opendj-server-legacy/src/main/java/org/forgerock/opendj/reactive/LDAPConnectionHandler2.java b/opendj-server-legacy/src/main/java/org/forgerock/opendj/reactive/LDAPConnectionHandler2.java
index 3ef1bf9..6746e51 100644
--- a/opendj-server-legacy/src/main/java/org/forgerock/opendj/reactive/LDAPConnectionHandler2.java
+++ b/opendj-server-legacy/src/main/java/org/forgerock/opendj/reactive/LDAPConnectionHandler2.java
@@ -22,6 +22,8 @@
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
+import static com.forgerock.opendj.util.StaticUtils.isFips;
+
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -92,6 +94,8 @@
import com.forgerock.reactive.ReactiveHandler;
import com.forgerock.reactive.Stream;
+import java.security.Provider;
+import java.security.Security;
/**
* This class defines a connection handler that will be used for communicating with clients over LDAP. It is actually
@@ -939,7 +943,11 @@
final TrustManager[] trustManagers =
trustMgrDN == null ? null : serverContext.getTrustManagerProvider(trustMgrDN).getTrustManagers();
SSLContext sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME);
- sslContext.init(keyManagers, trustManagers, null);
+ if (isFips()) {
+ sslContext.init(keyManagerProvider.getKeyManagers(), trustManagers, null);
+ } else {
+ sslContext.init(keyManagers, trustManagers, null);
+ }
return sslContext;
} catch (Exception e) {
logger.traceException(e);
diff --git a/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ApplicationTrustManager.java b/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ApplicationTrustManager.java
index 4d66575..bebb3d3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ApplicationTrustManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ApplicationTrustManager.java
@@ -458,4 +458,9 @@
}
return hostMatch;
}
+
+ public X509TrustManager getX509TrustManager() {
+ return trustManager;
+ }
+
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java b/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java
index 12a1de1..341b9fc 100644
--- a/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java
+++ b/opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionWrapper.java
@@ -26,6 +26,7 @@
import java.io.Closeable;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManager;
@@ -152,9 +153,18 @@
if (isLdaps || isStartTls)
{
try {
- options.set(SSL_CONTEXT, getSSLContext(trustManager, keyManager))
+ SSLContext sslContext = getSSLContext(trustManager, keyManager);
+
+ List<String> defaultProtocols;
+ if (trustManager == null) {
+ defaultProtocols = ConnectionFactoryProvider.getDefaultProtocols();
+ } else {
+ defaultProtocols = ConnectionFactoryProvider.getDefaultProtocols(sslContext);
+ }
+
+ options.set(SSL_CONTEXT, sslContext)
.set(SSL_USE_STARTTLS, isStartTls)
- .set(SSL_ENABLED_PROTOCOLS, ConnectionFactoryProvider.getDefaultProtocols());
+ .set(SSL_ENABLED_PROTOCOLS, defaultProtocols);
} catch (NoSuchAlgorithmException e) {
throw newLdapException(CLIENT_SIDE_PARAM_ERROR, "Unable to perform SSL initialization:" + e.getMessage());
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java b/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java
index b2da78b..5c36610 100644
--- a/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java
@@ -27,6 +27,7 @@
import static org.opends.admin.ads.ServerDescriptor.ServerProperty.*;
import static org.opends.admin.ads.util.ConnectionUtils.*;
import static org.opends.admin.ads.util.PreferredConnection.Type.*;
+import static org.opends.messages.AdminMessages.WARN_ADMIN_SET_PERMISSIONS_FAILED;
import static org.opends.messages.QuickSetupMessages.*;
import static org.opends.quicksetup.Step.*;
import static org.opends.quicksetup.installer.DataReplicationOptions.Type.*;
@@ -37,10 +38,15 @@
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.security.KeyStore;
import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -53,6 +59,8 @@
import java.util.Set;
import javax.naming.ldap.Rdn;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
import javax.swing.JPanel;
import org.forgerock.i18n.LocalizableMessage;
@@ -125,6 +133,8 @@
import org.opends.server.backends.task.TaskState;
import org.opends.server.tools.BackendTypeHelper;
import org.opends.server.tools.BackendTypeHelper.BackendTypeUIAdapter;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.FilePermission;
import org.opends.server.types.HostPort;
import org.opends.server.util.CertificateManager;
import org.opends.server.util.CollectionUtils;
@@ -205,6 +215,8 @@
private char[] selfSignedCertPw;
+ private ApplicationTrustManager trustManager;
+
private boolean registeredNewServerOnRemote;
private boolean createdAdministrator;
private boolean createdRemoteAds;
@@ -1363,6 +1375,8 @@
case PKCS11:
configureKeyAndTrustStore(CertificateManager.KEY_STORE_PATH_PKCS11, CertificateManager.KEY_STORE_TYPE_PKCS11,
CertificateManager.KEY_STORE_TYPE_JKS, sec);
+ configureAdminKeyAndTrustStore(CertificateManager.KEY_STORE_PATH_PKCS11, CertificateManager.KEY_STORE_TYPE_PKCS11,
+ CertificateManager.KEY_STORE_TYPE_JKS, sec);
break;
default:
@@ -1394,6 +1408,38 @@
}
}
+ private void configureAdminKeyAndTrustStore(final String keyStorePath, final String keyStoreType,
+ final String trustStoreType, final SecurityOptions sec) throws Exception
+ {
+ final String keystorePassword = sec.getKeystorePassword();
+ final String trustStorePath = getPath2("admin-truststore");
+
+ CertificateManager certManager = new CertificateManager(keyStorePath, keyStoreType, keystorePassword);
+ for (String keyStoreAlias : sec.getAliasesToUse())
+ {
+ SetupUtils.exportCertificate(certManager, keyStoreAlias, getTemporaryCertificatePath());
+ configureAdminTrustStore(trustStorePath, trustStoreType, keyStoreAlias, keystorePassword);
+ }
+
+ // Set default trustManager to allow check server startup status
+ if (com.forgerock.opendj.util.StaticUtils.isFips()) {
+ KeyStore truststore = null;
+ try (final FileInputStream fis = new FileInputStream(trustStorePath))
+ {
+ truststore = KeyStore.getInstance(trustStoreType);
+ truststore.load(fis, keystorePassword.toCharArray());
+ }
+ catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e)
+ {
+ // Nothing to do: if this occurs we will systematically refuse the certificates.
+ // Maybe we should avoid this and be strict, but we are in a best effort mode.
+ logger.warn(LocalizableMessage.raw("Error with the truststore"), e);
+ }
+
+ this.trustManager = new ApplicationTrustManager(truststore);
+ }
+ }
+
private void configureTrustStore(final String type, final String keyStoreAlias, final String password)
throws Exception
{
@@ -1406,6 +1452,28 @@
f.delete();
}
+ private void configureAdminTrustStore(final String trustStorePath, final String type, final String keyStoreAlias, final String password)
+ throws Exception
+ {
+ final String alias = keyStoreAlias != null ? keyStoreAlias : SELF_SIGNED_CERT_ALIASES[0];
+ final CertificateManager trustMgr = new CertificateManager(trustStorePath, type, password);
+ trustMgr.addCertificate(alias, new File(getTemporaryCertificatePath()));
+
+ createProtectedFile(getKeystorePinPath(), password);
+ final File f = new File(getTemporaryCertificatePath());
+ f.delete();
+ }
+
+ @Override
+ public ApplicationTrustManager getTrustManager()
+ {
+ if (trustManager != null) {
+ return trustManager;
+ }
+
+ return super.getTrustManager();
+ }
+
private void addCertificateArguments(SecurityOptions sec, List<String> argList)
{
final Collection<String> aliasInKeyStore = sec.getAliasesToUse();
@@ -4602,6 +4670,7 @@
FileManager fileManager = new FileManager();
fileManager.synchronize(getInstallation().getTemplateDirectory(), getInstallation().getInstanceDirectory());
}
+
}
/** Class used to be able to cancel long operations. */
diff --git a/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/SetupLauncher.java b/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/SetupLauncher.java
index cdeaa67..ff6820b 100644
--- a/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/SetupLauncher.java
+++ b/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/SetupLauncher.java
@@ -20,6 +20,8 @@
import static org.opends.messages.ToolMessages.*;
import static org.opends.server.util.ServerConstants.*;
+import static com.forgerock.opendj.util.StaticUtils.registerBcProvider;
+
import org.forgerock.i18n.LocalizableMessage;
import org.opends.quicksetup.CliApplication;
import org.opends.quicksetup.Installation;
@@ -91,6 +93,8 @@
try
{
argParser.parseArguments(args);
+
+ registerBcProvider();
if (argParser.isVersionArgumentPresent())
{
diff --git a/opendj-server-legacy/src/main/java/org/opends/quicksetup/util/ServerController.java b/opendj-server-legacy/src/main/java/org/opends/quicksetup/util/ServerController.java
index a4ee88a..a0dfdbc 100644
--- a/opendj-server-legacy/src/main/java/org/opends/quicksetup/util/ServerController.java
+++ b/opendj-server-legacy/src/main/java/org/opends/quicksetup/util/ServerController.java
@@ -23,6 +23,8 @@
import java.util.List;
import java.util.Map;
+import javax.net.ssl.TrustManager;
+
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.i18n.slf4j.LocalizedLogger;
@@ -39,6 +41,7 @@
import org.opends.server.util.SetupUtils;
import com.forgerock.opendj.cli.CliConstants;
+import com.forgerock.opendj.util.StaticUtils;
import static com.forgerock.opendj.cli.ArgumentConstants.*;
import static com.forgerock.opendj.cli.Utils.*;
@@ -308,6 +311,7 @@
* connect to the server after starting to verify that it is listening.
* @param suppressOutput indicating that ouput to standard output streams
* from the server should be suppressed.
+ * @param trustManager can be null
* @throws org.opends.quicksetup.ApplicationException if something goes wrong.
*/
private void startServer(boolean verifyCanConnect, boolean suppressOutput)
@@ -454,6 +458,11 @@
userDn = null;
userPw = null;
}
+
+ TrustManager trustManager = null;
+ if (StaticUtils.isFips()) {
+ trustManager = application.getTrustManager().getX509TrustManager();
+ }
for (int i=0; i<50 && !connected; i++)
{
@@ -463,7 +472,7 @@
timeout = application.getUserData().getConnectTimeout();
}
HostPort hp = new HostPort(getHostName(i), port);
- try (ConnectionWrapper conn = new ConnectionWrapper(hp, LDAPS, userDn, userPw, timeout, null))
+ try (ConnectionWrapper conn = new ConnectionWrapper(hp, LDAPS, userDn, userPw, timeout, trustManager))
{
return;
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/config/ConfigurationHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/config/ConfigurationHandler.java
index 42fea94..ae4c812 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/config/ConfigurationHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/config/ConfigurationHandler.java
@@ -589,10 +589,12 @@
* The original entry that is being replaced.
* @param newEntry
* The new entry to use in place of the existing entry with the same DN.
+ * @param structuralUpdate
+ * Force objectClass update.
* @throws DirectoryException
* If a problem occurs while trying to replace the entry.
*/
- public void replaceEntry(final Entry oldEntry, final Entry newEntry) throws DirectoryException
+ public void replaceEntry(final Entry oldEntry, final Entry newEntry, final boolean structuralUpdate) throws DirectoryException
{
final DN newEntryDN = newEntry.getName();
if (!backend.contains(newEntryDN))
@@ -601,7 +603,7 @@
ERR_CONFIG_FILE_MODIFY_NO_SUCH_ENTRY.get(oldEntry), getMatchedDN(newEntryDN), null);
}
- if (!Entries.getStructuralObjectClass(oldEntry, serverContext.getSchema()).equals(
+ if (!structuralUpdate && !Entries.getStructuralObjectClass(oldEntry, serverContext.getSchema()).equals(
Entries.getStructuralObjectClass(newEntry, serverContext.getSchema())))
{
throw new DirectoryException(ResultCode.NO_SUCH_OBJECT,
@@ -657,6 +659,11 @@
}
}
+ public void replaceEntry(final Entry oldEntry, final Entry newEntry) throws DirectoryException
+ {
+ replaceEntry(oldEntry, newEntry, false);
+ }
+
@Override
public void registerAddListener(final DN dn, final ConfigAddListener listener)
{
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
index 281fa0a..7c09ce0 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -27,6 +27,8 @@
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
+import static com.forgerock.opendj.util.StaticUtils.registerBcProvider;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -1403,6 +1405,7 @@
// The core Directory Server configuration.
coreConfigManager.initializeCoreConfig();
+ registerBcProvider();
initializeCryptoManager();
rotationPolicyConfigManager = new LogRotationPolicyConfigManager(serverContext);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedTrustManagerProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedTrustManagerProvider.java
index 3d74eac..f82d64c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedTrustManagerProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedTrustManagerProvider.java
@@ -43,6 +43,8 @@
import static org.opends.server.extensions.FileBasedKeyManagerProvider.getKeyStorePIN;
import static org.opends.server.util.StaticUtils.*;
+import static com.forgerock.opendj.util.StaticUtils.isFips;
+
/**
* This class defines a trust manager provider that will reference certificates
* stored in a file located on the Directory Server filesystem.
@@ -122,9 +124,13 @@
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
TrustManager[] newTrustManagers = new TrustManager[trustManagers.length];
- for (int i=0; i < trustManagers.length; i++)
- {
- newTrustManagers[i] = new ExpirationCheckTrustManager((X509TrustManager) trustManagers[i]);
+ if (isFips()) {
+ newTrustManagers = trustManagers;
+ } else {
+ for (int i=0; i < trustManagers.length; i++)
+ {
+ newTrustManagers[i] = new ExpirationCheckTrustManager((X509TrustManager) trustManagers[i]);
+ }
}
return newTrustManagers;
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/PKCS11TrustManagerProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/PKCS11TrustManagerProvider.java
new file mode 100644
index 0000000..e03490d
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/PKCS11TrustManagerProvider.java
@@ -0,0 +1,188 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2006-2010 Sun Microsystems, Inc.
+ * Portions Copyright 2021 Gluu, Inc.
+ */
+package org.opends.server.extensions;
+
+import org.forgerock.i18n.LocalizableMessage;
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.util.List;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import org.forgerock.opendj.config.server.ConfigurationChangeListener;
+import org.forgerock.opendj.server.config.server.TrustManagerProviderCfg;
+import org.forgerock.opendj.server.config.server.PKCS11TrustManagerProviderCfg;
+import org.opends.server.api.TrustManagerProvider;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.InitializationException;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.opends.server.util.ExpirationCheckTrustManager;
+
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import static org.opends.messages.ExtensionMessages.*;
+import static org.opends.server.extensions.FileBasedKeyManagerProvider.getKeyStorePIN;
+import static org.opends.server.util.StaticUtils.*;
+
+/**
+ * This class defines a trust manager provider that will reference certificates
+ * stored in a file located on the Directory Server filesystem.
+ */
+public class PKCS11TrustManagerProvider
+ extends TrustManagerProvider<PKCS11TrustManagerProviderCfg>
+ implements ConfigurationChangeListener<PKCS11TrustManagerProviderCfg>
+{
+ private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+
+ /** The truststore type to use when accessing the PKCS#11 keystore. */
+ private static final String PKCS11_TRUSTSTORE_TYPE = "PKCS11";
+
+ /** The PIN needed to access the trust store. */
+ private char[] trustStorePIN;
+
+ /** The handle to the configuration for this trust manager. */
+ private PKCS11TrustManagerProviderCfg currentConfig;
+
+ /**
+ * Creates a new instance of this file-based trust manager provider. The
+ * <CODE>initializeTrustManagerProvider</CODE> method must be called on the
+ * resulting object before it may be used.
+ */
+ public PKCS11TrustManagerProvider()
+ {
+ // No implementation is required.
+ }
+
+ @Override
+ public void initializeTrustManagerProvider(PKCS11TrustManagerProviderCfg cfg)
+ throws ConfigException, InitializationException
+ {
+ final ConfigChangeResult ccr = new ConfigChangeResult();
+
+ currentConfig = cfg;
+ trustStorePIN = getTrustStorePIN(cfg, ccr);
+ if (!ccr.getMessages().isEmpty())
+ {
+ throw new InitializationException(ccr.getMessages().get(0));
+ }
+
+ cfg.addPKCS11ChangeListener(this);
+ }
+
+ @Override
+ public void finalizeTrustManagerProvider()
+ {
+ currentConfig.removePKCS11ChangeListener(this);
+ }
+
+ @Override
+ public TrustManager[] getTrustManagers() throws DirectoryException
+ {
+ KeyStore trustStore;
+ try {
+ trustStore = KeyStore.getInstance(PKCS11_TRUSTSTORE_TYPE);
+ trustStore.load(null, trustStorePIN);
+ }
+ catch (Exception e)
+ {
+ logger.traceException(e);
+ LocalizableMessage message = ERR_PKCS11_KEYMANAGER_CANNOT_LOAD.get(getExceptionMessage(e));
+ throw new DirectoryException(DirectoryServer.getCoreConfigManager().getServerErrorResultCode(), message, e);
+ }
+
+ try
+ {
+ String trustManagerAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(trustManagerAlgorithm);
+ trustManagerFactory.init(trustStore);
+ TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+
+ return trustManagers;
+ }
+ catch (Exception e)
+ {
+ logger.traceException(e);
+
+ LocalizableMessage message =
+ ERR_PKCS11_TRUSTMANAGER_CANNOT_CREATE_FACTORY.get(getExceptionMessage(e));
+ throw new DirectoryException(DirectoryServer.getCoreConfigManager().getServerErrorResultCode(), message, e);
+ }
+ }
+
+ @Override
+ public boolean isConfigurationAcceptable(TrustManagerProviderCfg cfg, List<LocalizableMessage> unacceptableReasons)
+ {
+ PKCS11TrustManagerProviderCfg config = (PKCS11TrustManagerProviderCfg) cfg;
+ return isConfigurationChangeAcceptable(config, unacceptableReasons);
+ }
+
+ @Override
+ public boolean isConfigurationChangeAcceptable(PKCS11TrustManagerProviderCfg cfg,
+ List<LocalizableMessage> unacceptableReasons)
+ {
+ int startSize = unacceptableReasons.size();
+
+ final ConfigChangeResult ccr = new ConfigChangeResult();
+ getTrustStorePIN(cfg, ccr);
+ unacceptableReasons.addAll(ccr.getMessages());
+
+ return startSize == unacceptableReasons.size();
+ }
+
+ @Override
+ public ConfigChangeResult applyConfigurationChange(PKCS11TrustManagerProviderCfg cfg)
+ {
+ final ConfigChangeResult ccr = new ConfigChangeResult();
+ char[] newPIN = getTrustStorePIN(cfg, ccr);
+
+ if (ccr.getResultCode() == ResultCode.SUCCESS)
+ {
+ currentConfig = cfg;
+ trustStorePIN = newPIN;
+ }
+
+ return ccr;
+ }
+
+ private char[] getTrustStorePIN(PKCS11TrustManagerProviderCfg cfg, ConfigChangeResult ccr)
+ {
+ try
+ {
+ return FileBasedKeyManagerProvider.getKeyStorePIN(cfg.getTrustStorePinProperty(),
+ cfg.getTrustStorePinEnvironmentVariable(),
+ cfg.getTrustStorePinFile(),
+ cfg.getTrustStorePin(),
+ cfg.dn(),
+ ERR_FILE_TRUSTMANAGER_PIN_PROPERTY_NOT_SET,
+ ERR_FILE_TRUSTMANAGER_PIN_ENVAR_NOT_SET,
+ ERR_FILE_TRUSTMANAGER_PIN_NO_SUCH_FILE,
+ ERR_FILE_TRUSTMANAGER_PIN_FILE_CANNOT_READ,
+ ERR_FILE_TRUSTMANAGER_PIN_FILE_EMPTY);
+ }
+ catch (InitializationException e)
+ {
+ ccr.setResultCode(DirectoryServer.getCoreConfigManager().getServerErrorResultCode());
+ ccr.addMessage(e.getMessageObject());
+ return null;
+ }
+ }
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
index a654e32..84990d9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
@@ -85,6 +85,7 @@
import com.forgerock.opendj.cli.FileBasedArgument;
import com.forgerock.opendj.cli.IntegerArgument;
import com.forgerock.opendj.cli.StringArgument;
+import com.forgerock.opendj.util.StaticUtils;
/**
* This class provides a very basic tool that can be used to configure some of
@@ -187,6 +188,8 @@
+ "ds-cfg-trust-store-type: JCEKS" + NEW_LINE
+ "ds-cfg-trust-store-file: config/truststore" + NEW_LINE;
+ private static final String DN_ADMIN_KEY_MANAGER = "cn=Administration,cn=Key Manager Providers," + DN_CONFIG_ROOT;
+
/** The DN of the configuration entry defining the LDAP connection handler. */
private static final String DN_LDAP_CONNECTION_HANDLER = "cn=LDAP Connection Handler," + DN_CONNHANDLER_BASE;
/** The DN of the configuration entry defining the Administration connector. */
@@ -878,6 +881,9 @@
putKeyManagerConfigAttribute(enableStartTLS, DN_LDAP_CONNECTION_HANDLER);
putKeyManagerConfigAttribute(ldapsPort, DN_LDAPS_CONNECTION_HANDLER);
putKeyManagerConfigAttribute(ldapsPort, DN_HTTP_CONNECTION_HANDLER);
+ if (StaticUtils.isFips()) {
+ putAdminKeyManagerConfigAttribute(ldapsPort, DN_ADMIN_KEY_MANAGER);
+ }
if (keyManagerPath.isPresent())
{
@@ -917,6 +923,39 @@
}
}
+ private void putAdminKeyManagerConfigAttribute(final Argument arg, final String attributeDN)
+ throws ConfigureDSException
+ {
+ if (arg.isPresent())
+ {
+ try
+ {
+ updateConfigEntryByRemovingAttribute(attributeDN, ATTR_KEYSTORE_TYPE);
+ updateConfigEntryByRemovingAttribute(attributeDN, ATTR_KEYSTORE_FILE);
+
+ updateConfigEntryWithObjectClasses(
+ attributeDN,
+ "top", "ds-cfg-pkcs11-key-manager-provider", "ds-cfg-key-manager-provider");
+
+ updateConfigEntryWithAttribute(
+ attributeDN,
+ ATTR_KEYMANAGER_CLASS,
+ CoreSchema.getDirectoryStringSyntax(),
+ "org.opends.server.extensions.PKCS11KeyManagerProvider");
+
+ updateConfigEntryWithAttribute(
+ attributeDN,
+ ATTR_KEYSTORE_PIN_FILE,
+ CoreSchema.getDirectoryStringSyntax(),
+ "config/keystore.pin");
+ }
+ catch (final Exception e)
+ {
+ throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_KEYMANAGER_REFERENCE.get(e));
+ }
+ }
+ }
+
private void updateTrustManager() throws ConfigureDSException
{
if (trustManagerProviderDN.isPresent())
@@ -1127,6 +1166,15 @@
configHandler.replaceEntry(configEntry, Converters.from(newEntry));
}
+ /** Update a config entry with the provided objectCLass parameters. */
+ private void updateConfigEntryWithObjectClasses(String entryDn, Object...objectCLasses)
+ throws DirectoryException, ConfigException
+ {
+ org.forgerock.opendj.ldap.Entry configEntry = configHandler.getEntry(DN.valueOf(entryDn));
+ final org.forgerock.opendj.ldap.Entry newEntry = putAttribute(configEntry, ATTR_OBJECTCLASS, CoreSchema.getOIDSyntax(), objectCLasses);
+ configHandler.replaceEntry(configEntry, newEntry, true);
+ }
+
/**
* Duplicate the provided entry, and put an attribute to the duplicated entry.
* <p>
@@ -1158,7 +1206,7 @@
{
if (t.hasNameOrOID(attrName))
{
- entry.getUserAttributes().remove(t);
+ duplicateEntry.getUserAttributes().remove(t);
return duplicateEntry;
}
}
@@ -1167,7 +1215,7 @@
{
if (t.hasNameOrOID(attrName))
{
- entry.getOperationalAttributes().remove(t);
+ duplicateEntry.getOperationalAttributes().remove(t);
return duplicateEntry;
}
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java
index 487bfe5..8410788 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java
@@ -825,7 +825,7 @@
certType = SecurityOptions.CertificateType.NO_CERTIFICATE;
}
- Collection<String> certNicknames = argParser.certNicknameArg.getValues();
+ Collection<String> certNicknames = getCertNickNames();
if (pathToCertificat != null)
{
checkCertificateInKeystore(certType, pathToCertificat, pwd, certNicknames, errorMessages, keystoreAliases);
@@ -840,6 +840,20 @@
uData.setSecurityOptions(securityOptions);
}
+ private List<String> getCertNickNames() {
+ List<String> certNicknames = argParser.certNicknameArg.getValues();
+ if ((certNicknames == null) || (certNicknames.size() == 0)) {
+ return certNicknames;
+ }
+
+ List<String> splitedCertNicknames = new ArrayList<>();
+ for (String certNickname : certNicknames) {
+ splitedCertNicknames.addAll(StaticUtils.splittedStringAsList(certNickname, " "));
+ }
+
+ return splitedCertNicknames;
+ }
+
private void checkCanUsePort(int port, List<LocalizableMessage> errorMessages)
{
if (!SetupUtils.canUseAsPort(port))
@@ -1943,7 +1957,7 @@
boolean enableStartTLS, int ldapsPort) throws UserDataException, ClientException
{
String path;
- Collection<String> certNicknames = argParser.certNicknameArg.getValues();
+ Collection<String> certNicknames = getCertNickNames();
String pwd = argParser.getKeyStorePassword();
if (pwd != null && pwd.length() == 0)
{
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java b/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java
index 14a6713..c20ee44 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java
@@ -71,6 +71,8 @@
import com.forgerock.opendj.cli.Argument;
import com.forgerock.opendj.cli.ArgumentException;
+import java.security.Provider;
+import java.security.Security;
/**
* This class defines a number of static utility methods that may be used
@@ -2579,5 +2581,18 @@
}
}
}
+
+ public static List<String> splittedStringAsList(String str, String delim) {
+ final List<String> result = new ArrayList<String>();
+ if ((str != null) && !str.isEmpty()) {
+ final String[] array = str.split(delim);
+ if (array.length > 0) {
+ result.addAll(Arrays.asList(array));
+ }
+ }
+
+ return result;
+ }
+
}
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/extension.properties b/opendj-server-legacy/src/messages/org/opends/messages/extension.properties
index 62df785..84aa00c 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/extension.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/extension.properties
@@ -175,6 +175,9 @@
ERR_FILE_TRUSTMANAGER_INVALID_TYPE_106=The trust store type %s \
specified in attribute ds-cfg-trust-store-type of configuration entry %s is \
not valid: %s
+ERR_PKCS11_TRUSTMANAGER_CANNOT_CREATE_FACTORY_107=An error occurred while \
+ trying to create a trust manager factory to access the contents of the PKCS#11 \
+ truststore: %s
ERR_SEDCM_NO_PEER_CERTIFICATE_118=Could not map the provided certificate \
chain to a user entry because no peer certificate was available
ERR_SEDCM_PEER_CERT_NOT_X509_119=Could not map the provided certificate \
--
Gitblit v1.10.0