From f93487455cc1b5d7062ea6577d99dea25bfd81b3 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 14 Oct 2026 07:27:37 +0000
Subject: [PATCH] [#1188] Serialize and replace atomically the writes of the ads-truststore, and report a certificate it cannot take or drop (#1189)

---
 opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java |   22 ++++++++++++++++++----
 1 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java b/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java
index 9cff8a7..fe8d421 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java
@@ -13,6 +13,7 @@
  *
  * Copyright 2008-2010 Sun Microsystems, Inc.
  * Portions Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.crypto;
 
@@ -359,9 +360,15 @@
   private static void deleteEntry(DN dstDN)
   {
     DeleteOperation delOperation = getRootConnection().processDelete(dstDN);
-    if (delOperation.getResultCode() != ResultCode.SUCCESS)
+    if (delOperation.getResultCode() == ResultCode.NO_SUCH_OBJECT)
     {
-      logger.debug(INFO_TRUSTSTORESYNC_DELETE_FAILED, dstDN, delOperation.getErrorMessage());
+      // The certificate has left the trust store already, as it does when its key is marked compromised.
+      logger.debug(ERR_TRUSTSTORESYNC_DELETE_FAILED, dstDN, delOperation.getErrorMessage());
+    }
+    else if (delOperation.getResultCode() != ResultCode.SUCCESS)
+    {
+      // While the certificate is there, this server goes on trusting whoever holds the key.
+      logger.error(ERR_TRUSTSTORESYNC_DELETE_FAILED, dstDN, delOperation.getErrorMessage());
     }
   }
 
@@ -383,9 +390,16 @@
 
     Entry addEntry = new Entry(dstDN, ocMap, userAttrs, null);
     AddOperation addOperation = getRootConnection().processAdd(addEntry);
-    if (addOperation.getResultCode() != ResultCode.SUCCESS)
+    if (addOperation.getResultCode() == ResultCode.ENTRY_ALREADY_EXISTS)
     {
-      logger.debug(INFO_TRUSTSTORESYNC_ADD_FAILED, dstDN, addOperation.getErrorMessage());
+      // dsreplication seeds the trust store of the servers it enables: the certificate is there already.
+      logger.debug(ERR_TRUSTSTORESYNC_ADD_FAILED, dstDN, addOperation.getErrorMessage());
+    }
+    else if (addOperation.getResultCode() != ResultCode.SUCCESS)
+    {
+      // Without the certificate this server does not trust the server the key belongs to, and
+      // every replication connection between the two fails its handshake (#1188).
+      logger.error(ERR_TRUSTSTORESYNC_ADD_FAILED, dstDN, addOperation.getErrorMessage());
     }
   }
 

--
Gitblit v1.10.0