001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2007-2008 Sun Microsystems, Inc.
026     */
027    
028    package org.opends.server.admin.client.cli;
029    
030    import static org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.*;
031    import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
032    import static org.opends.server.loggers.debug.DebugLogger.getTracer;
033    import static org.opends.messages.AdminToolMessages.*;
034    import static org.opends.messages.ToolMessages.*;
035    import org.opends.messages.Message;
036    import org.opends.messages.MessageBuilder;
037    import static org.opends.server.tools.ToolConstants.*;
038    import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
039    import static org.opends.server.util.StaticUtils.wrapText;
040    
041    import java.io.File;
042    import java.io.FileInputStream;
043    import java.io.IOException;
044    import java.io.OutputStream;
045    import java.io.PrintStream;
046    import java.security.KeyStore;
047    import java.security.KeyStoreException;
048    import java.security.NoSuchAlgorithmException;
049    import java.security.cert.CertificateException;
050    import java.util.ArrayList;
051    import java.util.LinkedHashSet;
052    import java.util.logging.Level;
053    import java.util.logging.Logger;
054    
055    import javax.net.ssl.KeyManager;
056    
057    import org.opends.admin.ads.util.ApplicationKeyManager;
058    import org.opends.admin.ads.util.ApplicationTrustManager;
059    import org.opends.quicksetup.Constants;
060    import org.opends.server.loggers.debug.DebugTracer;
061    import org.opends.server.types.DebugLogLevel;
062    import org.opends.server.util.PasswordReader;
063    import org.opends.server.util.SelectableCertificateKeyManager;
064    import org.opends.server.util.args.Argument;
065    import org.opends.server.util.args.ArgumentException;
066    import org.opends.server.util.args.BooleanArgument;
067    import org.opends.server.util.args.FileBasedArgument;
068    import org.opends.server.util.args.IntegerArgument;
069    import org.opends.server.util.args.StringArgument;
070    
071    /**
072     * This is a commodity class that can be used to check the arguments required
073     * to establish a secure connection in the command line.  It can be used
074     * to generate an ApplicationTrustManager object based on the options provided
075     * by the user in the command line.
076     *
077     */
078    public final class SecureConnectionCliArgs
079    {
080      /**
081       * The 'hostName' global argument.
082       */
083      public StringArgument hostNameArg = null;
084    
085      /**
086       * The 'port' global argument.
087       */
088      public IntegerArgument portArg = null;
089    
090      /**
091       * The 'bindDN' global argument.
092       */
093      public StringArgument bindDnArg = null;
094    
095      /**
096       * The 'adminUID' global argument.
097       */
098      public StringArgument adminUidArg = null;
099    
100      /**
101       * The 'bindPasswordFile' global argument.
102       */
103      public FileBasedArgument bindPasswordFileArg = null;
104    
105      /**
106       * The 'bindPassword' global argument.
107       */
108      public StringArgument bindPasswordArg = null;
109    
110      /**
111       * The 'trustAllArg' global argument.
112       */
113      public BooleanArgument trustAllArg = null;
114    
115      /**
116       * The 'trustStore' global argument.
117       */
118      public StringArgument trustStorePathArg = null;
119    
120      /**
121       * The 'trustStorePassword' global argument.
122       */
123      public StringArgument trustStorePasswordArg = null;
124    
125      /**
126       * The 'trustStorePasswordFile' global argument.
127       */
128      public FileBasedArgument trustStorePasswordFileArg = null;
129    
130      /**
131       * The 'keyStore' global argument.
132       */
133      public StringArgument keyStorePathArg = null;
134    
135      /**
136       * The 'keyStorePassword' global argument.
137       */
138      public StringArgument keyStorePasswordArg = null;
139    
140      /**
141       * The 'keyStorePasswordFile' global argument.
142       */
143      public FileBasedArgument keyStorePasswordFileArg = null;
144    
145      /**
146       * The 'certNicknameArg' global argument.
147       */
148      public StringArgument certNicknameArg = null;
149    
150      /**
151       * The 'useSSLArg' global argument.
152       */
153      public BooleanArgument useSSLArg = null;
154    
155      /**
156       * The 'useStartTLSArg' global argument.
157       */
158      public BooleanArgument useStartTLSArg = null;
159    
160      /**
161       * Argument indicating a SASL option.
162       */
163      public StringArgument  saslOptionArg = null;
164    
165      /**
166       * Private container for global arguments.
167       */
168      private LinkedHashSet<Argument> argList = null;
169    
170      // the trust manager.
171      private ApplicationTrustManager trustManager;
172    
173      /**
174       * The tracer object for the debug logger.
175       */
176      private static final DebugTracer TRACER = getTracer();
177    
178      /**
179       * End Of Line.
180       */
181      public static String EOL = System.getProperty("line.separator");
182    
183      /**
184       * The Logger.
185       */
186      static private final Logger LOG =
187        Logger.getLogger(SecureConnectionCliArgs.class.getName());
188    
189      /**
190       * Creates a new instance of secure arguments.
191       */
192      public SecureConnectionCliArgs()
193      {
194      }
195    
196      /**
197       * Indicates whether or not any of the arguments are present.
198       *
199       * @return boolean where true indicates that at least one of the
200       *         arguments is present
201       */
202      public boolean argumentsPresent() {
203        boolean present = false;
204        if (argList != null) {
205          for (Argument arg : argList) {
206            if (arg.isPresent()) {
207              present = true;
208              break;
209            }
210          }
211        }
212        return present;
213      }
214    
215      /**
216       * Get the admin UID which has to be used for the command.
217       *
218       * @return The admin UID specified by the command line argument, or the
219       *         default value, if not specified.
220       */
221      public String getAdministratorUID()
222      {
223        if (adminUidArg.isPresent())
224        {
225          return adminUidArg.getValue();
226        }
227        else
228        {
229          return adminUidArg.getDefaultValue();
230        }
231      }
232    
233      /**
234       * Tells whether this parser uses the Administrator UID (instead of the
235       * bind DN) or not.
236       * @return <CODE>true</CODE> if this parser uses the Administrator UID and
237       * <CODE>false</CODE> otherwise.
238       */
239      public boolean useAdminUID()
240      {
241        return !adminUidArg.isHidden();
242      }
243    
244      /**
245       * Get the bindDN which has to be used for the command.
246       *
247       * @return The bindDN specified by the command line argument, or the
248       *         default value, if not specified.
249       */
250      public String getBindDN()
251      {
252        if (bindDnArg.isPresent())
253        {
254          return bindDnArg.getValue();
255        }
256        else
257        {
258          return bindDnArg.getDefaultValue();
259        }
260      }
261    
262      /**
263       * Get the password which has to be used for the command.
264       *
265       * @param dn
266       *          The user DN for which to password could be asked.
267       * @param out
268       *          The input stream to used if we have to prompt to the
269       *          user.
270       * @param err
271       *          The error stream to used if we have to prompt to the
272       *          user.
273       * @param clearArg
274       *          The password StringArgument argument.
275       * @param fileArg
276       *          The password FileBased argument.
277       * @return The password stored into the specified file on by the
278       *         command line argument, or prompts it if not specified.
279       */
280      public String getBindPassword(String dn,
281          OutputStream out, OutputStream err, StringArgument clearArg,
282          FileBasedArgument fileArg)
283      {
284        if (clearArg.isPresent())
285        {
286          String bindPasswordValue = clearArg.getValue();
287          if(bindPasswordValue != null && bindPasswordValue.equals("-"))
288          {
289            // read the password from the stdin.
290            try
291            {
292              out.write(INFO_LDAPAUTH_PASSWORD_PROMPT.get(dn).getBytes());
293              out.flush();
294              char[] pwChars = PasswordReader.readPassword();
295              bindPasswordValue = new String(pwChars);
296            } catch(Exception ex)
297            {
298              if (debugEnabled())
299              {
300                TRACER.debugCaught(DebugLogLevel.ERROR, ex);
301              }
302              try
303              {
304                err.write(wrapText(ex.getMessage(), MAX_LINE_WIDTH).getBytes());
305                err.write(EOL.getBytes());
306              }
307              catch (IOException e)
308              {
309              }
310              return null;
311            }
312          }
313          return bindPasswordValue;
314        }
315        else
316        if (fileArg.isPresent())
317        {
318          return fileArg.getValue();
319        }
320        else
321        {
322          // read the password from the stdin.
323          try
324          {
325            out.write(INFO_LDAPAUTH_PASSWORD_PROMPT.get(dn).toString().getBytes());
326            out.flush();
327            char[] pwChars = PasswordReader.readPassword();
328            return new String(pwChars);
329          }
330          catch (Exception ex)
331          {
332            if (debugEnabled())
333            {
334              TRACER.debugCaught(DebugLogLevel.ERROR, ex);
335            }
336            try
337            {
338              err.write(wrapText(ex.getMessage(), MAX_LINE_WIDTH).getBytes());
339              err.write(EOL.getBytes());
340            }
341            catch (IOException e)
342            {
343            }
344            return null;
345          }
346        }
347    
348      }
349    
350      /**
351       * Get the password which has to be used for the command.
352       *
353       * @param dn
354       *          The user DN for which to password could be asked.
355       * @param out
356       *          The input stream to used if we have to prompt to the
357       *          user.
358       * @param err
359       *          The error stream to used if we have to prompt to the
360       *          user.
361       * @return The password stored into the specified file on by the
362       *         command line argument, or prompts it if not specified.
363       */
364      public String getBindPassword(String dn, OutputStream out, OutputStream err)
365      {
366        return getBindPassword(dn, out, err, bindPasswordArg, bindPasswordFileArg);
367      }
368    
369      /**
370       * Get the password which has to be used for the command without prompting
371       * the user.  If no password was specified, return null.
372       *
373       * @param clearArg
374       *          The password StringArgument argument.
375       * @param fileArg
376       *          The password FileBased argument.
377       * @return The password stored into the specified file on by the
378       *         command line argument, or null it if not specified.
379       */
380      public String getBindPassword(StringArgument clearArg,
381          FileBasedArgument fileArg)
382      {
383        String pwd;
384        if (clearArg.isPresent())
385        {
386          pwd = clearArg.getValue();
387        }
388        else
389        if (fileArg.isPresent())
390        {
391          pwd = fileArg.getValue();
392        }
393        else
394        {
395          pwd = null;
396        }
397        return pwd;
398      }
399    
400      /**
401       * Get the password which has to be used for the command without prompting
402       * the user.  If no password was specified, return null.
403       *
404       * @return The password stored into the specified file on by the
405       *         command line argument, or null it if not specified.
406       */
407      public String getBindPassword()
408      {
409        return getBindPassword(bindPasswordArg, bindPasswordFileArg);
410      }
411    
412      /**
413       * Initialize Global option.
414       *
415       * @throws ArgumentException
416       *           If there is a problem with any of the parameters used
417       *           to create this argument.
418       * @return a ArrayList with the options created.
419       */
420      public LinkedHashSet<Argument> createGlobalArguments()
421      throws ArgumentException
422      {
423        argList = new LinkedHashSet<Argument>();
424    
425        useSSLArg = new BooleanArgument("useSSL", OPTION_SHORT_USE_SSL,
426            OPTION_LONG_USE_SSL, INFO_DESCRIPTION_USE_SSL.get());
427        useSSLArg.setPropertyName(OPTION_LONG_USE_SSL);
428        argList.add(useSSLArg);
429    
430        useStartTLSArg = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS,
431            OPTION_LONG_START_TLS,
432            INFO_DESCRIPTION_START_TLS.get());
433        useStartTLSArg.setPropertyName(OPTION_LONG_START_TLS);
434        argList.add(useStartTLSArg);
435    
436        hostNameArg = new StringArgument("host", OPTION_SHORT_HOST,
437            OPTION_LONG_HOST, false, false, true, INFO_HOST_PLACEHOLDER.get(),
438            "localhost",
439            null, INFO_DESCRIPTION_HOST.get());
440        hostNameArg.setPropertyName(OPTION_LONG_HOST);
441        argList.add(hostNameArg);
442    
443        portArg = new IntegerArgument("port", OPTION_SHORT_PORT, OPTION_LONG_PORT,
444            false, false, true, INFO_PORT_PLACEHOLDER.get(), 389, null,
445            INFO_DESCRIPTION_PORT.get());
446        portArg.setPropertyName(OPTION_LONG_PORT);
447        argList.add(portArg);
448    
449        bindDnArg = new StringArgument("bindDN", OPTION_SHORT_BINDDN,
450            OPTION_LONG_BINDDN, false, false, true, INFO_BINDDN_PLACEHOLDER.get(),
451            "cn=Directory Manager", null, INFO_DESCRIPTION_BINDDN.get());
452        bindDnArg.setPropertyName(OPTION_LONG_BINDDN);
453        argList.add(bindDnArg);
454    
455        // It is up to the classes that required admin UID to make this argument
456        // visible and add it.
457        adminUidArg = new StringArgument("adminUID", 'I',
458            "adminUID", false, false, true, INFO_ADMINUID_PLACEHOLDER.get(),
459            Constants.GLOBAL_ADMIN_UID, null,
460            INFO_DESCRIPTION_ADMIN_UID.get());
461        adminUidArg.setPropertyName("adminUID");
462        adminUidArg.setHidden(true);
463    
464        bindPasswordArg = new StringArgument("bindPassword",
465            OPTION_SHORT_BINDPWD, OPTION_LONG_BINDPWD, false, false, true,
466            INFO_BINDPWD_PLACEHOLDER.get(), null, null,
467            INFO_DESCRIPTION_BINDPASSWORD.get());
468        bindPasswordArg.setPropertyName(OPTION_LONG_BINDPWD);
469        argList.add(bindPasswordArg);
470    
471        bindPasswordFileArg = new FileBasedArgument("bindPasswordFile",
472            OPTION_SHORT_BINDPWD_FILE, OPTION_LONG_BINDPWD_FILE, false, false,
473            INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, null,
474            INFO_DESCRIPTION_BINDPASSWORDFILE.get());
475        bindPasswordFileArg.setPropertyName(OPTION_LONG_BINDPWD_FILE);
476        argList.add(bindPasswordFileArg);
477    
478        saslOptionArg = new StringArgument(
479                "sasloption", OPTION_SHORT_SASLOPTION,
480                OPTION_LONG_SASLOPTION, false,
481                true, true,
482                INFO_SASL_OPTION_PLACEHOLDER.get(), null, null,
483                INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS.get());
484        saslOptionArg.setPropertyName(OPTION_LONG_SASLOPTION);
485        argList.add(saslOptionArg);
486    
487        trustAllArg = new BooleanArgument("trustAll", OPTION_SHORT_TRUSTALL,
488            OPTION_LONG_TRUSTALL, INFO_DESCRIPTION_TRUSTALL.get());
489        trustAllArg.setPropertyName(OPTION_LONG_TRUSTALL);
490        argList.add(trustAllArg);
491    
492        trustStorePathArg = new StringArgument("trustStorePath",
493            OPTION_SHORT_TRUSTSTOREPATH, OPTION_LONG_TRUSTSTOREPATH, false,
494            false, true, INFO_TRUSTSTOREPATH_PLACEHOLDER.get(), null, null,
495            INFO_DESCRIPTION_TRUSTSTOREPATH.get());
496        trustStorePathArg.setPropertyName(OPTION_LONG_TRUSTSTOREPATH);
497        argList.add(trustStorePathArg);
498    
499        trustStorePasswordArg = new StringArgument("trustStorePassword",
500            OPTION_SHORT_TRUSTSTORE_PWD, OPTION_LONG_TRUSTSTORE_PWD, false, false,
501            true, INFO_TRUSTSTORE_PWD_PLACEHOLDER.get(), null, null,
502            INFO_DESCRIPTION_TRUSTSTOREPASSWORD.get());
503        trustStorePasswordArg.setPropertyName(OPTION_LONG_TRUSTSTORE_PWD);
504        argList.add(trustStorePasswordArg);
505    
506        trustStorePasswordFileArg = new FileBasedArgument("trustStorePasswordFile",
507            OPTION_SHORT_TRUSTSTORE_PWD_FILE, OPTION_LONG_TRUSTSTORE_PWD_FILE,
508            false, false, INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get(), null, null,
509            INFO_DESCRIPTION_TRUSTSTOREPASSWORD_FILE.get());
510        trustStorePasswordFileArg.setPropertyName(OPTION_LONG_TRUSTSTORE_PWD_FILE);
511        argList.add(trustStorePasswordFileArg);
512    
513        keyStorePathArg = new StringArgument("keyStorePath",
514            OPTION_SHORT_KEYSTOREPATH, OPTION_LONG_KEYSTOREPATH, false, false,
515            true, INFO_KEYSTOREPATH_PLACEHOLDER.get(), null, null,
516            INFO_DESCRIPTION_KEYSTOREPATH.get());
517        keyStorePathArg.setPropertyName(OPTION_LONG_KEYSTOREPATH);
518        argList.add(keyStorePathArg);
519    
520        keyStorePasswordArg = new StringArgument("keyStorePassword",
521            OPTION_SHORT_KEYSTORE_PWD,
522            OPTION_LONG_KEYSTORE_PWD, false, false, true,
523            INFO_KEYSTORE_PWD_PLACEHOLDER.get(), null, null,
524            INFO_DESCRIPTION_KEYSTOREPASSWORD.get());
525        keyStorePasswordArg.setPropertyName(OPTION_LONG_KEYSTORE_PWD);
526        argList.add(keyStorePasswordArg);
527    
528        keyStorePasswordFileArg = new FileBasedArgument("keystorePasswordFile",
529            OPTION_SHORT_KEYSTORE_PWD_FILE, OPTION_LONG_KEYSTORE_PWD_FILE, false,
530            false, INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get(), null, null,
531            INFO_DESCRIPTION_KEYSTOREPASSWORD_FILE.get());
532        keyStorePasswordFileArg.setPropertyName(OPTION_LONG_KEYSTORE_PWD_FILE);
533        argList.add(keyStorePasswordFileArg);
534    
535        certNicknameArg = new StringArgument("certNickname",
536            OPTION_SHORT_CERT_NICKNAME, OPTION_LONG_CERT_NICKNAME,
537            false, false, true, INFO_NICKNAME_PLACEHOLDER.get(), null, null,
538            INFO_DESCRIPTION_CERT_NICKNAME.get());
539        certNicknameArg.setPropertyName(OPTION_LONG_CERT_NICKNAME);
540        argList.add(certNicknameArg);
541    
542        return argList;
543      }
544    
545      /**
546       * Get the host name which has to be used for the command.
547       *
548       * @return The host name specified by the command line argument, or
549       *         the default value, if not specified.
550       */
551      public String getHostName()
552      {
553        if (hostNameArg.isPresent())
554        {
555          return hostNameArg.getValue();
556        }
557        else
558        {
559          return hostNameArg.getDefaultValue();
560        }
561      }
562    
563      /**
564       * Get the port which has to be used for the command.
565       *
566       * @return The port specified by the command line argument, or the
567       *         default value, if not specified.
568       */
569      public String getPort()
570      {
571        if (portArg.isPresent())
572        {
573          return portArg.getValue();
574        }
575        else
576        {
577          return portArg.getDefaultValue();
578        }
579      }
580    
581      /**
582       * Indication if provided global options are validate.
583       *
584       * @param buf the MessageBuilder to write the error messages.
585       * @return return code.
586       */
587      public int validateGlobalOptions(MessageBuilder buf)
588      {
589        ArrayList<Message> errors = new ArrayList<Message>();
590        // Couldn't have at the same time bindPassword and bindPasswordFile
591        if (bindPasswordArg.isPresent() && bindPasswordFileArg.isPresent()) {
592          Message message = ERR_TOOL_CONFLICTING_ARGS.get(
593                  bindPasswordArg.getLongIdentifier(),
594                  bindPasswordFileArg.getLongIdentifier());
595          errors.add(message);
596        }
597    
598        // Couldn't have at the same time trustAll and
599        // trustStore related arg
600        if (trustAllArg.isPresent() && trustStorePathArg.isPresent()) {
601          Message message = ERR_TOOL_CONFLICTING_ARGS.get(
602                  trustAllArg.getLongIdentifier(),
603                  trustStorePathArg.getLongIdentifier());
604          errors.add(message);
605        }
606        if (trustAllArg.isPresent() && trustStorePasswordArg.isPresent()) {
607          Message message = ERR_TOOL_CONFLICTING_ARGS.get(
608                  trustAllArg.getLongIdentifier(),
609                  trustStorePasswordArg.getLongIdentifier());
610          errors.add(message);
611        }
612        if (trustAllArg.isPresent() && trustStorePasswordFileArg.isPresent()) {
613          Message message = ERR_TOOL_CONFLICTING_ARGS.get(
614                  trustAllArg.getLongIdentifier(),
615                  trustStorePasswordFileArg.getLongIdentifier());
616          errors.add(message);
617        }
618    
619        // Couldn't have at the same time trustStorePasswordArg and
620        // trustStorePasswordFileArg
621        if (trustStorePasswordArg.isPresent()
622                && trustStorePasswordFileArg.isPresent()) {
623          Message message = ERR_TOOL_CONFLICTING_ARGS.get(
624                  trustStorePasswordArg.getLongIdentifier(),
625                  trustStorePasswordFileArg.getLongIdentifier());
626          errors.add(message);
627        }
628    
629        if (trustStorePathArg.isPresent())
630        {
631          // Check that the path exists and is readable
632          String value = trustStorePathArg.getValue();
633          if (!canRead(trustStorePathArg.getValue()))
634          {
635            Message message = ERR_CANNOT_READ_TRUSTSTORE.get(
636                value);
637            errors.add(message);
638          }
639        }
640    
641        if (keyStorePathArg.isPresent())
642        {
643          // Check that the path exists and is readable
644          String value = keyStorePathArg.getValue();
645          if (!canRead(trustStorePathArg.getValue()))
646          {
647            Message message = ERR_CANNOT_READ_KEYSTORE.get(
648                value);
649            errors.add(message);
650          }
651        }
652    
653        // Couldn't have at the same time startTLSArg and
654        // useSSLArg
655        if (useStartTLSArg.isPresent()
656                && useSSLArg.isPresent()) {
657          Message message = ERR_TOOL_CONFLICTING_ARGS.get(
658                  useStartTLSArg
659                          .getLongIdentifier(), useSSLArg.getLongIdentifier());
660          errors.add(message);
661        }
662        if (errors.size() > 0)
663        {
664          for (Message error : errors)
665          {
666            if (buf.length() > 0)
667            {
668              buf.append(EOL);
669            }
670            buf.append(error);
671          }
672          return CONFLICTING_ARGS.getReturnCode();
673        }
674    
675        return SUCCESSFUL_NOP.getReturnCode();
676      }
677      /**
678       * Indication if provided global options are validate.
679       *
680       * @param err the stream to be used to print error message.
681       * @return return code.
682       */
683      public int validateGlobalOptions(PrintStream err)
684      {
685        MessageBuilder buf = new MessageBuilder();
686        int returnValue = validateGlobalOptions(buf);
687        if (buf.length() > 0)
688        {
689          err.println(wrapText(buf.toString(), MAX_LINE_WIDTH));
690        }
691        return returnValue;
692      }
693    
694    
695      /**
696       * Indicate if the SSL mode is required.
697       *
698       * @return True if SSL mode is required
699       */
700      public boolean useSSL()
701      {
702        if (useSSLArg.isPresent())
703        {
704          return true;
705        }
706        else
707        {
708          return false ;
709        }
710      }
711    
712      /**
713       * Indicate if the startTLS mode is required.
714       *
715       * @return True if startTLS mode is required
716       */
717      public boolean useStartTLS()
718      {
719        if (useStartTLSArg.isPresent())
720        {
721          return true;
722        }
723        else
724        {
725          return false ;
726        }
727      }
728    
729      /**
730       * Handle TrustStore.
731       *
732       * @return The trustStore manager to be used for the command.
733       */
734      public ApplicationTrustManager getTrustManager()
735      {
736        if (trustManager == null)
737        {
738          KeyStore truststore = null ;
739          if (trustAllArg.isPresent())
740          {
741            // Running a null TrustManager  will force createLdapsContext and
742            // createStartTLSContext to use a bindTrustManager.
743            return null ;
744          }
745          else
746            if (trustStorePathArg.isPresent())
747            {
748              try
749              {
750                FileInputStream fos =
751                  new FileInputStream(trustStorePathArg.getValue());
752                String trustStorePasswordStringValue = null;
753                char[] trustStorePasswordValue = null;
754                if (trustStorePasswordArg.isPresent())
755                {
756                  trustStorePasswordStringValue = trustStorePasswordArg.getValue();
757                }
758                else if (trustStorePasswordFileArg.isPresent())
759                {
760                  trustStorePasswordStringValue =
761                    trustStorePasswordFileArg.getValue();
762                }
763    
764                if (trustStorePasswordStringValue !=  null)
765                {
766                  trustStorePasswordStringValue = System
767                  .getProperty("javax.net.ssl.trustStorePassword");
768                }
769    
770    
771                if (trustStorePasswordStringValue !=  null)
772                {
773                  trustStorePasswordValue =
774                    trustStorePasswordStringValue.toCharArray();
775                }
776    
777                truststore = KeyStore.getInstance(KeyStore.getDefaultType());
778                truststore.load(fos, trustStorePasswordValue);
779                fos.close();
780              }
781              catch (KeyStoreException e)
782              {
783                // Nothing to do: if this occurs we will systematically refuse the
784                // certificates.  Maybe we should avoid this and be strict, but we
785                // are in a best effort mode.
786                LOG.log(Level.WARNING, "Error with the truststore", e);
787              }
788              catch (NoSuchAlgorithmException e)
789              {
790                // Nothing to do: if this occurs we will systematically refuse the
791                // certificates.  Maybe we should avoid this and be strict, but we
792                // are in a best effort mode.
793                LOG.log(Level.WARNING, "Error with the truststore", e);
794              }
795              catch (CertificateException e)
796              {
797                // Nothing to do: if this occurs we will systematically refuse the
798                // certificates.  Maybe we should avoid this and be strict, but we
799                // are in a best effort mode.
800                LOG.log(Level.WARNING, "Error with the truststore", e);
801              }
802              catch (IOException e)
803              {
804                // Nothing to do: if this occurs we will systematically refuse the
805                // certificates.  Maybe we should avoid this and be strict, but we
806                // are in a best effort mode.
807                LOG.log(Level.WARNING, "Error with the truststore", e);
808              }
809            }
810          trustManager = new ApplicationTrustManager(truststore);
811        }
812        return trustManager;
813      }
814    
815      /**
816       * Handle KeyStore.
817       *
818       * @return The keyStore manager to be used for the command.
819       */
820      public KeyManager getKeyManager()
821      {
822        KeyStore keyStore = null;
823        String keyStorePasswordStringValue = null;
824        char[] keyStorePasswordValue = null;
825        if (keyStorePathArg.isPresent())
826        {
827          try
828          {
829            FileInputStream fos = new FileInputStream(keyStorePathArg.getValue());
830            if (keyStorePasswordArg.isPresent())
831            {
832              keyStorePasswordStringValue = keyStorePasswordArg.getValue();
833            }
834            else if (keyStorePasswordFileArg.isPresent())
835            {
836              keyStorePasswordStringValue = keyStorePasswordFileArg.getValue();
837            }
838            if (keyStorePasswordStringValue != null)
839            {
840              keyStorePasswordValue = keyStorePasswordStringValue.toCharArray();
841            }
842    
843            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
844            keyStore.load(fos,keyStorePasswordValue);
845            fos.close();
846          }
847          catch (KeyStoreException e)
848          {
849            // Nothing to do: if this occurs we will systematically refuse
850            // the
851            // certificates. Maybe we should avoid this and be strict, but
852            // we are in a best effort mode.
853            LOG.log(Level.WARNING, "Error with the keystore", e);
854          }
855          catch (NoSuchAlgorithmException e)
856          {
857            // Nothing to do: if this occurs we will systematically refuse
858            // the
859            // certificates. Maybe we should avoid this and be strict, but
860            // we are
861            // in a best effort mode.
862            LOG.log(Level.WARNING, "Error with the keystore", e);
863          }
864          catch (CertificateException e)
865          {
866            // Nothing to do: if this occurs we will systematically refuse
867            // the
868            // certificates. Maybe we should avoid this and be strict, but
869            // we are
870            // in a best effort mode.
871            LOG.log(Level.WARNING, "Error with the keystore", e);
872          }
873          catch (IOException e)
874          {
875            // Nothing to do: if this occurs we will systematically refuse
876            // the
877            // certificates. Maybe we should avoid this and be strict, but
878            // we are
879            // in a best effort mode.
880            LOG.log(Level.WARNING, "Error with the keystore", e);
881          }
882          char[] password = null;
883          if (keyStorePasswordStringValue != null)
884          {
885            password = keyStorePasswordStringValue.toCharArray();
886          }
887          ApplicationKeyManager akm = new ApplicationKeyManager(keyStore,password);
888          if (certNicknameArg.isPresent())
889          {
890            return new SelectableCertificateKeyManager(akm, certNicknameArg
891                .getValue());
892          }
893          else
894          {
895            return akm;
896          }
897        }
898        else
899        {
900          return null;
901        }
902      }
903    
904      /**
905       * Returns <CODE>true</CODE> if we can read on the provided path and
906       * <CODE>false</CODE> otherwise.
907       * @param path the path.
908       * @return <CODE>true</CODE> if we can read on the provided path and
909       * <CODE>false</CODE> otherwise.
910       */
911      private boolean canRead(String path)
912      {
913        boolean canRead;
914        File file = new File(path);
915        if (file.exists())
916        {
917          canRead = file.canRead();
918        }
919        else
920        {
921          canRead = false;
922        }
923        return canRead;
924      }
925    }