| opends/src/messages/messages/utility.properties | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java | ●●●●● patch | view | raw | blame | history |
opends/src/messages/messages/utility.properties
@@ -503,4 +503,31 @@ it was rejected by a plugin SEVERE_ERR_LDIF_REJECTED_BY_PLUGIN_225=Rejecting entry %s because it was \ rejected by a plugin: %s 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_TRUSTSTORE_PATH_230=Truststore path: INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PASSWORD_231=Password for \ truststore '%s': INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_NEEDED_232=Do you want to perform \ secure authentication (client side authentication)? INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PATH_233=Keystore path: INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD_234=Password for keystore \ '%s': INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_NAME_235=Certificate nickname: INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS_236=>>>> Specify OpenDS LDAP \ connection parameters SEVERE_ERR_LDAP_CONN_BAD_HOST_NAME_237=The hostname "%s" could not be \ resolved. Please check you have have the correct address SEVERE_ERR_LDAP_CONN_BAD_PORT_NUMBER_238=Invalid port number "%s". Please \ enter a valid port number between 1 and 65535 INFO_LDAP_CONN_PROMPT_HOST_NAME_239=Directory server hostname or IP address \ [%s]: INFO_LDAP_CONN_PROMPT_PORT_NUMBER_240=Directory server port number [%d]: INFO_LDAP_CONN_PROMPT_BIND_DN_241=Administrator user bind DN [%s]: INFO_LDAP_CONN_PROMPT_SECURITY_USE_SECURE_CTX_242=How do you want to connect? 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 opends/src/server/org/opends/server/tools/dsconfig/LDAPManagementContextFactory.java
@@ -27,24 +27,8 @@ package org.opends.server.tools.dsconfig; import static org.opends.messages.DSConfigMessages.*; import static org.opends.messages.ToolMessages.*; import java.io.File; import java.io.FileInputStream; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.KeyStore; import java.util.LinkedHashSet; import javax.naming.NamingException; import javax.naming.ldap.InitialLdapContext; import javax.net.ssl.KeyManager; import javax.net.ssl.TrustManager; import org.opends.admin.ads.util.ApplicationKeyManager; import org.opends.admin.ads.util.ApplicationTrustManager; import org.opends.admin.ads.util.ConnectionUtils; import static org.opends.messages.DSConfigMessages.*; import org.opends.messages.Message; import org.opends.messages.MessageBuilder; import org.opends.server.admin.client.AuthenticationException; @@ -58,17 +42,17 @@ import org.opends.server.admin.client.ldap.LDAPManagementContext; import org.opends.server.protocols.ldap.LDAPResultCode; import org.opends.server.tools.ClientException; import org.opends.server.util.SelectableCertificateKeyManager; import org.opends.server.util.args.Argument; import org.opends.server.util.args.ArgumentException; import org.opends.server.util.args.SubCommandArgumentParser; import org.opends.server.util.cli.CLIException; import org.opends.server.util.cli.LDAPConnectionConsoleInteraction; import org.opends.server.util.cli.ConsoleApplication; import org.opends.server.util.cli.Menu; import org.opends.server.util.cli.MenuBuilder; import org.opends.server.util.cli.MenuResult; import org.opends.server.util.cli.ValidationCallback; import javax.naming.NamingException; import javax.naming.ldap.InitialLdapContext; import javax.net.ssl.KeyManager; import javax.net.ssl.TrustManager; import java.util.LinkedHashSet; /** @@ -83,60 +67,6 @@ // The management context. private ManagementContext context = null; // Indicate if we need to display the heading private boolean isHeadingDisplayed = false; // the Console application private ConsoleApplication app; /** * Enumeration description protocols for interactive CLI choices. */ private enum Protocols { LDAP(1, INFO_DSCFG_PROMPT_SECURITY_LDAP.get()), SSL(2, INFO_DSCFG_PROMPT_SECURITY_USE_SSL.get()), START_TSL(3, INFO_DSCFG_PROMPT_SECURITY_USE_START_TSL.get()); private Integer choice; private Message msg; /** * Private constructor. * * @param i * the menu return value. * @param s * the message message. */ private Protocols(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; } }; /** * Creates a new LDAP management context factory. */ @@ -153,347 +83,23 @@ // Lazily create the LDAP management context. if (context == null) { this.app = app; isHeadingDisplayed = false; boolean secureConnection = ( secureArgsList.useSSLArg.isPresent() || secureArgsList.useStartTLSArg.isPresent() || secureArgsList.trustAllArg.isPresent() || secureArgsList.trustStorePathArg.isPresent() || secureArgsList.trustStorePasswordArg.isPresent() || secureArgsList.trustStorePasswordFileArg.isPresent() || secureArgsList.keyStorePathArg.isPresent() || secureArgsList.keyStorePasswordArg.isPresent() || secureArgsList.keyStorePasswordFileArg.isPresent() ); // Get the LDAP host. String hostName = secureArgsList.hostNameArg.getValue(); final String tmpHostName = hostName; if (app.isInteractive() && !secureArgsList.hostNameArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<String> callback = new ValidationCallback<String>() { public String validate(ConsoleApplication app, String input) throws CLIException { String ninput = input.trim(); if (ninput.length() == 0) { return tmpHostName; } else { try { InetAddress.getByName(ninput); return ninput; } catch (UnknownHostException e) { // Try again... app.println(); app.println(ERR_DSCFG_BAD_HOST_NAME.get(ninput)); app.println(); return null; } } } }; try { app.println(); hostName = app.readValidatedInput(INFO_DSCFG_PROMPT_HOST_NAME .get(hostName), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } boolean useSSL = secureArgsList.useSSL(); boolean useStartTLS = secureArgsList.useStartTLS(); KeyManager keyManager = null; TrustManager trustManager = null; boolean connectionTypeIsSet = ( secureArgsList.useSSLArg.isPresent() || secureArgsList.useStartTLSArg.isPresent() ); if (app.isInteractive() && !connectionTypeIsSet) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } MenuBuilder<Integer> builder = new MenuBuilder<Integer>(app); builder.setPrompt(INFO_DSCFG_PROMPT_SECURITY_USE_SECURE_CTX.get()); Protocols defaultProtocol ; if (secureConnection) { defaultProtocol = Protocols.SSL; } else { defaultProtocol = Protocols.LDAP; } for (Protocols p : Protocols.values()) { if (secureConnection && p.equals(Protocols.LDAP)) { continue ; } int i = builder.addNumberedOption(p.getMenuMessage(), MenuResult .success(p.getChoice())); if (p.equals(defaultProtocol)) { builder.setDefault( INFO_DSCFG_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE .get(new Integer(i)), MenuResult.success(p.getChoice())); } } Menu<Integer> menu = builder.toMenu(); try { MenuResult<Integer> result = menu.run(); if (result.isSuccess()) { if (result.getValue().equals(Protocols.SSL.getChoice())) { useSSL = true; } else if (result.getValue() .equals(Protocols.START_TSL.getChoice())) { useStartTLS = true; } } else { // Should never happen. throw new RuntimeException(); } } catch (CLIException e) { throw new RuntimeException(e); } } if (useSSL || useStartTLS) { // Get truststore info trustManager = getTrustManager(); // Check if we need client side authentication keyManager = getKeyManager(); } // Get the LDAP port. int portNumber; if (!useSSL) { portNumber = secureArgsList.portArg.getIntValue(); } else { if (secureArgsList.portArg.isPresent()) { portNumber = secureArgsList.portArg.getIntValue(); } else { portNumber = 636; } } final int tmpPortNumber = portNumber; if (app.isInteractive() && !secureArgsList.portArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<Integer> callback = new ValidationCallback<Integer>() { public Integer validate(ConsoleApplication app, String input) throws CLIException { String ninput = input.trim(); if (ninput.length() == 0) { return tmpPortNumber; } else { try { int i = Integer.parseInt(ninput); if (i < 1 || i > 65535) { throw new NumberFormatException(); } return i; } catch (NumberFormatException e) { // Try again... app.println(); app.println(ERR_DSCFG_BAD_PORT_NUMBER.get(ninput)); app.println(); return null; } } } }; try { app.println(); portNumber = app.readValidatedInput(INFO_DSCFG_PROMPT_PORT_NUMBER .get(portNumber), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // Get the LDAP bind credentials. String bindDN = secureArgsList.bindDnArg.getValue(); final String tmpBindDN = bindDN; if (keyManager == null) { if (app.isInteractive() && !secureArgsList.bindDnArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<String> callback = new ValidationCallback<String>() { public String validate(ConsoleApplication app, String input) throws CLIException { String ninput = input.trim(); if (ninput.length() == 0) { return tmpBindDN; } else { return ninput; } } }; try { app.println(); bindDN = app.readValidatedInput(INFO_DSCFG_PROMPT_BIND_DN .get(bindDN), callback); } catch (CLIException e) { throw ArgumentExceptionFactory .unableToReadConnectionParameters(e); } } } else { bindDN = null ; } String bindPassword = secureArgsList.bindPasswordArg.getValue(); if (keyManager == null) { if (secureArgsList.bindPasswordFileArg.isPresent()) { // Read from file if it exists. bindPassword = secureArgsList.bindPasswordFileArg.getValue(); if (bindPassword == null) { throw ArgumentExceptionFactory.missingBindPassword(bindDN); } } else if (bindPassword == null || bindPassword.equals("-")) { // Read the password from the stdin. if (!app.isInteractive()) { throw ArgumentExceptionFactory .unableToReadBindPasswordInteractively(); } if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } try { app.println(); Message prompt = INFO_LDAPAUTH_PASSWORD_PROMPT.get(bindDN); bindPassword = app.readPassword(prompt); } catch (Exception e) { throw ArgumentExceptionFactory .unableToReadConnectionParameters(e); } } } // Interact with the user though the console to get // LDAP connection information LDAPConnectionConsoleInteraction ci = new LDAPConnectionConsoleInteraction(app, secureArgsList); ci.run(); String hostName = ci.getHostName(); Integer portNumber = ci.getPortNumber(); String bindDN = ci.getBindDN(); String bindPassword = ci.getBindPassword(); TrustManager trustManager = ci.getTrustManager(); KeyManager keyManager = ci.getKeyManager(); // Do we have a secure connection ? LDAPConnection conn ; if (useSSL) if (ci.useSSL()) { InitialLdapContext ctx = null; InitialLdapContext ctx; String ldapsUrl = "ldaps://" + hostName + ":" + portNumber; try { @@ -510,9 +116,9 @@ message) ; } } else if (useStartTLS) else if (ci.useStartTLS()) { InitialLdapContext ctx = null; InitialLdapContext ctx; String ldapUrl = "ldap://" + hostName + ":" + portNumber; try { @@ -600,342 +206,4 @@ } } /** * Get the trust manager. * * @return The trust manager based on CLI args on interactive prompt. * @throws ArgumentException If an error occurs when getting args values. */ private ApplicationTrustManager getTrustManager() throws ArgumentException { boolean trustAll = secureArgsList.trustAllArg.isPresent(); if (app.isInteractive() && !secureArgsList.trustAllArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } try { app.println(); trustAll = app.confirmAction(INFO_DSCFG_PROMPT_SECURITY_USE_TRUST_ALL .get(), false); } 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 (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } 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_DSCFG_PROMPT_SECURITY_INVALID_FILE_PATH .get()); app.println(); return null; } File f = new File(ninput); if (f.exists() && f.canRead() && !f.isDirectory()) { return ninput; } else { app.println(); app.println(ERR_DSCFG_PROMPT_SECURITY_INVALID_FILE_PATH .get()); app.println(); return null; } } }; try { app.println(); truststorePath = app.readValidatedInput( INFO_DSCFG_PROMPT_SECURITY_TRUSTSTORE_PATH.get(), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // Then the truststore password. // As the most common case is to have no password for truststore, // we don't ask it in the interactive mode. String truststorePassword = secureArgsList.trustStorePasswordArg .getValue(); if (secureArgsList.trustStorePasswordFileArg.isPresent()) { // Read from file if it exists. truststorePassword = secureArgsList.trustStorePasswordFileArg .getValue(); } if ((truststorePassword != null) && (truststorePassword.equals("-"))) { // Read the password from the stdin. if (!app.isInteractive()) { truststorePassword = null; } else { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } try { app.println(); Message prompt = INFO_DSCFG_PROMPT_SECURITY_TRUSTSTORE_PASSWORD .get(truststorePath); truststorePassword = app.readPassword(prompt); } catch (Exception e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } } // 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.load(fos, truststorePassword.toCharArray()); } else { truststore.load(fos, null); } fos.close(); return new ApplicationTrustManager(truststore); } catch (Exception e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } /** * Get the key manager. * * @return The key manager based on CLI args on interactive prompt. * @throws ArgumentException If an error occurs when getting args values. */ private KeyManager getKeyManager() throws ArgumentException { // Do we need client side authentication ? // If one of the client side authentication args is set, we assume // that we // need client side authentication. boolean weDontKnowIfWeNeedKeystore = !(secureArgsList.keyStorePathArg .isPresent() || secureArgsList.keyStorePasswordArg.isPresent() || secureArgsList.keyStorePasswordFileArg.isPresent() || secureArgsList.certNicknameArg .isPresent()); // We don't have specific key manager parameter. // We assume that no client side authentication is required // Client side authentication is not the common use case. As a // consequence, interactive mode doesn't add an extra question // which will be in most cases useless. if (weDontKnowIfWeNeedKeystore) { return null; } // Get info about keystore. First get the keystore path. String keystorePath = secureArgsList.keyStorePathArg.getValue(); if (app.isInteractive() && !secureArgsList.keyStorePathArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<String> callback = new ValidationCallback<String>() { public String validate(ConsoleApplication app, String input) throws CLIException { String ninput = input.trim(); if (ninput.length() == 0) { return ninput; } File f = new File(ninput); if (f.exists() && f.canRead() && !f.isDirectory()) { return ninput; } else { app.println(); app.println(ERR_DSCFG_PROMPT_SECURITY_INVALID_FILE_PATH .get()); app.println(); return null; } } }; try { app.println(); keystorePath = app.readValidatedInput( INFO_DSCFG_PROMPT_SECURITY_KEYSTORE_PATH.get(), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // Then the keystore password. String keystorePassword = secureArgsList.keyStorePasswordArg.getValue(); if (secureArgsList.keyStorePasswordFileArg.isPresent()) { // Read from file if it exists. keystorePassword = secureArgsList.keyStorePasswordFileArg.getValue(); if (keystorePassword == null) { throw ArgumentExceptionFactory.missingBindPassword(keystorePassword); } } else if (keystorePassword == null || keystorePassword.equals("-")) { // Read the password from the stdin. if (!app.isInteractive()) { throw ArgumentExceptionFactory .unableToReadBindPasswordInteractively(); } if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } try { app.println(); Message prompt = INFO_DSCFG_PROMPT_SECURITY_KEYSTORE_PASSWORD .get(keystorePath); keystorePassword = app.readPassword(prompt); } catch (Exception e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // finally the certificate name, if needed. String certifNickname = secureArgsList.certNicknameArg.getValue(); if (app.isInteractive() && !secureArgsList.certNicknameArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_DSCFG_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<String> callback = new ValidationCallback<String>() { public String validate(ConsoleApplication app, String input) throws CLIException { return input.trim(); } }; try { app.println(); certifNickname = app.readValidatedInput( INFO_DSCFG_PROMPT_SECURITY_CERTIFICATE_NAME.get(), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // We'we got all the information to get the keystore manager try { FileInputStream fos = new FileInputStream(keystorePath); KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(fos, keystorePassword.toCharArray()); fos.close(); ApplicationKeyManager akm = new ApplicationKeyManager(keystore, keystorePassword.toCharArray()); if (certifNickname.length() != 0) { return new SelectableCertificateKeyManager(akm, certifNickname); } else { return akm ; } } catch (Exception e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } } opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
New file @@ -0,0 +1,895 @@ /* * 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.cli; import org.opends.messages.Message; import static org.opends.messages.UtilityMessages.*; import static org.opends.messages.ToolMessages.INFO_LDAPAUTH_PASSWORD_PROMPT; import org.opends.server.tools.dsconfig.ArgumentExceptionFactory; import org.opends.server.admin.client.cli.SecureConnectionCliArgs; import org.opends.server.util.args.ArgumentException; import org.opends.server.util.SelectableCertificateKeyManager; import org.opends.admin.ads.util.ApplicationTrustManager; import org.opends.admin.ads.util.ApplicationKeyManager; import javax.net.ssl.KeyManager; import javax.net.ssl.TrustManager; import java.net.InetAddress; import java.net.UnknownHostException; import java.io.File; import java.io.FileInputStream; import java.security.KeyStore; /** * Supports interacting with a user through the command line to * prompt for information necessary to create an LDAP connection. */ public class LDAPConnectionConsoleInteraction { private boolean useSSL; private boolean useStartTLS; private String hostName; private int portNumber; private String bindDN; private String bindPassword; private KeyManager keyManager; private TrustManager trustManager; // The SecureConnectionCliArgsList object. private SecureConnectionCliArgs secureArgsList = null; // Indicate if we need to display the heading private boolean isHeadingDisplayed = false; // the Console application private ConsoleApplication app; /** * Enumeration description protocols for interactive CLI choices. */ private enum Protocols { LDAP(1, INFO_LDAP_CONN_PROMPT_SECURITY_LDAP.get()), SSL(2, INFO_LDAP_CONN_PROMPT_SECURITY_USE_SSL.get()), START_TSL(3, INFO_LDAP_CONN_PROMPT_SECURITY_USE_START_TSL.get()); private Integer choice; private Message msg; /** * Private constructor. * * @param i * the menu return value. * @param msg * the message message. */ private Protocols(int i, Message msg) { choice = 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 * @param secureArgs existing set of arguments that have already * been parsed and contain some potential command line specified * LDAP arguments */ public LDAPConnectionConsoleInteraction(ConsoleApplication app, SecureConnectionCliArgs secureArgs) { this.app = app; this.secureArgsList = secureArgs; } /** * Interact with the user though the console to get information * necessary to establish an LDAP connection. * * @throws ArgumentException if there is a problem with the arguments */ public void run() throws ArgumentException { boolean secureConnection = ( secureArgsList.useSSLArg.isPresent() || secureArgsList.useStartTLSArg.isPresent() || secureArgsList.trustAllArg.isPresent() || secureArgsList.trustStorePathArg.isPresent() || secureArgsList.trustStorePasswordArg.isPresent() || secureArgsList.trustStorePasswordFileArg.isPresent() || secureArgsList.keyStorePathArg.isPresent() || secureArgsList.keyStorePasswordArg.isPresent() || secureArgsList.keyStorePasswordFileArg.isPresent() ); // Get the LDAP host. hostName = secureArgsList.hostNameArg.getValue(); final String tmpHostName = hostName; if (app.isInteractive() && !secureArgsList.hostNameArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<String> callback = new ValidationCallback<String>() { public String validate(ConsoleApplication app, String input) throws CLIException { String ninput = input.trim(); if (ninput.length() == 0) { return tmpHostName; } else { try { InetAddress.getByName(ninput); return ninput; } catch (UnknownHostException e) { // Try again... app.println(); app.println(ERR_LDAP_CONN_BAD_HOST_NAME.get(ninput)); app.println(); return null; } } } }; try { app.println(); hostName = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_HOST_NAME .get(hostName), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } useSSL = secureArgsList.useSSL(); useStartTLS = secureArgsList.useStartTLS(); boolean connectionTypeIsSet = ( secureArgsList.useSSLArg.isPresent() || secureArgsList.useStartTLSArg.isPresent() ); if (app.isInteractive() && !connectionTypeIsSet) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } MenuBuilder<Integer> builder = new MenuBuilder<Integer>(app); builder.setPrompt(INFO_LDAP_CONN_PROMPT_SECURITY_USE_SECURE_CTX.get()); Protocols defaultProtocol ; if (secureConnection) { defaultProtocol = Protocols.SSL; } else { defaultProtocol = Protocols.LDAP; } for (Protocols p : Protocols.values()) { if (secureConnection && p.equals(Protocols.LDAP)) { continue ; } int i = builder.addNumberedOption(p.getMenuMessage(), MenuResult .success(p.getChoice())); if (p.equals(defaultProtocol)) { builder.setDefault( INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE .get(i), MenuResult.success(p.getChoice())); } } Menu<Integer> menu = builder.toMenu(); try { MenuResult<Integer> result = menu.run(); if (result.isSuccess()) { if (result.getValue().equals(Protocols.SSL.getChoice())) { useSSL = true; } else if (result.getValue() .equals(Protocols.START_TSL.getChoice())) { useStartTLS = true; } } else { // Should never happen. throw new RuntimeException(); } } catch (CLIException e) { throw new RuntimeException(e); } } if (useSSL || useStartTLS) { // Get truststore info trustManager = getTrustManagerInternal(); // Check if we need client side authentication keyManager = getKeyManagerInternal(); } // Get the LDAP port. if (!useSSL) { portNumber = secureArgsList.portArg.getIntValue(); } else { if (secureArgsList.portArg.isPresent()) { portNumber = secureArgsList.portArg.getIntValue(); } else { portNumber = 636; } } final int tmpPortNumber = portNumber; if (app.isInteractive() && !secureArgsList.portArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<Integer> callback = new ValidationCallback<Integer>() { public Integer validate(ConsoleApplication app, String input) throws CLIException { String ninput = input.trim(); if (ninput.length() == 0) { return tmpPortNumber; } else { try { int i = Integer.parseInt(ninput); if (i < 1 || i > 65535) { throw new NumberFormatException(); } return i; } catch (NumberFormatException e) { // Try again... app.println(); app.println(ERR_LDAP_CONN_BAD_PORT_NUMBER.get(ninput)); app.println(); return null; } } } }; try { app.println(); portNumber = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_PORT_NUMBER .get(portNumber), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // Get the LDAP bind credentials. bindDN = secureArgsList.bindDnArg.getValue(); final String tmpBindDN = bindDN; if (keyManager == null) { if (app.isInteractive() && !secureArgsList.bindDnArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<String> callback = new ValidationCallback<String>() { public String validate(ConsoleApplication app, String input) throws CLIException { String ninput = input.trim(); if (ninput.length() == 0) { return tmpBindDN; } else { return ninput; } } }; try { app.println(); bindDN = app.readValidatedInput(INFO_LDAP_CONN_PROMPT_BIND_DN .get(bindDN), callback); } catch (CLIException e) { throw ArgumentExceptionFactory .unableToReadConnectionParameters(e); } } } else { bindDN = null ; } bindPassword = secureArgsList.bindPasswordArg.getValue(); if (keyManager == null) { if (secureArgsList.bindPasswordFileArg.isPresent()) { // Read from file if it exists. bindPassword = secureArgsList.bindPasswordFileArg.getValue(); if (bindPassword == null) { throw ArgumentExceptionFactory.missingBindPassword(bindDN); } } else if (bindPassword == null || bindPassword.equals("-")) { // Read the password from the stdin. if (!app.isInteractive()) { throw ArgumentExceptionFactory .unableToReadBindPasswordInteractively(); } if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } try { app.println(); Message prompt = INFO_LDAPAUTH_PASSWORD_PROMPT.get(bindDN); bindPassword = app.readPassword(prompt); } catch (Exception e) { throw ArgumentExceptionFactory .unableToReadConnectionParameters(e); } } } } /** * Get the trust manager. * * @return The trust manager based on CLI args on interactive prompt. * @throws ArgumentException If an error occurs when getting args values. */ private ApplicationTrustManager getTrustManagerInternal() throws ArgumentException { boolean trustAll = secureArgsList.trustAllArg.isPresent(); if (app.isInteractive() && !secureArgsList.trustAllArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } try { app.println(); trustAll = app.confirmAction( INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL.get(), false); } 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 (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } 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.exists() && f.canRead() && !f.isDirectory()) { return ninput; } else { app.println(); app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH .get()); app.println(); return null; } } }; try { app.println(); truststorePath = app.readValidatedInput( INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH.get(), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // Then the truststore password. // As the most common case is to have no password for truststore, // we don't ask it in the interactive mode. String truststorePassword = secureArgsList.trustStorePasswordArg .getValue(); if (secureArgsList.trustStorePasswordFileArg.isPresent()) { // Read from file if it exists. truststorePassword = secureArgsList.trustStorePasswordFileArg .getValue(); } if ((truststorePassword != null) && (truststorePassword.equals("-"))) { // Read the password from the stdin. if (!app.isInteractive()) { truststorePassword = null; } else { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } try { app.println(); Message prompt = INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PASSWORD .get(truststorePath); truststorePassword = app.readPassword(prompt); } catch (Exception e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } } // 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.load(fos, truststorePassword.toCharArray()); } else { truststore.load(fos, null); } fos.close(); return new ApplicationTrustManager(truststore); } catch (Exception e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } /** * Get the key manager. * * @return The key manager based on CLI args on interactive prompt. * @throws ArgumentException If an error occurs when getting args values. */ private KeyManager getKeyManagerInternal() throws ArgumentException { // Do we need client side authentication ? // If one of the client side authentication args is set, we assume // that we // need client side authentication. boolean weDontKnowIfWeNeedKeystore = !(secureArgsList.keyStorePathArg .isPresent() || secureArgsList.keyStorePasswordArg.isPresent() || secureArgsList.keyStorePasswordFileArg.isPresent() || secureArgsList.certNicknameArg .isPresent()); // We don't have specific key manager parameter. // We assume that no client side authentication is required // Client side authentication is not the common use case. As a // consequence, interactive mode doesn't add an extra question // which will be in most cases useless. if (weDontKnowIfWeNeedKeystore) { return null; } // Get info about keystore. First get the keystore path. String keystorePath = secureArgsList.keyStorePathArg.getValue(); if (app.isInteractive() && !secureArgsList.keyStorePathArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<String> callback = new ValidationCallback<String>() { public String validate(ConsoleApplication app, String input) throws CLIException { String ninput = input.trim(); if (ninput.length() == 0) { return ninput; } File f = new File(ninput); if (f.exists() && f.canRead() && !f.isDirectory()) { return ninput; } else { app.println(); app.println(ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH .get()); app.println(); return null; } } }; try { app.println(); keystorePath = app.readValidatedInput( INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PATH.get(), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // Then the keystore password. String keystorePassword = secureArgsList.keyStorePasswordArg.getValue(); if (secureArgsList.keyStorePasswordFileArg.isPresent()) { // Read from file if it exists. keystorePassword = secureArgsList.keyStorePasswordFileArg.getValue(); if (keystorePassword == null) { throw ArgumentExceptionFactory.missingBindPassword(keystorePassword); } } else if (keystorePassword == null || keystorePassword.equals("-")) { // Read the password from the stdin. if (!app.isInteractive()) { throw ArgumentExceptionFactory .unableToReadBindPasswordInteractively(); } if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } try { app.println(); Message prompt = INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD .get(keystorePath); keystorePassword = app.readPassword(prompt); } catch (Exception e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // finally the certificate name, if needed. String certifNickname = secureArgsList.certNicknameArg.getValue(); if (app.isInteractive() && !secureArgsList.certNicknameArg.isPresent()) { if (!isHeadingDisplayed) { app.println(); app.println(); app.println(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); isHeadingDisplayed = true; } ValidationCallback<String> callback = new ValidationCallback<String>() { public String validate(ConsoleApplication app, String input) throws CLIException { return input.trim(); } }; try { app.println(); certifNickname = app.readValidatedInput( INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_NAME.get(), callback); } catch (CLIException e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } // We'we got all the information to get the keystore manager try { FileInputStream fos = new FileInputStream(keystorePath); KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(fos, keystorePassword.toCharArray()); fos.close(); ApplicationKeyManager akm = new ApplicationKeyManager(keystore, keystorePassword.toCharArray()); if (certifNickname.length() != 0) { return new SelectableCertificateKeyManager(akm, certifNickname); } else { return akm ; } } catch (Exception e) { throw ArgumentExceptionFactory.unableToReadConnectionParameters(e); } } /** * Indicates whether or not a connection should use SSL based on * this interaction. * * @return boolean where true means use SSL */ public boolean useSSL() { return useSSL; } /** * Indicates whether or not a connection should use StartTLS based on * this interaction. * * @return boolean where true means use StartTLS */ public boolean useStartTLS() { return useStartTLS; } /** * Gets the host name that should be used for connections based on * this interaction. * * @return host name for connections */ public String getHostName() { return hostName; } /** * Gets the port number name that should be used for connections based on * this interaction. * * @return port number for connections */ public int getPortNumber() { return portNumber; } /** * Gets the bind DN name that should be used for connections based on * this interaction. * * @return bind DN for connections */ public String getBindDN() { return this.bindDN; } /** * Gets the bind password that should be used for connections based on * this interaction. * * @return bind password for connections */ public String getBindPassword() { return this.bindPassword; } /** * Gets the trust manager that should be used for connections based on * this interaction. * * @return trust manager for connections */ public TrustManager getTrustManager() { return this.trustManager; } /** * Gets the key manager that should be used for connections based on * this interaction. * * @return key manager for connections */ public KeyManager getKeyManager() { return this.keyManager; } }