/* * 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 legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * 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 legal-notices/CDDLv1_0.txt. * 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 * * * Copyright 2007-2010 Sun Microsystems, Inc. * Portions Copyright 2014-2015 ForgeRock AS */ package org.opends.server.admin.client.cli; import static com.forgerock.opendj.cli.CliMessages.*; import static com.forgerock.opendj.cli.ReturnCode.*; import static com.forgerock.opendj.cli.Utils.*; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.Collection; import java.util.Set; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.LocalizableMessageBuilder; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.opends.admin.ads.util.ApplicationTrustManager; import com.forgerock.opendj.cli.Argument; import com.forgerock.opendj.cli.ArgumentException; import com.forgerock.opendj.cli.ArgumentGroup; import com.forgerock.opendj.cli.BooleanArgument; import com.forgerock.opendj.cli.ClientException; import com.forgerock.opendj.cli.CommonArguments; import com.forgerock.opendj.cli.ConsoleApplication; import com.forgerock.opendj.cli.FileBasedArgument; import com.forgerock.opendj.cli.StringArgument; import com.forgerock.opendj.cli.SubCommandArgumentParser; /** * This is a commodity class that can be used to check the arguments required to * establish a secure connection in the command line. It can be used to generate * an ApplicationTrustManager object based on the options provided by the user * in the command line. */ public abstract class SecureConnectionCliParser extends SubCommandArgumentParser { /** * Logger. */ private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** * The 'showUsage' global argument. */ protected BooleanArgument showUsageArg; /** * The 'verbose' global argument. */ protected BooleanArgument verboseArg; /** * The secure args list object. */ protected SecureConnectionCliArgs secureArgsList ; /** * Argument indicating a properties file argument. */ protected StringArgument propertiesFileArg; /** * The argument which should be used to indicate that we will not * look for properties file. */ protected BooleanArgument noPropertiesFileArg; /** * Creates a new instance of this argument parser with no arguments. * * @param mainClassName * The fully-qualified name of the Java class that should * be invoked to launch the program with which this * argument parser is associated. * @param toolDescription * A human-readable description for the tool, which will be * included when displaying usage information. * @param longArgumentsCaseSensitive * Indicates whether subcommand and long argument names * should be treated in a case-sensitive manner. */ protected SecureConnectionCliParser(String mainClassName, LocalizableMessage toolDescription, boolean longArgumentsCaseSensitive) { super(mainClassName, toolDescription, longArgumentsCaseSensitive); } /** * Get the bindDN which has to be used for the command. * * @return The bindDN specified by the command line argument, or the * default value, if not specified. */ public String getBindDN() { return secureArgsList.getBindDN(); } /** * Returns the Administrator UID provided in the command-line. * @return the Administrator UID provided in the command-line. */ public String getAdministratorUID() { return secureArgsList.getAdministratorUID(); } /** * Get the password which has to be used for the command. * * @param dn * The user DN for which to password could be asked. * @param out * The input stream to used if we have to prompt to the * user. * @param err * The error stream to used if we have to prompt to the * user. * @param pwdArg * The password StringArgument argument. * @param fileArg * The password FileBased argument. * @return The password stored into the specified file on by the * command line argument, or prompts it if not specified. */ protected String getBindPassword(String dn, OutputStream out, OutputStream err, StringArgument pwdArg, FileBasedArgument fileArg) { if (fileArg.isPresent()) { return fileArg.getValue(); } String bindPasswordValue = pwdArg.isPresent() ? pwdArg.getValue() : null; if (bindPasswordValue == null || "-".equals(bindPasswordValue)) { // Read the password from the STDin. try { return readPassword(dn, out); } catch (Exception ex) { logger.traceException(ex); try { err.write(wrapText(ex.getMessage(), MAX_LINE_WIDTH).getBytes()); err.write(LINE_SEPARATOR.getBytes()); } catch (IOException e) { // Nothing to do. } } } return bindPasswordValue; } private String readPassword(String dn, OutputStream out) throws IOException, ClientException { out.write(INFO_LDAPAUTH_PASSWORD_PROMPT.get(dn).toString().getBytes()); out.flush(); char[] pwChars = ConsoleApplication.readPassword(); return new String(pwChars); } /** * Gets the password which has to be used for the command. * * @param dn * The user DN for which to password could be asked. * @param out * The input stream to used if we have to prompt to the * user. * @param err * The error stream to used if we have to prompt to the * user. * @return The password stored into the specified file on by the * command line argument, or prompts it if not specified. */ public String getBindPassword(String dn, OutputStream out, OutputStream err) { return getBindPassword(dn, out, err, secureArgsList.bindPasswordArg, secureArgsList.bindPasswordFileArg); } /** * Gets the password which has to be used for the command without prompting * the user. If no password was specified, return null. * * @return The password stored into the specified file on by the * command line argument, or null it if not specified. */ public String getBindPassword() { return getBindPassword(secureArgsList.bindPasswordArg, secureArgsList.bindPasswordFileArg); } /** * Initialize Global option. * * @param outStream * The output stream used for the usage. * @param alwaysSSL If true, always use the SSL connection type. In this case, * the arguments useSSL and startTLS are not present. * * @throws ArgumentException * If there is a problem with any of the parameters used * to create this argument. * @return a ArrayList with the options created. */ protected Set<Argument> createGlobalArguments(OutputStream outStream, boolean alwaysSSL) throws ArgumentException { secureArgsList = new SecureConnectionCliArgs(alwaysSSL); Set<Argument> set = secureArgsList.createGlobalArguments(); showUsageArg = CommonArguments.getShowUsage(); setUsageArgument(showUsageArg, outStream); set.add(showUsageArg); verboseArg = CommonArguments.getVerbose(); set.add(verboseArg); propertiesFileArg = CommonArguments.getPropertiesFile(); setFilePropertiesArgument(propertiesFileArg); set.add(propertiesFileArg); noPropertiesFileArg = CommonArguments.getNoPropertiesFile(); setNoPropertiesFileArgument(noPropertiesFileArg); set.add(noPropertiesFileArg); return set; } /** * Initialize the global options with the provided set of arguments. * @param args the arguments to use to initialize the global options. * @throws ArgumentException if there is a conflict with the provided * arguments. */ protected void initializeGlobalArguments(Collection<Argument> args) throws ArgumentException { initializeGlobalArguments(args, null); } /** * Initialize the global options with the provided set of arguments. * @param args the arguments to use to initialize the global options. * @param argGroup to which args will be added * @throws ArgumentException if there is a conflict with the provided * arguments. */ protected void initializeGlobalArguments( Collection<Argument> args, ArgumentGroup argGroup) throws ArgumentException { for (Argument arg : args) { addGlobalArgument(arg, argGroup); } // Set the propertiesFile argument setFilePropertiesArgument(propertiesFileArg); } /** * Get the host name which has to be used for the command. * * @return The host name specified by the command line argument, or * the default value, if not specified. */ public String getHostName() { return secureArgsList.getHostName(); } /** * Get the port which has to be used for the command. * * @return The port specified by the command line argument, or the * default value, if not specified. */ public String getPort() { return secureArgsList.getPort(); } /** * Indication if provided global options are validate. * * @param buf the LocalizableMessageBuilder to write the error messages. * @return return code. */ public int validateGlobalOptions(LocalizableMessageBuilder buf) { int ret = secureArgsList.validateGlobalOptions(buf) ; // Couldn't have at the same time properties file arg and // propertiesFileArg if (noPropertiesFileArg.isPresent() && propertiesFileArg.isPresent()) { LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get( noPropertiesFileArg.getLongIdentifier(), propertiesFileArg .getLongIdentifier()); if (buf.length() > 0) { buf.append(LINE_SEPARATOR); } buf.append(message); return CONFLICTING_ARGS.get(); } return ret; } /** * Indication if provided global options are validate. * * @param err the stream to be used to print error message. * @return return code. */ public int validateGlobalOptions(PrintStream err) { LocalizableMessageBuilder buf = new LocalizableMessageBuilder(); int returnValue = validateGlobalOptions(buf); printWrappedText(err, buf.toString()); return returnValue; } /** * Indicate if the verbose mode is required. * * @return True if verbose mode is required */ public boolean isVerbose() { return verboseArg.isPresent(); } /** * Indicate if the SSL mode is required. * * @return True if SSL mode is required */ public boolean useSSL() { return secureArgsList.useSSL(); } /** * Indicate if the startTLS mode is required. * * @return True if startTLS mode is required */ public boolean useStartTLS() { return secureArgsList.useStartTLS(); } /** * Handle TrustStore. * * @return The trustStore manager to be used for the command. */ public ApplicationTrustManager getTrustManager() { return secureArgsList.getTrustManager(); } /** * Returns the timeout to be used to connect in milliseconds. The method * must be called after parsing the arguments. * @return the timeout to be used to connect in milliseconds. Returns * {@code 0} if there is no timeout. * @throws IllegalStateException if the method is called before * parsing the arguments. */ public int getConnectTimeout()throws IllegalStateException { try { return secureArgsList.connectTimeoutArg.getIntValue(); } catch (ArgumentException ae) { throw new IllegalStateException("Argument parser is not parsed: "+ae, ae); } } }