From 58d668e476b45ccdac9fce119f398d151d292ebe Mon Sep 17 00:00:00 2001
From: lutoff <lutoff@localhost>
Date: Tue, 11 Sep 2007 12:50:16 +0000
Subject: [PATCH] Fix for issue #2240
---
opendj-sdk/opends/src/messages/messages/utility.properties | 17 +
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java | 109 +++++++--
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/OpendsCertificationException.java | 96 ++++++++
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ApplicationTrustManager.java | 29 +
opendj-sdk/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java | 426 +++++++++++++++++++++++++++++++++-
5 files changed, 623 insertions(+), 54 deletions(-)
diff --git a/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ApplicationTrustManager.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ApplicationTrustManager.java
index cf2f9ec..5b35b98 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ApplicationTrustManager.java
+++ b/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ApplicationTrustManager.java
@@ -163,7 +163,10 @@
lastRefusedChain = chain;
lastRefusedAuthType = authType;
lastRefusedCause = Cause.NOT_TRUSTED;
- throw ce;
+ OpendsCertificationException e = new OpendsCertificationException(
+ chain);
+ e.initCause(ce);
+ throw e;
}
if (!explicitlyAccepted)
@@ -177,7 +180,10 @@
lastRefusedChain = chain;
lastRefusedAuthType = authType;
lastRefusedCause = Cause.HOST_NAME_MISMATCH;
- throw ce;
+ OpendsCertificationException e = new OpendsCertificationException(
+ chain);
+ e.initCause(ce);
+ throw e;
}
}
}
@@ -214,7 +220,9 @@
lastRefusedChain = chain;
lastRefusedAuthType = authType;
lastRefusedCause = Cause.NOT_TRUSTED;
- throw ce;
+ OpendsCertificationException e = new OpendsCertificationException(chain);
+ e.initCause(ce);
+ throw e;
}
if (!explicitlyAccepted)
@@ -228,7 +236,10 @@
lastRefusedChain = chain;
lastRefusedAuthType = authType;
lastRefusedCause = Cause.HOST_NAME_MISMATCH;
- throw ce;
+ OpendsCertificationException e = new OpendsCertificationException(
+ chain);
+ e.initCause(ce);
+ throw e;
}
}
}
@@ -334,8 +345,8 @@
}
if (!found)
{
- throw new CertificateException(
- "Certificate not in list of accepted certificates");
+ throw new OpendsCertificationException(
+ "Certificate not in list of accepted certificates", chain);
}
}
@@ -368,8 +379,10 @@
if (!matches)
{
- throw new CertificateException("Hostname mismatch between host name "+
- host+" and subject DN: "+chain[0].getSubjectX500Principal());
+ throw new OpendsCertificationException(
+ "Hostname mismatch between host name " + host
+ + " and subject DN: " + chain[0].getSubjectX500Principal(),
+ chain);
}
}
}
diff --git a/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/OpendsCertificationException.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/OpendsCertificationException.java
new file mode 100644
index 0000000..11566d8
--- /dev/null
+++ b/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/OpendsCertificationException.java
@@ -0,0 +1,96 @@
+/*
+ * 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.admin.ads.util;
+
+//
+// J2SE
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate ;
+
+/**
+ * When a remote client (dsconfig for instance) wants to establish a
+ * remote connection with opends server through a secure connection,
+ * and if the certificate is not known, the SSL handcheck fails and
+ * this exception is thrown. This allows to get the certificate chain
+ * which is unknown.
+ */
+public class OpendsCertificationException extends CertificateException
+{
+
+ /**
+ * The serial version UUID.
+ */
+ private static final long serialVersionUID = 1151044344529478436L;
+
+
+ // ------------------
+ // Private certificate chain
+ // ------------------
+ private X509Certificate[] chain;
+
+ // ------------------
+ // Constructor
+ // ------------------
+
+ /**
+ * Build a new OpendsCertificationException object.
+ *
+ * @param chain the certificate chain which is unknown and has caused
+ * the SSL handcheck failure.
+ */
+ public OpendsCertificationException(X509Certificate[] chain)
+ {
+ super();
+ this.chain = chain;
+ }
+
+ /**
+ * Build a new OpendsCertificationException object.
+ *
+ * @param msg the detail message string of this exception.
+ *
+ * @param chain the certificate chain which is unknown and has caused
+ * the SSL handcheck failure.
+ */
+ public OpendsCertificationException(String msg, X509Certificate[] chain)
+ {
+ super(msg);
+ this.chain = chain;
+ }
+
+ /**
+ * Return the certificate chain which is unknown and has caused
+ * the SSL handcheck failure.
+ *
+ * @return the certificate chain which is unknown and has caused
+ * the SSL handcheck failure.
+ */
+ public X509Certificate[] getChain()
+ {
+ return chain;
+ }
+}
diff --git a/opendj-sdk/opends/src/messages/messages/utility.properties b/opendj-sdk/opends/src/messages/messages/utility.properties
index 8a597ba..2ad99e8 100644
--- a/opendj-sdk/opends/src/messages/messages/utility.properties
+++ b/opendj-sdk/opends/src/messages/messages/utility.properties
@@ -506,8 +506,8 @@
INFO_LDAP_CONN_PROMPT_SECURITY_LDAP_226=LDAP
INFO_LDAP_CONN_PROMPT_SECURITY_USE_SSL_227=LDAP with SSL
INFO_LDAP_CONN_PROMPT_SECURITY_USE_START_TSL_228=LDAP with StartTSL
-INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL_229=Do you want to automatically \
- trust the server certificate?
+INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL_229=Automatically \
+ trust
INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH_230=Truststore path:
INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PASSWORD_231=Password for \
truststore '%s':
@@ -531,3 +531,16 @@
INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE_243=%d
SEVERE_ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH_244=The provided path \
is not valid
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_METHOD_245=How do you want to trust the server certificate?
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_246=Use a truststore
+INFO_LDAP_CONN_PROMPT_SECURITY_MANUAL_CHECK_247=Manually validate
+INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE_248=Server Certificate:
+INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_249=%s
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_250=Do you trust this server certificate?
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_NO_251=No
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_SESSION_252=Yes, for this session only
+INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_ALWAYS_253=Yes, also add it to a truststore
+INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_DETAILS_254=View certificate details
+INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN_255 =User DN : %s
+INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY_256=Validity : From '%s'%n To '%s'
+INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER_257 =Issuer : %s
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java
index 8a70706..624bf65 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java
@@ -26,8 +26,9 @@
*/
package org.opends.server.tools.dsconfig;
-
import org.opends.admin.ads.util.ConnectionUtils;
+import org.opends.admin.ads.util.OpendsCertificationException;
+
import static org.opends.messages.DSConfigMessages.*;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
@@ -101,38 +102,96 @@
{
InitialLdapContext ctx;
String ldapsUrl = "ldaps://" + hostName + ":" + portNumber;
- try
+ while (true)
{
- ctx = ConnectionUtils.createLdapsContext(ldapsUrl, bindDN,
- bindPassword, ConnectionUtils.getDefaultLDAPTimeout(), null,
- trustManager, keyManager);
- conn = JNDIDirContextAdaptor.adapt(ctx);
- }
- catch (NamingException e)
- {
- Message message = ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(
- hostName, String.valueOf(portNumber));
- throw new ClientException(LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR,
- message) ;
+ try
+ {
+ ctx = ConnectionUtils.createLdapsContext(ldapsUrl, bindDN,
+ bindPassword, ConnectionUtils.getDefaultLDAPTimeout(), null,
+ trustManager, keyManager);
+ conn = JNDIDirContextAdaptor.adapt(ctx);
+ break;
+ }
+ catch (NamingException e)
+ {
+ if ( app.isInteractive() && ci.isTrustStoreInMemory())
+ {
+ if ((e.getRootCause() != null)
+ && (e.getRootCause().getCause()
+ instanceof OpendsCertificationException))
+ {
+ OpendsCertificationException oce =
+ (OpendsCertificationException) e.getRootCause().getCause();
+ if (ci.checkServerCertificate(oce.getChain()))
+ {
+ // If the certificate is trusted, update the trust manager.
+ trustManager = ci.getTrustManager();
+
+ // Try to connect again.
+ continue ;
+ }
+ }
+ else
+ {
+ Message message = ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(
+ hostName, String.valueOf(portNumber));
+ throw new ClientException(
+ LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR, message);
+ }
+ }
+ Message message = ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(
+ hostName, String.valueOf(portNumber));
+ throw new ClientException(
+ LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR, message);
+ }
}
}
else if (ci.useStartTLS())
{
InitialLdapContext ctx;
String ldapUrl = "ldap://" + hostName + ":" + portNumber;
- try
+ while (true)
{
- ctx = ConnectionUtils.createStartTLSContext(ldapUrl, bindDN,
- bindPassword, ConnectionUtils.getDefaultLDAPTimeout(), null,
- trustManager, keyManager, null);
- conn = JNDIDirContextAdaptor.adapt(ctx);
- }
- catch (NamingException e)
- {
- Message message = ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(
- hostName, String.valueOf(portNumber));
- throw new ClientException(LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR,
- message) ;
+ try
+ {
+ ctx = ConnectionUtils.createStartTLSContext(ldapUrl, bindDN,
+ bindPassword, ConnectionUtils.getDefaultLDAPTimeout(), null,
+ trustManager, keyManager, null);
+ conn = JNDIDirContextAdaptor.adapt(ctx);
+ break;
+ }
+ catch (NamingException e)
+ {
+ if ( app.isInteractive() && ci.isTrustStoreInMemory())
+ {
+ if ((e.getRootCause() != null)
+ && (e.getRootCause().getCause()
+ instanceof OpendsCertificationException))
+ {
+ OpendsCertificationException oce =
+ (OpendsCertificationException) e.getRootCause().getCause();
+ if (ci.checkServerCertificate(oce.getChain()))
+ {
+ // If the certificate is trusted, update the trust manager.
+ trustManager = ci.getTrustManager();
+
+ // Try to connect again.
+ continue ;
+ }
+ }
+ else
+ {
+ Message message = ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(
+ hostName, String.valueOf(portNumber));
+ throw new ClientException(
+ LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR, message);
+ }
+ }
+ Message message = ERR_DSCFG_ERROR_LDAP_FAILED_TO_CONNECT.get(
+ hostName, String.valueOf(portNumber));
+ throw new ClientException(
+ LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR, message);
+ }
}
}
else
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java b/opendj-sdk/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
index 05eff62..ae8afa7 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
@@ -43,7 +43,11 @@
import java.net.UnknownHostException;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.X509Certificate;
/**
* Supports interacting with a user through the command line to
@@ -69,6 +73,12 @@
// the Console application
private ConsoleApplication app;
+ // Indicate if the truststore in in memory
+ private boolean trustStoreInMemory = false;
+
+ // The truststore to use for the SSL or STARTTLS connection
+ private KeyStore truststore;
+
/**
* Enumeration description protocols for interactive CLI choices.
*/
@@ -118,6 +128,105 @@
}
/**
+ * Enumeration description protocols for interactive CLI choices.
+ */
+ private enum TrustMethod
+ {
+ TRUSTALL(1, INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL.get()),
+
+ TRUSTSTORE(2,INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE.get()),
+
+ DISPLAY_CERTIFICATE(3,INFO_LDAP_CONN_PROMPT_SECURITY_MANUAL_CHECK.get());
+
+ private Integer choice;
+
+ private Message msg;
+
+ /**
+ * Private constructor.
+ *
+ * @param i
+ * the menu return value.
+ * @param s
+ * the message message.
+ */
+ private TrustMethod(int i, Message msg)
+ {
+ choice = new Integer(i);
+ this.msg = msg;
+ }
+
+ /**
+ * Returns the choice number.
+ *
+ * @return the attribute name.
+ */
+ public Integer getChoice()
+ {
+ return choice;
+ }
+
+ /**
+ * Return the menu message.
+ *
+ * @return the menu message.
+ */
+ public Message getMenuMessage()
+ {
+ return msg;
+ }
+ }
+
+ /**
+ * Enumeration description server certificate trust option.
+ */
+ private enum TrustOption
+ {
+ UNTRUSTED(1, INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_NO.get()),
+ SESSION(2,INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_SESSION.get()),
+ PERMAMENT(3,INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_ALWAYS.get()),
+ CERTIFICATE_DETAILS(4,
+ INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_DETAILS.get());
+
+ private Integer choice;
+
+ private Message msg;
+
+ /**
+ * Private constructor.
+ *
+ * @param i
+ * the menu return value.
+ * @param s
+ * the message message.
+ */
+ private TrustOption(int i, Message msg)
+ {
+ choice = new Integer(i);
+ this.msg = msg;
+ }
+
+ /**
+ * Returns the choice number.
+ *
+ * @return the attribute name.
+ */
+ public Integer getChoice()
+ {
+ return choice;
+ }
+
+ /**
+ * Return the menu message.
+ *
+ * @return the menu message.
+ */
+ public Message getMenuMessage()
+ {
+ return msg;
+ }
+ }
+ /**
* Constructs a parameterized instance.
*
* @param app console application
@@ -480,8 +589,25 @@
private ApplicationTrustManager getTrustManagerInternal()
throws ArgumentException
{
- boolean trustAll = secureArgsList.trustAllArg.isPresent();
- if (app.isInteractive() && !secureArgsList.trustAllArg.isPresent())
+ // If we have the trustALL flag, don't do anything
+ // just return null
+ if (secureArgsList.trustAllArg.isPresent())
+ {
+ return null;
+ }
+
+ // Check if some trust manager info are set
+ boolean weDontKnowTheTrustMethod =
+ !( secureArgsList.trustAllArg.isPresent()
+ ||
+ secureArgsList.trustStorePathArg.isPresent()
+ ||
+ secureArgsList.trustStorePasswordArg.isPresent()
+ ||
+ secureArgsList.trustStorePasswordFileArg.isPresent()
+ );
+ boolean askForTrustStore = false;
+ if (app.isInteractive() && weDontKnowTheTrustMethod)
{
if (!isHeadingDisplayed)
{
@@ -491,29 +617,73 @@
isHeadingDisplayed = true;
}
+ app.println();
+ MenuBuilder<Integer> builder = new MenuBuilder<Integer>(app);
+ builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_METHOD.get());
+
+ TrustMethod defaultTrustMethod = TrustMethod.DISPLAY_CERTIFICATE;
+ for (TrustMethod t : TrustMethod.values())
+ {
+ int i = builder.addNumberedOption(t.getMenuMessage(), MenuResult
+ .success(t.getChoice()));
+ if (t.equals(defaultTrustMethod))
+ {
+ builder.setDefault(
+ INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE
+ .get(new Integer(i)), MenuResult.success(t.getChoice()));
+ }
+ }
+
+ Menu<Integer> menu = builder.toMenu();
+ trustStoreInMemory = false;
try
{
- app.println();
- trustAll = app.confirmAction(
- INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL.get(), false);
+ MenuResult<Integer> result = menu.run();
+ if (result.isSuccess())
+ {
+ if (result.getValue().equals(TrustMethod.TRUSTALL.getChoice()))
+ {
+ // If we have the trustALL flag, don't do anything
+ // just return null
+ return null;
+ }
+ else if (result.getValue().equals(
+ TrustMethod.TRUSTSTORE.getChoice()))
+ {
+ // We have to ask for truststore info
+ askForTrustStore = true;
+ }
+ else if (result.getValue().equals(
+ TrustMethod.DISPLAY_CERTIFICATE.getChoice()))
+ {
+ // The certificate will be displayed to the user
+ askForTrustStore = false;
+ trustStoreInMemory = true;
+ }
+ else
+ {
+ // Should never happen.
+ throw new RuntimeException();
+ }
+ }
+ else
+ {
+ // Should never happen.
+ throw new RuntimeException();
+ }
}
catch (CLIException e)
{
- // Should never happen.
throw new RuntimeException(e);
- }
- }
- // Trust everything, so no trust manager
- if (trustAll)
- {
- return null;
+ }
}
// If we not trust all server certificates, we have to get info
// about truststore. First get the truststore path.
String truststorePath = secureArgsList.trustStorePathArg.getValue();
- if (app.isInteractive() && !secureArgsList.trustStorePathArg.isPresent())
+ if (app.isInteractive() && !secureArgsList.trustStorePathArg.isPresent()
+ && askForTrustStore)
{
if (!isHeadingDisplayed)
{
@@ -610,17 +780,24 @@
// We'we got all the information to get the truststore manager
try
{
- FileInputStream fos = new FileInputStream(truststorePath);
- KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
- if (truststorePassword != null)
+ truststore = KeyStore.getInstance(KeyStore.getDefaultType());
+ if (truststorePath != null)
{
- truststore.load(fos, truststorePassword.toCharArray());
+ FileInputStream fos = new FileInputStream(truststorePath);
+ if (truststorePassword != null)
+ {
+ truststore.load(fos, truststorePassword.toCharArray());
+ }
+ else
+ {
+ truststore.load(fos, null);
+ }
+ fos.close();
}
else
{
- truststore.load(fos, null);
+ truststore.load(null, null);
}
- fos.close();
return new ApplicationTrustManager(truststore);
}
catch (Exception e)
@@ -890,6 +1067,217 @@
return this.keyManager;
}
+ /**
+ * Indicate if the truststore is in memory.
+ *
+ * @return true if the truststore is in memory.
+ */
+ public boolean isTrustStoreInMemory() {
+ return this.trustStoreInMemory;
+ }
+ /**
+ * Indicate if the certificate chain can be trusted.
+ *
+ * @param chain The certificate chain to validate
+ * @return true if the server certificate is trusted.
+ */
+ public boolean checkServerCertificate(X509Certificate[] chain)
+ {
+ app.println();
+ app.println(INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE.get());
+ app.println();
+ for (int i = 0; i < chain.length; i++)
+ {
+ // Certificate DN
+ app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN.get(
+ chain[i].getSubjectDN().toString()));
+
+ // certificate validity
+ app.println(
+ INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY.get(
+ chain[i].getNotBefore().toString(),
+ chain[i].getNotAfter().toString()));
+
+ // certificate Issuer
+ app.println(
+ INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER.get(
+ chain[i].getIssuerDN().toString()));
+
+ if (i+1 <chain.length)
+ {
+ app.println();
+ app.println();
+ }
+ }
+ MenuBuilder<Integer> builder = new MenuBuilder<Integer>(app);
+ builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION.get());
+
+ TrustOption defaultTrustMethod = TrustOption.SESSION ;
+ for (TrustOption t : TrustOption.values())
+ {
+ int i = builder.addNumberedOption(t.getMenuMessage(), MenuResult
+ .success(t.getChoice()));
+ if (t.equals(defaultTrustMethod))
+ {
+ builder.setDefault(
+ INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE
+ .get(new Integer(i)), MenuResult.success(t.getChoice()));
+ }
+ }
+
+ app.println();
+ app.println();
+
+ Menu<Integer> menu = builder.toMenu();
+ while (true)
+ {
+ try
+ {
+ MenuResult<Integer> result = menu.run();
+ if (result.isSuccess())
+ {
+ if (result.getValue().equals(TrustOption.UNTRUSTED.getChoice()))
+ {
+ return false;
+ }
+
+ if ((result.getValue().equals(TrustOption.CERTIFICATE_DETAILS
+ .getChoice())))
+ {
+ for (int i = 0; i < chain.length; i++)
+ {
+ app.println();
+ app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE
+ .get(chain[i].toString()));
+ }
+ continue;
+ }
+
+ // We should add it in the memory truststore
+ for (int i = 0; i < chain.length; i++)
+ {
+ String alias = chain[i].getSubjectDN().getName();
+ try
+ {
+ truststore.setCertificateEntry(alias, chain[i]);
+ }
+ catch (KeyStoreException e1)
+ {
+ // What should we do else?
+ return false;
+ }
+ }
+
+ // Update the trust manager
+ trustManager = new ApplicationTrustManager(truststore);
+
+ if (result.getValue().equals(TrustOption.PERMAMENT.getChoice()))
+ {
+ ValidationCallback<String> callback =
+ new ValidationCallback<String>()
+ {
+ public String validate(ConsoleApplication app, String input)
+ throws CLIException
+ {
+ String ninput = input.trim();
+ if (ninput.length() == 0)
+ {
+ app.println();
+ app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH
+ .get());
+ app.println();
+ return null;
+ }
+ File f = new File(ninput);
+ if (!f.isDirectory())
+ {
+ return ninput;
+ }
+ else
+ {
+ app.println();
+ app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH
+ .get());
+ app.println();
+ return null;
+ }
+ }
+ };
+
+ String truststorePath;
+ try
+ {
+ app.println();
+ truststorePath = app.readValidatedInput(
+ INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH.get(),
+ callback);
+ }
+ catch (CLIException e)
+ {
+ return true;
+ }
+
+ // Read the password from the stdin.
+ String truststorePassword;
+ try
+ {
+ app.println();
+ Message prompt = INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD
+ .get(truststorePath);
+ truststorePassword = app.readPassword(prompt);
+ }
+ catch (Exception e)
+ {
+ return true;
+ }
+ try
+ {
+ KeyStore ts = KeyStore.getInstance("JKS");
+ FileInputStream fis;
+ try
+ {
+ fis = new FileInputStream(truststorePath);
+ }
+ catch (FileNotFoundException e)
+ {
+ fis = null;
+ }
+ ts.load(fis, truststorePassword.toCharArray());
+ if (fis != null)
+ {
+ fis.close();
+ }
+ for (int i = 0; i < chain.length; i++)
+ {
+ String alias = chain[i].getSubjectDN().getName();
+ ts.setCertificateEntry(alias, chain[i]);
+ }
+ FileOutputStream fos = new FileOutputStream(truststorePath);
+ ts.store(fos, truststorePassword.toCharArray());
+ if (fos != null)
+ {
+ fos.close();
+ }
+ }
+ catch (Exception e)
+ {
+ return true;
+ }
+ }
+ return true;
+ }
+ else
+ {
+ // Should never happen.
+ throw new RuntimeException();
+ }
+ }
+ catch (CLIException cliE)
+ {
+ throw new RuntimeException(cliE);
+ }
+ }
+ }
}
--
Gitblit v1.10.0