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/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java | 426 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 407 insertions(+), 19 deletions(-)
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