From 70d9a179cdd8d975b44e1815c249e20d9f91097f Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 16 Sep 2026 08:10:15 +0000
Subject: [PATCH] [#912] Provision the ads-truststore from an existing key store at setup time (#984)

---
 opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java |  115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 115 insertions(+), 0 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java b/opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java
index ea304f8..d4267e5 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/util/Platform.java
@@ -23,6 +23,7 @@
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.math.BigInteger;
+import java.security.Key;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.KeyStore;
@@ -56,6 +57,7 @@
 import static org.opends.messages.UtilityMessages.ERR_CERTMGR_CERT_REPLIES_INVALID;
 import static org.opends.messages.UtilityMessages.ERR_CERTMGR_DELETE_ALIAS;
 import static org.opends.messages.UtilityMessages.ERR_CERTMGR_GEN_SELF_SIGNED_CERT;
+import static org.opends.messages.UtilityMessages.ERR_CERTMGR_IMPORT_KEY_ENTRY;
 import static org.opends.messages.UtilityMessages.ERR_CERTMGR_KEYSTORE_NONEXISTANT;
 import static org.opends.messages.UtilityMessages.ERR_CERTMGR_TRUSTED_CERT;
 
@@ -190,6 +192,62 @@
       }
     }
 
+    private final void importKeyEntry(KeyStore ks, String ksType, String ksPath, String alias, char[] pwd,
+                                      Key privateKey, Certificate[] chain) throws KeyStoreException
+    {
+      try
+      {
+        if (ks == null)
+        {
+          ks = KeyStore.getInstance(ksType);
+          ks.load(null, pwd);
+        }
+        else if (ks.containsAlias(alias))
+        {
+          // setKeyEntry would silently replace whatever the alias holds.
+          LocalizableMessage msg = ERR_CERTMGR_ALIAS_ALREADY_EXISTS.get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        // The key is re-encrypted with the password of this key store: the key managers of
+        // the server are initialised with the store password only, so a key which kept the
+        // password of the key store it comes from could not be read back.
+        ks.setKeyEntry(alias, privateKey, pwd, chain);
+        try (FileOutputStream fileOutStream = new FileOutputStream(ksPath)) {
+          ks.store(fileOutStream, pwd);
+        }
+      }
+      catch (Exception e)
+      {
+        throw new KeyStoreException(ERR_CERTMGR_IMPORT_KEY_ENTRY.get(alias, e.getMessage()).toString(), e);
+      }
+    }
+
+    private final void addTrustedCertificate(KeyStore ks, String ksType, String ksPath, String alias, char[] pwd,
+                                             Certificate certificate) throws KeyStoreException
+    {
+      try
+      {
+        if (ks == null)
+        {
+          ks = KeyStore.getInstance(ksType);
+          ks.load(null, pwd);
+        }
+        else if (ks.containsAlias(alias))
+        {
+          LocalizableMessage msg = ERR_CERTMGR_ALIAS_ALREADY_EXISTS.get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        ks.setCertificateEntry(alias, certificate);
+        try (FileOutputStream fileOutStream = new FileOutputStream(ksPath)) {
+          ks.store(fileOutStream, pwd);
+        }
+      }
+      catch (Exception e)
+      {
+        throw new KeyStoreException(ERR_CERTMGR_TRUSTED_CERT.get(alias, e.getMessage()).toString(), e);
+      }
+    }
+
     private static final KeyStore generateSelfSignedCertificate(KeyStore ks,
                                                                 String ksType, String ksPath, KeyType keyType, String alias, char[] pwd, String dn,
                                                                 int validity) throws KeyStoreException
@@ -333,6 +391,63 @@
   }
 
   /**
+   * Copy a key entry, that is a private key and its certificate chain, into the provided
+   * keystore; creating the keystore with the provided type and path if it doesn't exist.
+   * The private key is re-encrypted with the password of the destination keystore.
+   *
+   * @param ks
+   *          The keystore to add the key entry to, may be null if it doesn't exist.
+   * @param ksType
+   *          The type to use if the keystore is created.
+   * @param ksPath
+   *          The path to the keystore.
+   * @param alias
+   *          The alias to store the key entry under.
+   * @param pwd
+   *          The keystore password, used for the private key as well.
+   * @param privateKey
+   *          The private key to store.
+   * @param chain
+   *          The certificate chain of the private key, the certificate it belongs to first.
+   * @throws KeyStoreException
+   *           If the alias is already in use, or an error occurred adding the key entry to
+   *           the keystore.
+   */
+  public static void importKeyEntry(KeyStore ks, String ksType, String ksPath, String alias, char[] pwd,
+                                    Key privateKey, Certificate[] chain) throws KeyStoreException
+  {
+    IMPL.importKeyEntry(ks, ksType, ksPath, alias, pwd, privateKey, chain);
+  }
+
+  /**
+   * Add the provided certificate to the provided keystore as a trusted certificate entry;
+   * creating the keystore with the provided type and path if it doesn't exist. Only such
+   * an entry is a trust anchor: the certificate chain of a key entry is not, the trust
+   * managers take the certificate the key belongs to and none of its issuers.
+   *
+   * @param ks
+   *          The keystore to add the certificate to, may be null if it doesn't exist.
+   * @param ksType
+   *          The type to use if the keystore is created.
+   * @param ksPath
+   *          The path to the keystore.
+   * @param alias
+   *          The alias to store the certificate under.
+   * @param pwd
+   *          The keystore password.
+   * @param certificate
+   *          The certificate to trust.
+   * @throws KeyStoreException
+   *           If the alias is already in use, or an error occurred adding the certificate
+   *           to the keystore.
+   */
+  public static void addTrustedCertificate(KeyStore ks, String ksType, String ksPath, String alias, char[] pwd,
+                                           Certificate certificate) throws KeyStoreException
+  {
+    IMPL.addTrustedCertificate(ks, ksType, ksPath, alias, pwd, certificate);
+  }
+
+  /**
    * Delete the specified alias from the provided keystore.
    *
    * @param ks

--
Gitblit v1.10.0