From 07314bd0f1ad8d225edead4d97495876edb5fdc2 Mon Sep 17 00:00:00 2001
From: Patrick Diligent <patrick.diligent@forgerock.com>
Date: Fri, 17 Apr 2015 01:23:20 +0000
Subject: [PATCH] OPENDJ-1056 CR-6649 Add troubleshooting logging for mis-configured secure connections

---
 opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedKeyManagerProvider.java |   20 ++++++++++
 opendj-server-legacy/src/main/java/org/opends/server/util/SelectableCertificateKeyManager.java   |   53 +++++++++++++++++++++-----
 opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java   |    5 ++
 opendj-server-legacy/src/messages/org/opends/messages/protocol.properties                        |    2 +
 opendj-server-legacy/src/messages/org/opends/messages/extension.properties                       |    2 +
 5 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedKeyManagerProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedKeyManagerProvider.java
index d4edb1b..c0aa5db 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedKeyManagerProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/FileBasedKeyManagerProvider.java
@@ -36,6 +36,8 @@
 import java.io.IOException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
+import java.util.Enumeration;
+import java.util.Iterator;
 import java.util.List;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -258,6 +260,24 @@
                                    message, e);
     }
 
+    try {
+      // Troubleshooting aid; Analyse the keystore for the presence of at least one private entry.
+      boolean foundOneKeyEntry = false;
+      Enumeration<String> aliases = keyStore.aliases();
+      while (aliases.hasMoreElements()) {
+        String alias = aliases.nextElement();
+        if (keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
+          foundOneKeyEntry = true;
+          break;
+        }
+      }
+      if (!foundOneKeyEntry) {
+        logger.warn(INFO_NO_KEY_ENTRY_IN_KEYSTORE, keyStoreFile);
+      }
+    }
+    catch (Exception e) {
+      logger.traceException(e);
+    }
 
     try
     {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
index 33bdeaa..b011204 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -1386,6 +1386,9 @@
           .getKeyManagerProvider(keyMgrDN);
       if (keyManagerProvider == null)
       {
+        if (config.isUseSSL()) {
+          logger.warn(INFO_NULL_KEY_PROVIDER_MANAGER, keyMgrDN, friendlyName);
+        }
         keyManagerProvider = new NullKeyManagerProvider();
       }
 
@@ -1398,7 +1401,7 @@
       else
       {
         keyManagers = SelectableCertificateKeyManager.wrap(
-            keyManagerProvider.getKeyManagers(), alias);
+            keyManagerProvider.getKeyManagers(), alias, friendlyName);
       }
 
       DN trustMgrDN = config.getTrustManagerProviderDN();
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/SelectableCertificateKeyManager.java b/opendj-server-legacy/src/main/java/org/opends/server/util/SelectableCertificateKeyManager.java
index 09eb4fa..a992660 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/util/SelectableCertificateKeyManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/util/SelectableCertificateKeyManager.java
@@ -28,6 +28,8 @@
 
 
 
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+
 import java.net.Socket;
 import java.security.Principal;
 import java.security.PrivateKey;
@@ -37,6 +39,7 @@
 import javax.net.ssl.X509ExtendedKeyManager;
 import javax.net.ssl.X509KeyManager;
 
+import static org.opends.messages.ExtensionMessages.INFO_KEYSTORE_DOES_NOT_CONTAIN_ALIAS;
 
 
 /**
@@ -60,7 +63,30 @@
   /** The key manager that is wrapped by this key manager. */
   private final X509KeyManager keyManager;
 
+  /** Provide additional troubleshooting aid to localize a misconfigured SSL connection. */
+  private final String componentName;
 
