From 4daff1f3fd3f8e9e4f0135eee76fa1ca2ce02e4e Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Wed, 28 Feb 2007 21:01:32 +0000
Subject: [PATCH] Add a new key manager which provides the ability to specify which certificate should be presented based on its alias (aka its nickname). This is used both by server-side code which needs to present a certificate to clients, as well as by client-side code which needs to present a certificate to the server.
---
opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java | 18 +
opendj-sdk/opends/src/server/org/opends/server/tools/LDAPSearch.java | 20 +
opendj-sdk/opends/src/server/org/opends/server/util/SelectableCertificateKeyManager.java | 315 +++++++++++++++++++++
opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java | 4
opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiConnector.java | 22 +
opendj-sdk/opends/src/server/org/opends/server/tools/StopDS.java | 20 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPAuthenticationHandlerTestCase.java | 17
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPSearchTestCase.java | 110 +++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPCompareTestCase.java | 112 +++++++
opendj-sdk/opends/src/server/org/opends/server/extensions/TLSConnectionSecurityProvider.java | 16
opendj-sdk/opends/src/server/org/opends/server/tools/LDAPModify.java | 22 +
opendj-sdk/opends/src/server/org/opends/server/tools/SSLConnectionFactory.java | 10
opendj-sdk/opends/resource/config/config.ldif | 2
opendj-sdk/opends/src/server/org/opends/server/tools/LDAPCompare.java | 20 +
opendj-sdk/opends/src/server/org/opends/server/tools/LDAPDelete.java | 22 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPModifyTestCase.java | 110 +++++++
opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java | 18 +
opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java | 13
opendj-sdk/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java | 2
opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java | 17 +
20 files changed, 859 insertions(+), 31 deletions(-)
diff --git a/opendj-sdk/opends/resource/config/config.ldif b/opendj-sdk/opends/resource/config/config.ldif
index c8e3e55..58f472b 100644
--- a/opendj-sdk/opends/resource/config/config.ldif
+++ b/opendj-sdk/opends/resource/config/config.ldif
@@ -374,7 +374,7 @@
ds-cfg-connection-handler-enabled: true
ds-cfg-use-ssl: false
ds-cfg-listen-port: 1689
-ds-cfg-ssl-cert-nickname: adm-server-cert
+ds-cfg-ssl-cert-nickname: server-cert
dn: cn=Entry Cache,cn=config
objectClass: top
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java b/opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java
index 4eaa9b8..a3a4697 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/ClientConnection.java
@@ -1488,6 +1488,24 @@
/**
+ * Retrieves the alias of the server certificate that should be used
+ * for operations requiring a server certificate. The default
+ * implementation returns {@code null} to indicate that any alias is
+ * acceptable.
+ *
+ * @return The alias of the server certificate that should be used
+ * for operations requring a server certificate, or
+ * {@code null} if any alias is acceptable.
+ */
+ public String getCertificateAlias()
+ {
+ // In the default implementation, we'll return null.
+ return null;
+ }
+
+
+
+ /**
* Retrieves a string representation of this client connection.
*
* @return A string representation of this client connection.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/TLSConnectionSecurityProvider.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/TLSConnectionSecurityProvider.java
index 292dab1..4dc1a09 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/TLSConnectionSecurityProvider.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/TLSConnectionSecurityProvider.java
@@ -50,6 +50,7 @@
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.InitializationException;
import org.opends.server.types.SSLClientAuthPolicy;
+import org.opends.server.util.SelectableCertificateKeyManager;
import static org.opends.server.loggers.Debug.*;
import static org.opends.server.messages.ExtensionsMessages.*;
@@ -195,8 +196,19 @@
{
// FIXME -- Is it bad to create a new SSLContext for each connection?
sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME);
- sslContext.init(keyManagerProvider.getKeyManagers(),
- trustManagerProvider.getTrustManagers(), null);
+
+ String alias = clientConnection.getCertificateAlias();
+ if (alias == null)
+ {
+ sslContext.init(keyManagerProvider.getKeyManagers(),
+ trustManagerProvider.getTrustManagers(), null);
+ }
+ else
+ {
+ sslContext.init(SelectableCertificateKeyManager.wrap(
+ keyManagerProvider.getKeyManagers(), alias),
+ trustManagerProvider.getTrustManagers(), null);
+ }
}
catch (Exception e)
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
index ae6eefb..978c092 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -7655,6 +7655,17 @@
public static final int MSGID_STOPDS_CHECK_STOPPABILITY =
CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 804;
+
+
+ /**
+ * The message ID for the message that will be used as the description of the
+ * certNickname argument. This does not take any arguments.
+ */
+ public static final int MSGID_DESCRIPTION_CERT_NICKNAME =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 805;
+
+
+
/**
* Associates a set of generic messages with the message IDs defined in this
* class.
@@ -8117,6 +8128,8 @@
"Certificate keystore PIN");
registerMessage(MSGID_DESCRIPTION_KEYSTOREPASSWORD_FILE,
"Certificate keystore PIN file");
+ registerMessage(MSGID_DESCRIPTION_CERT_NICKNAME,
+ "Nickname of certificate for SSL client authentication");
registerMessage(MSGID_DESCRIPTION_TRUSTSTOREPASSWORD,
"Certificate trust store PIN");
registerMessage(MSGID_DESCRIPTION_TRUSTSTOREPASSWORD_FILE,
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
index b2bb2ab..4240962 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
@@ -1062,9 +1062,9 @@
if (certNameAttr == null)
{
//
- // This is fine -- we'll just use the default.
+ // This is fine -- we'll just let the server pick one.
certNameAttr = new StringConfigAttribute(ATTR_SSL_CERT_NICKNAME,
- getMessage(msgID), false, false, false, DEFAULT_SSL_CERT_NICKNAME);
+ getMessage(msgID), false, false, false, (String) null);
}
return certNameAttr;
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiConnector.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiConnector.java
index cc4c9b4..2742394 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiConnector.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/RmiConnector.java
@@ -32,6 +32,7 @@
import java.rmi.registry.Registry;
import java.util.HashMap;
+import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.SSLContext;
@@ -48,6 +49,8 @@
import org.opends.server.types.DebugLogCategory;
import org.opends.server.types.DebugLogSeverity;
+import org.opends.server.util.SelectableCertificateKeyManager;
+
import static org.opends.server.loggers.Debug.*;
/**
@@ -320,15 +323,30 @@
// ---------------------
//
// Get a Server socket factory
+ KeyManager[] keyManagers;
KeyManagerProvider provider = jmxConnectionHandler.keyManagerProvider;
if (provider == null)
{
- provider = new NullKeyManagerProvider();
+ keyManagers = new NullKeyManagerProvider().getKeyManagers();
+ }
+ else
+ {
+ String nickname = jmxConnectionHandler.sslServerCertNickname;
+ if (nickname == null)
+ {
+ keyManagers = provider.getKeyManagers();
+ }
+ else
+ {
+ keyManagers =
+ SelectableCertificateKeyManager.wrap(provider.getKeyManagers(),
+ nickname);
+ }
}
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(
- provider.getKeyManagers(),
+ keyManagers,
null,
null);
SSLSocketFactory ssf = ctx.getSocketFactory();
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
index 06bad10..4cd3342 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -2653,5 +2653,22 @@
return connectionHandler.getTrustManagerProviderDN();
}
+
+
+
+ /**
+ * Retrieves the alias of the server certificate that should be used
+ * for operations requiring a server certificate. The default
+ * implementation returns {@code null} to indicate that any alias is
+ * acceptable.
+ *
+ * @return The alias of the server certificate that should be used
+ * for operations requring a server certificate, or
+ * {@code null} if any alias is acceptable.
+ */
+ public String getCertificateAlias()
+ {
+ return connectionHandler.getSSLServerCertNickname();
+ }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
index 4253411..dd0c2ef 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -901,8 +901,8 @@
configEntry.getConfigAttribute(certNameStub);
if (certNameAttr == null)
{
- // This is fine -- we'll just use the default.
- sslServerCertNickname = DEFAULT_SSL_CERT_NICKNAME;
+ // This is fine -- We'll just let the server pick one.
+ sslServerCertNickname = null;
}
else
{
@@ -1792,6 +1792,20 @@
/**
+ * Retrieves the nickname of the server certificate that should be used in
+ * conjunction with this LDAP connection handler.
+ *
+ * @return The nickname of the server certificate that should be used in
+ * conjunction with this LDAP connection handler.
+ */
+ public String getSSLServerCertNickname()
+ {
+ return sslServerCertNickname;
+ }
+
+
+
+ /**
* Retrieves the maximum ASN.1 element value length that will be allowed by
* this connection handler.
*
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPCompare.java b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPCompare.java
index 6a099c6..ba5d156 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPCompare.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPCompare.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.tools;
@@ -343,6 +343,7 @@
StringArgument assertionFilter = null;
StringArgument bindDN = null;
StringArgument bindPassword = null;
+ StringArgument certNickname = null;
StringArgument controlStr = null;
StringArgument encodingStr = null;
StringArgument filename = null;
@@ -438,6 +439,11 @@
MSGID_DESCRIPTION_KEYSTOREPASSWORD_FILE);
argParser.addArgument(keyStorePasswordFile);
+ certNickname = new StringArgument("certnickname", 'N', "certNickname",
+ false, false, true, "{nickname}", null,
+ null, MSGID_DESCRIPTION_CERT_NICKNAME);
+ argParser.addArgument(certNickname);
+
trustStorePath = new StringArgument("trustStorePath", 'P',
"trustStorePath", false, false, true,
"{trustStorePath}", null, null,
@@ -796,9 +802,19 @@
SSLConnectionFactory sslConnectionFactory = null;
if(connectionOptions.useSSL() || connectionOptions.useStartTLS())
{
+ String clientAlias;
+ if (certNickname.isPresent())
+ {
+ clientAlias = certNickname.getValue();
+ }
+ else
+ {
+ clientAlias = null;
+ }
+
sslConnectionFactory = new SSLConnectionFactory();
sslConnectionFactory.init(trustAll.isPresent(), keyStorePathValue,
- keyStorePasswordValue,
+ keyStorePasswordValue, clientAlias,
trustStorePathValue, trustStorePasswordValue);
connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPDelete.java b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPDelete.java
index 1e9db57..9b6a5c5 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPDelete.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPDelete.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.tools;
@@ -323,6 +323,7 @@
IntegerArgument version = null;
StringArgument bindDN = null;
StringArgument bindPassword = null;
+ StringArgument certNickname = null;
StringArgument controlStr = null;
StringArgument encodingStr = null;
StringArgument filename = null;
@@ -415,6 +416,11 @@
MSGID_DESCRIPTION_KEYSTOREPASSWORD_FILE);
argParser.addArgument(keyStorePasswordFile);
+ certNickname = new StringArgument("certnickname", 'N', "certNickname",
+ false, false, true, "{nickname}", null,
+ null, MSGID_DESCRIPTION_CERT_NICKNAME);
+ argParser.addArgument(certNickname);
+
trustStorePath = new StringArgument("trustStorePath", 'P',
"trustStorePath", false, false, true,
"{trustStorePath}", null, null,
@@ -679,10 +685,20 @@
SSLConnectionFactory sslConnectionFactory = null;
if(connectionOptions.useSSL() || connectionOptions.useStartTLS())
{
+ String clientAlias;
+ if (certNickname.isPresent())
+ {
+ clientAlias = certNickname.getValue();
+ }
+ else
+ {
+ clientAlias = null;
+ }
+
sslConnectionFactory = new SSLConnectionFactory();
sslConnectionFactory.init(trustAll.isPresent(), keyStorePathValue,
- keyStorePasswordValue, trustStorePathValue,
- trustStorePasswordValue);
+ keyStorePasswordValue, clientAlias,
+ trustStorePathValue, trustStorePasswordValue);
connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPModify.java b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPModify.java
index 65cc23a..38e0831 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPModify.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPModify.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.tools;
@@ -581,6 +581,7 @@
StringArgument assertionFilter = null;
StringArgument bindDN = null;
StringArgument bindPassword = null;
+ StringArgument certNickname = null;
StringArgument controlStr = null;
StringArgument encodingStr = null;
StringArgument filename = null;
@@ -677,6 +678,11 @@
MSGID_DESCRIPTION_KEYSTOREPASSWORD_FILE);
argParser.addArgument(keyStorePasswordFile);
+ certNickname = new StringArgument("certnickname", 'N', "certNickname",
+ false, false, true, "{nickname}", null,
+ null, MSGID_DESCRIPTION_CERT_NICKNAME);
+ argParser.addArgument(certNickname);
+
trustStorePath = new StringArgument("trustStorePath", 'P',
"trustStorePath", false, false, true,
"{trustStorePath}", null, null,
@@ -1022,10 +1028,20 @@
SSLConnectionFactory sslConnectionFactory = null;
if(connectionOptions.useSSL() || connectionOptions.useStartTLS())
{
+ String clientAlias;
+ if (certNickname.isPresent())
+ {
+ clientAlias = certNickname.getValue();
+ }
+ else
+ {
+ clientAlias = null;
+ }
+
sslConnectionFactory = new SSLConnectionFactory();
sslConnectionFactory.init(trustAll.isPresent(), keyStorePathValue,
- keyStorePasswordValue, trustStorePathValue,
- trustStorePasswordValue);
+ keyStorePasswordValue, clientAlias,
+ trustStorePathValue, trustStorePasswordValue);
connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java
index 9792843..126e79a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPPasswordModify.java
@@ -550,7 +550,7 @@
{
SSLConnectionFactory sslConnectionFactory = new SSLConnectionFactory();
sslConnectionFactory.init(sslBlindTrust.isPresent(),
- sslKeyStore.getValue(), keyPIN,
+ sslKeyStore.getValue(), keyPIN, null,
sslTrustStore.getValue(), trustPIN);
connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPSearch.java b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPSearch.java
index 0a47f41..d12ba23 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPSearch.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/LDAPSearch.java
@@ -584,6 +584,7 @@
StringArgument baseDN = null;
StringArgument bindDN = null;
StringArgument bindPassword = null;
+ StringArgument certNickname = null;
StringArgument controlStr = null;
StringArgument dereferencePolicy = null;
StringArgument encodingStr = null;
@@ -690,6 +691,11 @@
MSGID_DESCRIPTION_KEYSTOREPASSWORD_FILE);
argParser.addArgument(keyStorePasswordFile);
+ certNickname = new StringArgument("certnickname", 'N', "certNickname",
+ false, false, true, "{nickname}", null,
+ null, MSGID_DESCRIPTION_CERT_NICKNAME);
+ argParser.addArgument(certNickname);
+
trustStorePath = new StringArgument("trustStorePath", 'P',
"trustStorePath", false, false, true,
"{trustStorePath}", null, null,
@@ -1315,10 +1321,20 @@
SSLConnectionFactory sslConnectionFactory = null;
if(connectionOptions.useSSL() || connectionOptions.useStartTLS())
{
+ String clientAlias;
+ if (certNickname.isPresent())
+ {
+ clientAlias = certNickname.getValue();
+ }
+ else
+ {
+ clientAlias = null;
+ }
+
sslConnectionFactory = new SSLConnectionFactory();
sslConnectionFactory.init(trustAll.isPresent(), keyStorePathValue,
- keyStorePasswordValue, trustStorePathValue,
- trustStorePasswordValue);
+ keyStorePasswordValue, clientAlias,
+ trustStorePathValue, trustStorePasswordValue);
connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/SSLConnectionFactory.java b/opendj-sdk/opends/src/server/org/opends/server/tools/SSLConnectionFactory.java
index 630ed29..ebdf6eb 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/SSLConnectionFactory.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/SSLConnectionFactory.java
@@ -41,6 +41,7 @@
import javax.net.ssl.TrustManagerFactory;
import org.opends.server.extensions.BlindTrustManagerProvider;
+import org.opends.server.util.SelectableCertificateKeyManager;
import static org.opends.server.messages.ToolMessages.*;
import static org.opends.server.messages.MessageHandler.*;
@@ -74,6 +75,7 @@
* @param keyStorePath The path to the key store file.
* @param keyStorePassword The PIN to use to access the key store
* contents.
+ * @param clientAlias The alias to use for the client certificate.
* @param trustStorePath The path to the trust store file.
* @param trustStorePassword The PIN to use to access the trust store
* contents.
@@ -82,7 +84,7 @@
* connection factory.
*/
public void init(boolean trustAll, String keyStorePath,
- String keyStorePassword,
+ String keyStorePassword, String clientAlias,
String trustStorePath, String trustStorePassword)
throws SSLConnectionException
{
@@ -108,6 +110,12 @@
{
keyManagers = getKeyManagers(KeyStore.getDefaultType(), null,
keyStorePath, keyStorePassword);
+
+ if (clientAlias != null)
+ {
+ keyManagers = SelectableCertificateKeyManager.wrap(keyManagers,
+ clientAlias);
+ }
}
ctx.init(keyManagers, trustManagers, new java.security.SecureRandom());
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/StopDS.java b/opendj-sdk/opends/src/server/org/opends/server/tools/StopDS.java
index 6c1bc93..7a7fe2e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/StopDS.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/StopDS.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.tools;
@@ -176,6 +176,7 @@
IntegerArgument port;
StringArgument bindDN;
StringArgument bindPW;
+ StringArgument certNickname;
StringArgument host;
StringArgument keyStoreFile;
StringArgument keyStorePW;
@@ -276,6 +277,11 @@
MSGID_STOPDS_DESCRIPTION_KSPWFILE);
argParser.addArgument(keyStorePWFile);
+ certNickname = new StringArgument("certnickname", 'N', "certNickname",
+ false, false, true, "{nickname}", null,
+ null, MSGID_DESCRIPTION_CERT_NICKNAME);
+ argParser.addArgument(certNickname);
+
trustStoreFile = new StringArgument("truststorefile", 'P',
"trustStoreFile", false, false, true,
"{trustStoreFile}", null, null,
@@ -490,9 +496,19 @@
{
try
{
+ String clientAlias;
+ if (certNickname.isPresent())
+ {
+ clientAlias = certNickname.getValue();
+ }
+ else
+ {
+ clientAlias = null;
+ }
+
SSLConnectionFactory sslConnectionFactory = new SSLConnectionFactory();
sslConnectionFactory.init(trustAll.isPresent(), keyStoreFile.getValue(),
- keyStorePW.getValue(),
+ keyStorePW.getValue(), clientAlias,
trustStoreFile.getValue(),
trustStorePW.getValue());
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/SelectableCertificateKeyManager.java b/opendj-sdk/opends/src/server/org/opends/server/util/SelectableCertificateKeyManager.java
new file mode 100644
index 0000000..edfacad
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/SelectableCertificateKeyManager.java
@@ -0,0 +1,315 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying * information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.util;
+
+
+
+import java.net.Socket;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.net.ssl.X509KeyManager;
+
+
+
+/**
+ * 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 certificate(s)
+ * should be used for client and/or server operations. The certificate
+ * selection will be based on the alias (also called the nickname) of the
+ * certificate.
+ */
+public class SelectableCertificateKeyManager
+ extends X509ExtendedKeyManager
+{
+ // The alias of the certificate that should be selected from the key manager.
+ private String alias;
+
+ // The key manager that is wrapped by this key manager.
+ private X509KeyManager keyManager;
+
+
+
+ /**
+ * 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.
+ */
+ public SelectableCertificateKeyManager(X509KeyManager keyManager,
+ String alias)
+ {
+ super();
+
+ this.keyManager = keyManager;
+ this.alias = alias;
+ }
+
+
+
+ /**
+ * Chooses the alias of the client certificate that should be used based on
+ * the provided critieria. This will either return the preferred alias
+ * configured for this key manager, or {@code null} if no client certificate
+ * with that alias is configured in the underlying key manager.
+ *
+ * @param keyType The set of key algorithm names, ordered with the most
+ * preferred key type first.
+ * @param issuers The list of acceptable issuer subject names, or
+ * {@code null} if any issuer may be used.
+ * @param socket The socket to be used for this connection.
+ *
+ * @return The alias configured for this key manager, or {@code null} if no
+ * such client certificate is available with that alias.
+ */
+ public String chooseClientAlias(String[] keyType, Principal[] issuers,
+ Socket socket)
+ {
+ for (String type : keyType)
+ {
+ String[] clientAliases = keyManager.getClientAliases(type, issuers);
+ if (clientAliases != null)
+ {
+ for (String clientAlias : clientAliases)
+ {
+ if (clientAlias.equals(alias))
+ {
+ return alias;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+
+ /**
+ * Chooses the alias of the client certificate that should be used based on
+ * the provided critieria. This will either return the preferred alias
+ * configured for this key manager, or {@code null} if no client certificate
+ * with that alias is configured in the underlying key manager.
+ *
+ * @param keyType The set of key algorithm names, ordered with the most
+ * preferred key type first.
+ * @param issuers The list of acceptable issuer subject names, or
+ * {@code null} if any issuer may be used.
+ * @param engine The SSL engine to be used for this connection.
+ *
+ * @return The alias configured for this key manager, or {@code null} if no
+ * such client certificate is available with that alias.
+ */
+ public String chooseEngineClientAlias(String[] keyType, Principal[] issuers,
+ SSLEngine engine)
+ {
+ for (String type : keyType)
+ {
+ String[] clientAliases = keyManager.getClientAliases(type, issuers);
+ if (clientAliases != null)
+ {
+ for (String clientAlias : clientAliases)
+ {
+ if (clientAlias.equals(alias))
+ {
+ return alias;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+
+ /**
+ * Chooses the alias of the server certificate that should be used based on
+ * the provided critieria. This will either return the preferred alias
+ * configured for this key manager, or {@code null} if no server certificate
+ * with that alias is configured in the underlying key manager.
+ *
+ * @param keyType The public key type for the certificate.
+ * @param issuers The list of acceptable issuer subject names, or
+ * {@code null} if any issuer may be used.
+ * @param socket The socket to be used for this connection.
+ *
+ * @return The alias configured for this key manager, or {@code null} if no
+ * such server certificate is available with that alias.
+ */
+ public String chooseServerAlias(String keyType, Principal[] issuers,
+ Socket socket)
+ {
+ String[] serverAliases = keyManager.getServerAliases(keyType, issuers);
+ if (serverAliases != null)
+ {
+ for (String serverAlias : serverAliases)
+ {
+ if (serverAlias.equals(alias))
+ {
+ return alias;
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+
+ /**
+ * Chooses the alias of the server certificate that should be used based on
+ * the provided critieria. This will either return the preferred alias
+ * configured for this key manager, or {@code null} if no server certificate
+ * with that alias is configured in the underlying key manager.
+ *
+ * @param keyType The public key type for the certificate.
+ * @param issuers The list of acceptable issuer subject names, or
+ * {@code null} if any issuer may be used.
+ * @param engine The SSL engine to be used for this connection.
+ *
+ * @return The alias configured for this key manager, or {@code null} if no
+ * such server certificate is available with that alias.
+ */
+ public String chooseEngineServerAlias(String keyType, Principal[] issuers,
+ SSLEngine engine)
+ {
+ String[] serverAliases = keyManager.getServerAliases(keyType, issuers);
+ if (serverAliases != null)
+ {
+ for (String serverAlias : serverAliases)
+ {
+ if (serverAlias.equals(alias))
+ {
+ return alias;
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+
+ /**
+ * Retrieves the certificate chain for the provided alias.
+ *
+ * @param alias The alias for the certificate chain to retrieve.
+ *
+ * @return The certificate chain for the provided alias, or {@code null} if
+ * no certificate is associated with the provided alias.
+ */
+ public X509Certificate[] getCertificateChain(String alias)
+ {
+ return keyManager.getCertificateChain(alias);
+ }
+
+
+
+ /**
+ * Retrieves the set of certificate aliases that may be used for client
+ * authentication with the given public key type and set of issuers.
+ *
+ * @param keyType The public key type for the aliases to retrieve.
+ * @param issuers The list of acceptable issuer subject names, or
+ * {@code null} if any issuer may be used.
+ *
+ * @return The set of certificate aliases that may be used for client
+ * authentication with the given public key type and set of issuers,
+ * or {@code null} if there were none.
+ */
+ public String[] getClientAliases(String keyType, Principal[] issuers)
+ {
+ return keyManager.getClientAliases(keyType, issuers);
+ }
+
+
+
+ /**
+ * Retrieves the private key for the provided alias.
+ *
+ * @param alias The alias for the private key to return.
+ *
+ * @return The private key for the provided alias, or {@code null} if no
+ * private key is available for the provided alias.
+ */
+ public PrivateKey getPrivateKey(String alias)
+ {
+ return keyManager.getPrivateKey(alias);
+ }
+
+
+
+ /**
+ * Retrieves the set of certificate aliases that may be used for server
+ * authentication with the given public key type and set of issuers.
+ *
+ * @param keyType The public key type for the aliases to retrieve.
+ * @param issuers The list of acceptable issuer subject names, or
+ * {@code null} if any issuer may be used.
+ *
+ * @return The set of certificate aliases that may be used for server
+ * authentication with the given public key type and set of issuers,
+ * or {@code null} if there were none.
+ */
+ public String[] getServerAliases(String keyType, Principal[] issuers)
+ {
+ return keyManager.getServerAliases(keyType, issuers);
+ }
+
+
+
+ /**
+ * 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.
+ *
+ * @return A key manager array
+ */
+ public static X509ExtendedKeyManager[] wrap(KeyManager[] keyManagers,
+ String alias)
+ {
+ X509ExtendedKeyManager[] newKeyManagers =
+ new X509ExtendedKeyManager[keyManagers.length];
+ for (int i=0; i < keyManagers.length; i++)
+ {
+ newKeyManagers[i] = new SelectableCertificateKeyManager(
+ (X509KeyManager) keyManagers[i], alias);
+ }
+
+ return newKeyManagers;
+ }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPAuthenticationHandlerTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPAuthenticationHandlerTestCase.java
index 377c0ab..a54b5f4 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPAuthenticationHandlerTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPAuthenticationHandlerTestCase.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.tools;
@@ -2471,7 +2471,8 @@
SSLConnectionFactory factory = new SSLConnectionFactory();
- factory.init(false, keyStorePath, "password", trustStorePath, "password");
+ factory.init(false, keyStorePath, "password", "client-cert",
+ trustStorePath, "password");
Socket s = factory.createSocket("127.0.0.1",
@@ -2541,7 +2542,8 @@
SSLConnectionFactory factory = new SSLConnectionFactory();
- factory.init(false, keyStorePath, "password", trustStorePath, "password");
+ factory.init(false, keyStorePath, "password", "client-cert", trustStorePath,
+ "password");
Socket s = factory.createSocket("127.0.0.1",
@@ -2609,7 +2611,8 @@
SSLConnectionFactory factory = new SSLConnectionFactory();
- factory.init(false, keyStorePath, "password", trustStorePath, "password");
+ factory.init(false, keyStorePath, "password", "client-cert", trustStorePath,
+ "password");
Socket s = factory.createSocket("127.0.0.1",
@@ -2683,7 +2686,8 @@
SSLConnectionFactory factory = new SSLConnectionFactory();
- factory.init(false, keyStorePath, "password", trustStorePath, "password");
+ factory.init(false, keyStorePath, "password", "client-cert", trustStorePath,
+ "password");
Socket s = factory.createSocket("127.0.0.1",
@@ -4205,7 +4209,8 @@
SSLConnectionFactory factory = new SSLConnectionFactory();
- factory.init(false, keyStorePath, "password", trustStorePath, "password");
+ factory.init(false, keyStorePath, "password", "client-cert", trustStorePath,
+ "password");
Socket s = factory.createSocket("127.0.0.1",
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPCompareTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPCompareTestCase.java
index b47f2c7..2da6066 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPCompareTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPCompareTestCase.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.tools;
@@ -636,6 +636,116 @@
/**
+ * Tests a simple LDAP compare over SSL using a trust store and SASL EXTERNAL
+ * authentication when explicitly specifying a valid client certificate.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSimpleCompareSSLTrustStoreSASLExternalValidClientCert()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ Entry e = TestCaseUtils.makeEntry(
+ "dn: cn=Test User,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: Test User",
+ "givenName: Test",
+ "ds-privilege-name: bypass-acl",
+ "sn: User");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ AddOperation addOperation =
+ conn.processAdd(e.getDN(), e.getObjectClasses(), e.getUserAttributes(),
+ e.getOperationalAttributes());
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+
+
+ String keyStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.keystore";
+ String trustStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.truststore";
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()),
+ "-Z",
+ "-K", keyStorePath,
+ "-W", "password",
+ "-N", "client-cert",
+ "-P", trustStorePath,
+ "-r",
+ "cn:Test User",
+ "cn=Test User,o=test"
+ };
+
+ assertEquals(LDAPCompare.mainCompare(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests a simple LDAP compare over SSL using a trust store and SASL EXTERNAL
+ * authentication when explicitly specifying an invalid client certificate.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSimpleCompareSSLTrustStoreSASLExternalInvalidClientCert()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ Entry e = TestCaseUtils.makeEntry(
+ "dn: cn=Test User,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: Test User",
+ "givenName: Test",
+ "ds-privilege-name: bypass-acl",
+ "sn: User");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ AddOperation addOperation =
+ conn.processAdd(e.getDN(), e.getObjectClasses(), e.getUserAttributes(),
+ e.getOperationalAttributes());
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+
+
+ String keyStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.keystore";
+ String trustStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.truststore";
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()),
+ "-Z",
+ "-K", keyStorePath,
+ "-W", "password",
+ "-N", "invalid",
+ "-P", trustStorePath,
+ "-r",
+ "cn:Test User",
+ "cn=Test User,o=test"
+ };
+
+ assertFalse(LDAPCompare.mainCompare(args, false, null, null) == 0);
+ }
+
+
+
+ /**
* Tests a simple LDAP compare using StartTLS with a trust store and SASL
* EXTERNAL authentication.
*
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPModifyTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPModifyTestCase.java
index 212f5fa..b0b096b 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPModifyTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPModifyTestCase.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2007 Sun Microsystems, Inc.
*/
package org.opends.server.tools;
@@ -562,6 +562,114 @@
/**
+ * Tests a simple modify operation over SSL using a trust store and SASL
+ * EXTERNAL while explicitly specifying a valid client certificate.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSSLTrustStoreSASLExternalValidClientCert()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ Entry e = TestCaseUtils.makeEntry(
+ "dn: cn=Test User,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: Test User",
+ "givenName: Test",
+ "ds-privilege-name: bypass-acl",
+ "sn: User");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ AddOperation addOperation =
+ conn.processAdd(e.getDN(), e.getObjectClasses(), e.getUserAttributes(),
+ e.getOperationalAttributes());
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+
+
+ String keyStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.keystore";
+ String trustStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.truststore";
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()),
+ "-Z",
+ "-K", keyStorePath,
+ "-W", "password",
+ "-N", "client-cert",
+ "-P", trustStorePath,
+ "-r",
+ "-f", modifyFilePath
+ };
+
+ assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests a simple modify operation over SSL using a trust store and SASL
+ * EXTERNAL while explicitly specifying an invalid client certificate.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSSLTrustStoreSASLExternalInvalidClientCert()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ Entry e = TestCaseUtils.makeEntry(
+ "dn: cn=Test User,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: Test User",
+ "givenName: Test",
+ "ds-privilege-name: bypass-acl",
+ "sn: User");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ AddOperation addOperation =
+ conn.processAdd(e.getDN(), e.getObjectClasses(), e.getUserAttributes(),
+ e.getOperationalAttributes());
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+
+
+ String keyStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.keystore";
+ String trustStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.truststore";
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()),
+ "-Z",
+ "-K", keyStorePath,
+ "-W", "password",
+ "-N", "invalid",
+ "-P", trustStorePath,
+ "-r",
+ "-f", modifyFilePath
+ };
+
+ assertFalse(LDAPModify.mainModify(args, false, null, null) == 0);
+ }
+
+
+
+ /**
* Tests a simple modify operation with StartTLS using a trust store and SASL
* EXTERNAL.
*
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPSearchTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPSearchTestCase.java
index b2a00e8..9900bb8 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPSearchTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tools/LDAPSearchTestCase.java
@@ -714,6 +714,116 @@
/**
+ * Tests a simple LDAP search over SSL using a trust store and SASL EXTERNAL
+ * authentication when explicitly specifying a valid client certificate.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSimpleSearchSSLTrustStoreSASLExternalValidClientCert()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ Entry e = TestCaseUtils.makeEntry(
+ "dn: cn=Test User,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: Test User",
+ "givenName: Test",
+ "sn: User");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ AddOperation addOperation =
+ conn.processAdd(e.getDN(), e.getObjectClasses(), e.getUserAttributes(),
+ e.getOperationalAttributes());
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+
+
+ String keyStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.keystore";
+ String trustStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.truststore";
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()),
+ "-Z",
+ "-K", keyStorePath,
+ "-W", "password",
+ "-N", "client-cert",
+ "-P", trustStorePath,
+ "-r",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertEquals(LDAPSearch.mainSearch(args, false, null, System.err), 0);
+ }
+
+
+
+ /**
+ * Tests a simple LDAP search over SSL using a trust store and SASL EXTERNAL
+ * authentication when explicitly specifying an invalid client certificate.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSimpleSearchSSLTrustStoreSASLExternalInvalidClientCert()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ Entry e = TestCaseUtils.makeEntry(
+ "dn: cn=Test User,o=test",
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "cn: Test User",
+ "givenName: Test",
+ "sn: User");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ AddOperation addOperation =
+ conn.processAdd(e.getDN(), e.getObjectClasses(), e.getUserAttributes(),
+ e.getOperationalAttributes());
+ assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
+
+
+ String keyStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.keystore";
+ String trustStorePath = DirectoryServer.getServerRoot() + File.separator +
+ "config" + File.separator + "client.truststore";
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapsPort()),
+ "-Z",
+ "-K", keyStorePath,
+ "-W", "password",
+ "-N", "invalid",
+ "-P", trustStorePath,
+ "-r",
+ "-b", "",
+ "-s", "base",
+ "(objectClass=*)"
+ };
+
+ assertFalse(LDAPSearch.mainSearch(args, false, null, null) == 0);
+ }
+
+
+
+ /**
* Tests a simple LDAP search using StartTLS with a trust store and SASL
* EXTERNAL authentication.
*
--
Gitblit v1.10.0