+  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+
+
+  /**
+   * Creates a new instance of this key manager that will wrap the provided key
+   * manager and use the certificate with the specified alias.
+   *
+   * @param  keyManager       The key manager to be wrapped by this key manager.
+   * @param  alias            The nickname of the certificate that should be
+   *                          selected for operations involving this key manager.
+   * @param  componentName    Name of the component to which is associated this key manager
+   */
+  public SelectableCertificateKeyManager(X509KeyManager keyManager,
+                                         String alias, String componentName)
+  {
+    super();
+
+    this.keyManager = keyManager;
+    this.alias      = alias;
+    this.componentName       = componentName;
+  }
 
   /**
    * Creates a new instance of this key manager that will wrap the provided key
@@ -73,14 +99,10 @@
   public SelectableCertificateKeyManager(X509KeyManager keyManager,
                                          String alias)
   {
-    super();
-
-    this.keyManager = keyManager;
-    this.alias      = alias;
+    this(keyManager, alias, "[unknown]");
   }
 
 
-
   /**
    * Chooses the alias of the client certificate that should be used based on
    * the provided criteria.  This will either return the preferred alias
@@ -113,7 +135,7 @@
         }
       }
     }
-
+    logger.warn(INFO_KEYSTORE_DOES_NOT_CONTAIN_ALIAS, keyType, alias, componentName);
     return null;
   }
 
@@ -153,6 +175,7 @@
       }
     }
 
+    logger.warn(INFO_KEYSTORE_DOES_NOT_CONTAIN_ALIAS, keyType, alias, componentName);
     return null;
   }
 
@@ -187,6 +210,7 @@
       }
     }
 
+    logger.warn(INFO_KEYSTORE_DOES_NOT_CONTAIN_ALIAS, keyType, alias, componentName);
     return null;
   }
 
@@ -225,6 +249,7 @@
       }
     }
 
+    logger.warn(INFO_KEYSTORE_DOES_NOT_CONTAIN_ALIAS, keyType, alias, componentName);
     return null;
   }
 
@@ -302,24 +327,30 @@
    * Wraps the provided set of key managers in selectable certificate key
    * managers using the provided alias.
    *
-   * @param  keyManagers  The set of key managers to be wrapped.
-   * @param  alias        The alias to use for selecting the desired
-   *                      certificate.
+   * @param  keyManagers      The set of key managers to be wrapped.
+   * @param  alias            The alias to use for selecting the desired
+   *                          certificate.
+   * @param  componentName    Name of the component to which is associated this key manager
    *
    * @return  A key manager array
    */
   public static X509ExtendedKeyManager[] wrap(KeyManager[] keyManagers,
-                                              String alias)
+                                              String alias, String componentName)
   {
     X509ExtendedKeyManager[] newKeyManagers =
          new X509ExtendedKeyManager[keyManagers.length];
     for (int i=0; i < keyManagers.length; i++)
     {
       newKeyManagers[i] = new SelectableCertificateKeyManager(
-                                   (X509KeyManager) keyManagers[i], alias);
+                                   (X509KeyManager) keyManagers[i], alias, componentName);
     }
 
     return newKeyManagers;
   }
+
+  public static X509ExtendedKeyManager[] wrap(KeyManager[] keyManagers,
+                                              String alias) {
+    return wrap(keyManagers, alias, "[unknown]");
+  }
 }
 
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 eae437d..bc04302 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/extension.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/extension.properties
@@ -1023,3 +1023,5 @@
  definition '%s' is invalid because the range '%s' is missing the minus
 ERR_CHARSET_VALIDATOR_SHORT_RANGE_635=The provided character range \
  definition '%s' is invalid because the range '%s' is too short
+INFO_KEYSTORE_DOES_NOT_CONTAIN_ALIAS_636=The %s key with alias '%s' was not found for '%s'
+INFO_NO_KEY_ENTRY_IN_KEYSTORE_637=There is no key entry in keystore %s
\ No newline at end of file
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/protocol.properties b/opendj-server-legacy/src/messages/org/opends/messages/protocol.properties
index 01faa20..8a7daca 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/protocol.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/protocol.properties
@@ -907,3 +907,5 @@
  whitespace character at the current position: %s
 ERR_GSER_NO_VALID_IDENTIFIEDCHOICE_1523=The GSER value does not \
  contain a valid IdentifiedChoiceValue at the current position: %s
+INFO_NULL_KEY_PROVIDER_MANAGER_1524=The keystore %s seems to be missing, \
+  this may render the secure port inoperative for '%s'
\ No newline at end of file

--
Gitblit v1.10.0