001/* 002 * Copyright 2017-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2017-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2017-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.util.ssl.cert; 037 038 039 040import java.io.BufferedInputStream; 041import java.io.BufferedReader; 042import java.io.ByteArrayInputStream; 043import java.io.File; 044import java.io.FileInputStream; 045import java.io.FileOutputStream; 046import java.io.InputStream; 047import java.io.InputStreamReader; 048import java.io.IOException; 049import java.io.OutputStream; 050import java.io.PrintStream; 051import java.nio.file.Files; 052import java.net.InetAddress; 053import java.security.Key; 054import java.security.KeyPair; 055import java.security.KeyStore; 056import java.security.PrivateKey; 057import java.security.Provider; 058import java.security.PublicKey; 059import java.security.UnrecoverableKeyException; 060import java.security.cert.Certificate; 061import java.text.SimpleDateFormat; 062import java.util.ArrayList; 063import java.util.Arrays; 064import java.util.Collections; 065import java.util.Date; 066import java.util.Enumeration; 067import java.util.Iterator; 068import java.util.LinkedHashMap; 069import java.util.LinkedHashSet; 070import java.util.List; 071import java.util.Map; 072import java.util.Set; 073import java.util.concurrent.LinkedBlockingQueue; 074import java.util.concurrent.TimeUnit; 075import java.util.concurrent.atomic.AtomicReference; 076 077import com.unboundid.asn1.ASN1BitString; 078import com.unboundid.asn1.ASN1Element; 079import com.unboundid.ldap.sdk.DN; 080import com.unboundid.ldap.sdk.LDAPConnectionOptions; 081import com.unboundid.ldap.sdk.LDAPException; 082import com.unboundid.ldap.sdk.ResultCode; 083import com.unboundid.ldap.sdk.Version; 084import com.unboundid.util.Base64; 085import com.unboundid.util.BouncyCastleFIPSHelper; 086import com.unboundid.util.ByteStringBuffer; 087import com.unboundid.util.CommandLineTool; 088import com.unboundid.util.CryptoHelper; 089import com.unboundid.util.Debug; 090import com.unboundid.util.NotNull; 091import com.unboundid.util.Nullable; 092import com.unboundid.util.OID; 093import com.unboundid.util.ObjectPair; 094import com.unboundid.util.PasswordReader; 095import com.unboundid.util.PropertyManager; 096import com.unboundid.util.StaticUtils; 097import com.unboundid.util.ThreadSafety; 098import com.unboundid.util.ThreadSafetyLevel; 099import com.unboundid.util.Validator; 100import com.unboundid.util.args.ArgumentException; 101import com.unboundid.util.args.ArgumentParser; 102import com.unboundid.util.args.BooleanArgument; 103import com.unboundid.util.args.BooleanValueArgument; 104import com.unboundid.util.args.DNArgument; 105import com.unboundid.util.args.FileArgument; 106import com.unboundid.util.args.IA5StringArgumentValueValidator; 107import com.unboundid.util.args.IPAddressArgumentValueValidator; 108import com.unboundid.util.args.IntegerArgument; 109import com.unboundid.util.args.OIDArgumentValueValidator; 110import com.unboundid.util.args.StringArgument; 111import com.unboundid.util.args.TimestampArgument; 112import com.unboundid.util.args.SubCommand; 113import com.unboundid.util.ssl.JVMDefaultTrustManager; 114import com.unboundid.util.ssl.PKCS11KeyManager; 115 116import static com.unboundid.util.ssl.cert.CertMessages.*; 117 118 119 120/** 121 * This class provides a tool that can be used to manage X.509 certificates for 122 * use in TLS communication. 123 */ 124@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 125public final class ManageCertificates 126 extends CommandLineTool 127{ 128 /** 129 * The path to the keystore with the JVM's set of default trusted issuer 130 * certificates. 131 */ 132 @Nullable private static final File JVM_DEFAULT_CACERTS_FILE; 133 static 134 { 135 File caCertsFile; 136 try 137 { 138 caCertsFile = JVMDefaultTrustManager.getInstance().getCACertsFile(); 139 } 140 catch (final Exception e) 141 { 142 Debug.debugException(e); 143 caCertsFile = null; 144 } 145 146 JVM_DEFAULT_CACERTS_FILE = caCertsFile; 147 } 148 149 150 151 /** 152 * The name of the keystore type that should be used for the Bouncy Castle 153 * FIPS-compliant keystore. 154 */ 155 @NotNull private static final String BCFKS_KEYSTORE_TYPE = 156 BouncyCastleFIPSHelper.FIPS_KEY_STORE_TYPE; 157 158 159 160 /** 161 * The name of the BCFKS keystore type, formatted in all lowercase. 162 */ 163 @NotNull private static final String BCFKS_KEYSTORE_TYPE_LC = 164 BCFKS_KEYSTORE_TYPE.toLowerCase(); 165 166 167 168 /** 169 * The name of a system property that can be used to specify the default 170 * keystore type for new keystores. 171 */ 172 @NotNull private static final String PROPERTY_DEFAULT_KEYSTORE_TYPE = 173 ManageCertificates.class.getName() + ".defaultKeystoreType"; 174 175 176 177 /** 178 * The default keystore type that will be used for new keystores when the 179 * type is not specified. 180 */ 181 @NotNull private static final String DEFAULT_KEYSTORE_TYPE; 182 static 183 { 184 final String propertyValue = 185 PropertyManager.get(PROPERTY_DEFAULT_KEYSTORE_TYPE); 186 if (CryptoHelper.usingFIPSMode() || 187 ((propertyValue != null) && propertyValue.equalsIgnoreCase( 188 BCFKS_KEYSTORE_TYPE))) 189 { 190 DEFAULT_KEYSTORE_TYPE = BCFKS_KEYSTORE_TYPE; 191 } 192 else if ((propertyValue != null) && 193 (propertyValue.equalsIgnoreCase("PKCS12") || 194 propertyValue.equalsIgnoreCase("PKCS#12") || 195 propertyValue.equalsIgnoreCase("PKCS #12") || 196 propertyValue.equalsIgnoreCase("PKCS 12"))) 197 { 198 DEFAULT_KEYSTORE_TYPE = CryptoHelper.KEY_STORE_TYPE_PKCS_12; 199 } 200 else 201 { 202 DEFAULT_KEYSTORE_TYPE = CryptoHelper.KEY_STORE_TYPE_JKS; 203 } 204 } 205 206 207 208 /** 209 * The column at which to wrap long lines of output. 210 */ 211 private static final int WRAP_COLUMN = StaticUtils.TERMINAL_WIDTH_COLUMNS - 1; 212 213 214 215 /** 216 * The set of values that will be allowed for the keystore type argument. 217 */ 218 @NotNull private static final Set<String> ALLOWED_KEYSTORE_TYPE_VALUES = 219 StaticUtils.setOf("jks", 220 "pkcs11", "pkcs 11", "pkcs#11", "pkcs #11", 221 "pkcs12", "pkcs 12", "pkcs#12", "pkcs #12", 222 BCFKS_KEYSTORE_TYPE_LC); 223 224 225 226 // The global argument parser used by this tool. 227 @Nullable private volatile ArgumentParser globalParser = null; 228 229 // The argument parser for the selected subcommand. 230 @Nullable private volatile ArgumentParser subCommandParser = null; 231 232 // The input stream to use for standard input. 233 @NotNull private final InputStream in; 234 235 236 237 /** 238 * Invokes this tool with the default standard output and standard error and 239 * the provided set of arguments. 240 * 241 * @param args The command-line arguments provided to this program. 242 */ 243 public static void main(@NotNull final String... args) 244 { 245 final ResultCode resultCode = main(System.in, System.out, System.err, args); 246 if (resultCode != ResultCode.SUCCESS) 247 { 248 System.exit(Math.max(1, Math.min(resultCode.intValue(), 255))); 249 } 250 } 251 252 253 254 /** 255 * Invokes this tool with the provided output and error streams and set of 256 * arguments. 257 * 258 * @param in The input stream to use for standard input. It may be 259 * {@code null} if no input stream should be available. 260 * @param out The output stream to use for standard output. It may be 261 * {@code null} if standard output should be suppressed. 262 * @param err The output stream to use for standard error. It may be 263 * {@code null} if standard error should be suppressed. 264 * @param args The command-line arguments provided to this program. 265 * 266 * @return The result code obtained from tool processing. 267 */ 268 @NotNull() 269 public static ResultCode main(@Nullable final InputStream in, 270 @Nullable final OutputStream out, 271 @Nullable final OutputStream err, 272 @NotNull final String... args) 273 { 274 final ManageCertificates manageCertificates = 275 new ManageCertificates(in, out, err); 276 return manageCertificates.runTool(args); 277 } 278 279 280 281 /** 282 * Creates a new instance of this tool with the provided output and error 283 * streams. Standard input will bot be available. 284 * 285 * @param out The output stream to use for standard output. It may be 286 * {@code null} if standard output should be suppressed. 287 * @param err The output stream to use for standard error. It may be 288 * {@code null} if standard error should be suppressed. 289 */ 290 public ManageCertificates(@Nullable final OutputStream out, 291 @Nullable final OutputStream err) 292 { 293 this(null, out, err); 294 } 295 296 297 298 /** 299 * Creates a new instance of this tool with the provided output and error 300 * streams. 301 * 302 * @param in The input stream to use for standard input. It may be 303 * {@code null} if no input stream should be available. 304 * @param out The output stream to use for standard output. It may be 305 * {@code null} if standard output should be suppressed. 306 * @param err The output stream to use for standard error. It may be 307 * {@code null} if standard error should be suppressed. 308 */ 309 public ManageCertificates(@Nullable final InputStream in, 310 @Nullable final OutputStream out, 311 @Nullable final OutputStream err) 312 { 313 super(out, err); 314 315 if (in == null) 316 { 317 this.in = new ByteArrayInputStream(StaticUtils.NO_BYTES); 318 } 319 else 320 { 321 this.in = in; 322 } 323 } 324 325 326 327 /** 328 * Retrieves the name of this tool. It should be the name of the command used 329 * to invoke this tool. 330 * 331 * @return The name for this tool. 332 */ 333 @Override() 334 @NotNull() 335 public String getToolName() 336 { 337 return "manage-certificates"; 338 } 339 340 341 342 /** 343 * Retrieves a human-readable description for this tool. 344 * 345 * @return A human-readable description for this tool. 346 */ 347 @Override() 348 @NotNull() 349 public String getToolDescription() 350 { 351 return INFO_MANAGE_CERTS_TOOL_DESC.get(); 352 } 353 354 355 356 /** 357 * Retrieves a version string for this tool, if available. 358 * 359 * @return A version string for this tool, or {@code null} if none is 360 * available. 361 */ 362 @Override() 363 @NotNull() 364 public String getToolVersion() 365 { 366 return Version.NUMERIC_VERSION_STRING; 367 } 368 369 370 371 /** 372 * Indicates whether this tool should provide support for an interactive mode, 373 * in which the tool offers a mode in which the arguments can be provided in 374 * a text-driven menu rather than requiring them to be given on the command 375 * line. If interactive mode is supported, it may be invoked using the 376 * "--interactive" argument. Alternately, if interactive mode is supported 377 * and {@link #defaultsToInteractiveMode()} returns {@code true}, then 378 * interactive mode may be invoked by simply launching the tool without any 379 * arguments. 380 * 381 * @return {@code true} if this tool supports interactive mode, or 382 * {@code false} if not. 383 */ 384 @Override() 385 public boolean supportsInteractiveMode() 386 { 387 return true; 388 } 389 390 391 392 /** 393 * Indicates whether this tool defaults to launching in interactive mode if 394 * the tool is invoked without any command-line arguments. This will only be 395 * used if {@link #supportsInteractiveMode()} returns {@code true}. 396 * 397 * @return {@code true} if this tool defaults to using interactive mode if 398 * launched without any command-line arguments, or {@code false} if 399 * not. 400 */ 401 @Override() 402 public boolean defaultsToInteractiveMode() 403 { 404 return true; 405 } 406 407 408 409 /** 410 * Indicates whether this tool supports the use of a properties file for 411 * specifying default values for arguments that aren't specified on the 412 * command line. 413 * 414 * @return {@code true} if this tool supports the use of a properties file 415 * for specifying default values for arguments that aren't specified 416 * on the command line, or {@code false} if not. 417 */ 418 @Override() 419 public boolean supportsPropertiesFile() 420 { 421 return true; 422 } 423 424 425 426 /** 427 * Indicates whether this tool should provide arguments for redirecting output 428 * to a file. If this method returns {@code true}, then the tool will offer 429 * an "--outputFile" argument that will specify the path to a file to which 430 * all standard output and standard error content will be written, and it will 431 * also offer a "--teeToStandardOut" argument that can only be used if the 432 * "--outputFile" argument is present and will cause all output to be written 433 * to both the specified output file and to standard output. 434 * 435 * @return {@code true} if this tool should provide arguments for redirecting 436 * output to a file, or {@code false} if not. 437 */ 438 @Override() 439 protected boolean supportsOutputFile() 440 { 441 return false; 442 } 443 444 445 446 /** 447 * {@inheritDoc} 448 */ 449 @Override() 450 protected boolean supportsDebugLogging() 451 { 452 return true; 453 } 454 455 456 457 /** 458 * Indicates whether to log messages about the launch and completion of this 459 * tool into the invocation log of Ping Identity server products that may 460 * include it. This method is not needed for tools that are not expected to 461 * be part of the Ping Identity server products suite. Further, this value 462 * may be overridden by settings in the server's 463 * tool-invocation-logging.properties file. 464 * <BR><BR> 465 * This method should generally return {@code true} for tools that may alter 466 * the server configuration, data, or other state information, and 467 * {@code false} for tools that do not make any changes. 468 * 469 * @return {@code true} if Ping Identity server products should include 470 * messages about the launch and completion of this tool in tool 471 * invocation log files by default, or {@code false} if not. 472 */ 473 @Override() 474 protected boolean logToolInvocationByDefault() 475 { 476 return true; 477 } 478 479 480 481 /** 482 * Adds the command-line arguments supported for use with this tool to the 483 * provided argument parser. The tool may need to retain references to the 484 * arguments (and/or the argument parser, if trailing arguments are allowed) 485 * to it in order to obtain their values for use in later processing. 486 * 487 * @param parser The argument parser to which the arguments are to be added. 488 * 489 * @throws ArgumentException If a problem occurs while adding any of the 490 * tool-specific arguments to the provided 491 * argument parser. 492 */ 493 @Override() 494 public void addToolArguments(@NotNull final ArgumentParser parser) 495 throws ArgumentException 496 { 497 globalParser = parser; 498 499 500 // Define the "list-certificates" subcommand and all of its arguments. 501 final ArgumentParser listCertsParser = new ArgumentParser( 502 "list-certificates", INFO_MANAGE_CERTS_SC_LIST_CERTS_DESC.get()); 503 504 final FileArgument listCertsKeystore = new FileArgument(null, "keystore", 505 (JVM_DEFAULT_CACERTS_FILE == null), 1, null, 506 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_DESC.get(), true, true, true, 507 false); 508 listCertsKeystore.addLongIdentifier("keystore-path", true); 509 listCertsKeystore.addLongIdentifier("keystorePath", true); 510 listCertsKeystore.addLongIdentifier("keystore-file", true); 511 listCertsKeystore.addLongIdentifier("keystoreFile", true); 512 listCertsParser.addArgument(listCertsKeystore); 513 514 if (JVM_DEFAULT_CACERTS_FILE != null) 515 { 516 final BooleanArgument listCertsUseJVMDefault = new BooleanArgument(null, 517 "use-jvm-default-trust-store", 1, 518 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_JVM_DEFAULT_DESC.get( 519 JVM_DEFAULT_CACERTS_FILE.getAbsolutePath())); 520 listCertsUseJVMDefault.addLongIdentifier("useJVMDefaultTrustStore", true); 521 listCertsUseJVMDefault.addLongIdentifier("jvm-default", true); 522 listCertsUseJVMDefault.addLongIdentifier("jvmDefault", true); 523 listCertsParser.addArgument(listCertsUseJVMDefault); 524 525 listCertsParser.addRequiredArgumentSet(listCertsUseJVMDefault, 526 listCertsKeystore); 527 listCertsParser.addExclusiveArgumentSet(listCertsUseJVMDefault, 528 listCertsKeystore); 529 } 530 531 final StringArgument listCertsKeystorePassword = new StringArgument(null, 532 "keystore-password", false, 1, 533 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 534 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_PW_DESC.get()); 535 listCertsKeystorePassword.addLongIdentifier("keystorePassword", true); 536 listCertsKeystorePassword.addLongIdentifier("keystore-passphrase", true); 537 listCertsKeystorePassword.addLongIdentifier("keystorePassphrase", true); 538 listCertsKeystorePassword.addLongIdentifier("keystore-pin", true); 539 listCertsKeystorePassword.addLongIdentifier("keystorePIN", true); 540 listCertsKeystorePassword.addLongIdentifier("storepass", true); 541 listCertsKeystorePassword.setSensitive(true); 542 listCertsParser.addArgument(listCertsKeystorePassword); 543 544 final FileArgument listCertsKeystorePasswordFile = new FileArgument(null, 545 "keystore-password-file", false, 1, null, 546 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_PW_FILE_DESC.get(), true, true, 547 true, false); 548 listCertsKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 549 true); 550 listCertsKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 551 true); 552 listCertsKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 553 true); 554 listCertsKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 555 true); 556 listCertsKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 557 listCertsParser.addArgument(listCertsKeystorePasswordFile); 558 559 final BooleanArgument listCertsPromptForKeystorePassword = 560 new BooleanArgument(null, "prompt-for-keystore-password", 561 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_PROMPT_FOR_KS_PW_DESC.get()); 562 listCertsPromptForKeystorePassword.addLongIdentifier( 563 "promptForKeystorePassword", true); 564 listCertsPromptForKeystorePassword.addLongIdentifier( 565 "prompt-for-keystore-passphrase", true); 566 listCertsPromptForKeystorePassword.addLongIdentifier( 567 "promptForKeystorePassphrase", true); 568 listCertsPromptForKeystorePassword.addLongIdentifier( 569 "prompt-for-keystore-pin", true); 570 listCertsPromptForKeystorePassword.addLongIdentifier( 571 "promptForKeystorePIN", true); 572 listCertsParser.addArgument(listCertsPromptForKeystorePassword); 573 574 final StringArgument listCertsKeystoreType = new StringArgument(null, 575 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 576 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_TYPE_DESC.get(), 577 ALLOWED_KEYSTORE_TYPE_VALUES); 578 listCertsKeystoreType.addLongIdentifier("key-store-type", true); 579 listCertsKeystoreType.addLongIdentifier("keystoreType", true); 580 listCertsKeystoreType.addLongIdentifier("keystore-format", true); 581 listCertsKeystoreType.addLongIdentifier("key-store-format", true); 582 listCertsKeystoreType.addLongIdentifier("keystoreFormat", true); 583 listCertsKeystoreType.addLongIdentifier("storetype", true); 584 listCertsParser.addArgument(listCertsKeystoreType); 585 586 final StringArgument listCertsAlias = new StringArgument(null, "alias", 587 false, 0, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 588 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_ALIAS_DESC.get()); 589 listCertsAlias.addLongIdentifier("nickname", true); 590 listCertsParser.addArgument(listCertsAlias); 591 592 final BooleanArgument listCertsDisplayPEM = new BooleanArgument(null, 593 "display-pem-certificate", 1, 594 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_DISPLAY_PEM_DESC.get()); 595 listCertsDisplayPEM.addLongIdentifier("displayPEMCertificate", true); 596 listCertsDisplayPEM.addLongIdentifier("display-pem", true); 597 listCertsDisplayPEM.addLongIdentifier("displayPEM", true); 598 listCertsDisplayPEM.addLongIdentifier("show-pem-certificate", true); 599 listCertsDisplayPEM.addLongIdentifier("showPEMCertificate", true); 600 listCertsDisplayPEM.addLongIdentifier("show-pem", true); 601 listCertsDisplayPEM.addLongIdentifier("showPEM", true); 602 listCertsDisplayPEM.addLongIdentifier("pem", true); 603 listCertsDisplayPEM.addLongIdentifier("rfc", true); 604 listCertsParser.addArgument(listCertsDisplayPEM); 605 606 final BooleanArgument listCertsVerbose = new BooleanArgument(null, 607 "verbose", 1, INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_VERBOSE_DESC.get()); 608 listCertsParser.addArgument(listCertsVerbose); 609 610 final BooleanArgument listCertsDisplayCommand = new BooleanArgument(null, 611 "display-keytool-command", 1, 612 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_DISPLAY_COMMAND_DESC.get()); 613 listCertsDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 614 listCertsDisplayCommand.addLongIdentifier("show-keytool-command", true); 615 listCertsDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 616 listCertsParser.addArgument(listCertsDisplayCommand); 617 618 listCertsParser.addExclusiveArgumentSet(listCertsKeystorePassword, 619 listCertsKeystorePasswordFile, listCertsPromptForKeystorePassword); 620 621 final LinkedHashMap<String[],String> listCertsExamples = 622 new LinkedHashMap<>(StaticUtils.computeMapCapacity(3)); 623 listCertsExamples.put( 624 new String[] 625 { 626 "list-certificates", 627 "--keystore", getPlatformSpecificPath("config", "keystore") 628 }, 629 INFO_MANAGE_CERTS_SC_LIST_CERTS_EXAMPLE_1.get( 630 getPlatformSpecificPath("config", "keystore"))); 631 listCertsExamples.put( 632 new String[] 633 { 634 "list-certificates", 635 "--keystore", getPlatformSpecificPath("config", "keystore.p12"), 636 "--keystore-password-file", 637 getPlatformSpecificPath("config", "keystore.pin"), 638 "--alias", "server-cert", 639 "--verbose", 640 "--display-pem-certificate", 641 "--display-keytool-command" 642 }, 643 INFO_MANAGE_CERTS_SC_LIST_CERTS_EXAMPLE_2.get( 644 getPlatformSpecificPath("config", "keystore.p12"), 645 getPlatformSpecificPath("config", "keystore.pin"))); 646 if (JVM_DEFAULT_CACERTS_FILE != null) 647 { 648 listCertsExamples.put( 649 new String[] 650 { 651 "list-certificates", 652 "--use-jvm-default-trust-store" 653 }, 654 INFO_MANAGE_CERTS_SC_LIST_CERTS_EXAMPLE_3.get()); 655 } 656 657 final SubCommand listCertsSubCommand = new SubCommand("list-certificates", 658 INFO_MANAGE_CERTS_SC_LIST_CERTS_DESC.get(), listCertsParser, 659 listCertsExamples); 660 listCertsSubCommand.addName("listCertificates", true); 661 listCertsSubCommand.addName("list-certs", true); 662 listCertsSubCommand.addName("listCerts", true); 663 listCertsSubCommand.addName("list", true); 664 665 parser.addSubCommand(listCertsSubCommand); 666 667 668 // Define the "export-certificate" subcommand and all of its arguments. 669 final ArgumentParser exportCertParser = new ArgumentParser( 670 "export-certificate", INFO_MANAGE_CERTS_SC_EXPORT_CERT_DESC.get()); 671 672 final FileArgument exportCertKeystore = new FileArgument(null, "keystore", 673 (JVM_DEFAULT_CACERTS_FILE == null), 1, null, 674 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_KS_DESC.get(), true, true, true, 675 false); 676 exportCertKeystore.addLongIdentifier("keystore-path", true); 677 exportCertKeystore.addLongIdentifier("keystorePath", true); 678 exportCertKeystore.addLongIdentifier("keystore-file", true); 679 exportCertKeystore.addLongIdentifier("keystoreFile", true); 680 exportCertParser.addArgument(exportCertKeystore); 681 682 if (JVM_DEFAULT_CACERTS_FILE != null) 683 { 684 final BooleanArgument exportCertUseJVMDefault = new BooleanArgument(null, 685 "use-jvm-default-trust-store", 1, 686 INFO_MANAGE_CERTS_SC_EXPORT_CERTS_ARG_JVM_DEFAULT_DESC.get( 687 JVM_DEFAULT_CACERTS_FILE.getAbsolutePath())); 688 exportCertUseJVMDefault.addLongIdentifier("useJVMDefaultTrustStore", 689 true); 690 exportCertUseJVMDefault.addLongIdentifier("jvm-default", true); 691 exportCertUseJVMDefault.addLongIdentifier("jvmDefault", true); 692 exportCertParser.addArgument(exportCertUseJVMDefault); 693 694 exportCertParser.addRequiredArgumentSet(exportCertUseJVMDefault, 695 exportCertKeystore); 696 exportCertParser.addExclusiveArgumentSet(exportCertUseJVMDefault, 697 exportCertKeystore); 698 } 699 700 final StringArgument exportCertKeystorePassword = new StringArgument(null, 701 "keystore-password", false, 1, 702 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 703 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_KS_PW_DESC.get()); 704 exportCertKeystorePassword.addLongIdentifier("keystorePassword", true); 705 exportCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 706 exportCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 707 exportCertKeystorePassword.addLongIdentifier("keystore-pin", true); 708 exportCertKeystorePassword.addLongIdentifier("keystorePIN", true); 709 exportCertKeystorePassword.addLongIdentifier("storepass", true); 710 exportCertKeystorePassword.setSensitive(true); 711 exportCertParser.addArgument(exportCertKeystorePassword); 712 713 final FileArgument exportCertKeystorePasswordFile = new FileArgument(null, 714 "keystore-password-file", false, 1, null, 715 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 716 true, false); 717 exportCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 718 true); 719 exportCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 720 true); 721 exportCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 722 true); 723 exportCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 724 true); 725 exportCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 726 exportCertParser.addArgument(exportCertKeystorePasswordFile); 727 728 final BooleanArgument exportCertPromptForKeystorePassword = 729 new BooleanArgument(null, "prompt-for-keystore-password", 730 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 731 exportCertPromptForKeystorePassword.addLongIdentifier( 732 "promptForKeystorePassword", true); 733 exportCertPromptForKeystorePassword.addLongIdentifier( 734 "prompt-for-keystore-passphrase", true); 735 exportCertPromptForKeystorePassword.addLongIdentifier( 736 "promptForKeystorePassphrase", true); 737 exportCertPromptForKeystorePassword.addLongIdentifier( 738 "prompt-for-keystore-pin", true); 739 exportCertPromptForKeystorePassword.addLongIdentifier( 740 "promptForKeystorePIN", true); 741 exportCertParser.addArgument(exportCertPromptForKeystorePassword); 742 743 final StringArgument exportCertKeystoreType = new StringArgument(null, 744 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 745 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_KS_TYPE_DESC.get(), 746 ALLOWED_KEYSTORE_TYPE_VALUES); 747 exportCertKeystoreType.addLongIdentifier("key-store-type", true); 748 exportCertKeystoreType.addLongIdentifier("keystoreType", true); 749 exportCertKeystoreType.addLongIdentifier("keystore-format", true); 750 exportCertKeystoreType.addLongIdentifier("key-store-format", true); 751 exportCertKeystoreType.addLongIdentifier("keystoreFormat", true); 752 exportCertKeystoreType.addLongIdentifier("storetype", true); 753 exportCertParser.addArgument(exportCertKeystoreType); 754 755 final StringArgument exportCertAlias = new StringArgument(null, "alias", 756 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 757 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_ALIAS_DESC.get()); 758 exportCertAlias.addLongIdentifier("nickname", true); 759 exportCertParser.addArgument(exportCertAlias); 760 761 final BooleanArgument exportCertChain = new BooleanArgument(null, 762 "export-certificate-chain", 1, 763 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_CHAIN_DESC.get()); 764 exportCertChain.addLongIdentifier("exportCertificateChain", true); 765 exportCertChain.addLongIdentifier("export-chain", true); 766 exportCertChain.addLongIdentifier("exportChain", true); 767 exportCertChain.addLongIdentifier("certificate-chain", true); 768 exportCertChain.addLongIdentifier("certificateChain", true); 769 exportCertChain.addLongIdentifier("chain", true); 770 exportCertParser.addArgument(exportCertChain); 771 772 final Set<String> exportCertOutputFormatAllowedValues = StaticUtils.setOf( 773 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 774 final StringArgument exportCertOutputFormat = new StringArgument(null, 775 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 776 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_FORMAT_DESC.get(), 777 exportCertOutputFormatAllowedValues, "PEM"); 778 exportCertOutputFormat.addLongIdentifier("outputFormat", true); 779 exportCertParser.addArgument(exportCertOutputFormat); 780 781 final FileArgument exportCertOutputFile = new FileArgument(null, 782 "output-file", false, 1, null, 783 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_FILE_DESC.get(), false, true, 784 true, false); 785 exportCertOutputFile.addLongIdentifier("outputFile", true); 786 exportCertOutputFile.addLongIdentifier("export-file", true); 787 exportCertOutputFile.addLongIdentifier("exportFile", true); 788 exportCertOutputFile.addLongIdentifier("certificate-file", true); 789 exportCertOutputFile.addLongIdentifier("certificateFile", true); 790 exportCertOutputFile.addLongIdentifier("file", true); 791 exportCertOutputFile.addLongIdentifier("filename", true); 792 exportCertParser.addArgument(exportCertOutputFile); 793 794 final BooleanArgument exportCertSeparateFile = new BooleanArgument(null, 795 "separate-file-per-certificate", 1, 796 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_SEPARATE_FILE_DESC.get()); 797 exportCertSeparateFile.addLongIdentifier("separateFilePerCertificate", 798 true); 799 exportCertSeparateFile.addLongIdentifier("separate-files", true); 800 exportCertSeparateFile.addLongIdentifier("separateFiles", true); 801 exportCertParser.addArgument(exportCertSeparateFile); 802 803 final BooleanArgument exportCertDisplayCommand = new BooleanArgument(null, 804 "display-keytool-command", 1, 805 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 806 exportCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 807 exportCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 808 exportCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 809 exportCertParser.addArgument(exportCertDisplayCommand); 810 811 exportCertParser.addExclusiveArgumentSet(exportCertKeystorePassword, 812 exportCertKeystorePasswordFile, exportCertPromptForKeystorePassword); 813 exportCertParser.addDependentArgumentSet(exportCertSeparateFile, 814 exportCertChain); 815 exportCertParser.addDependentArgumentSet(exportCertSeparateFile, 816 exportCertOutputFile); 817 818 final LinkedHashMap<String[],String> exportCertExamples = 819 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 820 exportCertExamples.put( 821 new String[] 822 { 823 "export-certificate", 824 "--keystore", getPlatformSpecificPath("config", "keystore"), 825 "--alias", "server-cert" 826 }, 827 INFO_MANAGE_CERTS_SC_EXPORT_CERT_EXAMPLE_1.get()); 828 exportCertExamples.put( 829 new String[] 830 { 831 "export-certificate", 832 "--keystore", getPlatformSpecificPath("config", "keystore.p12"), 833 "--keystore-password-file", 834 getPlatformSpecificPath("config", "keystore.pin"), 835 "--alias", "server-cert", 836 "--export-certificate-chain", 837 "--output-format", "DER", 838 "--output-file", "certificate-chain.der", 839 "--display-keytool-command" 840 }, 841 INFO_MANAGE_CERTS_SC_EXPORT_CERT_EXAMPLE_2.get()); 842 843 final SubCommand exportCertSubCommand = new SubCommand("export-certificate", 844 INFO_MANAGE_CERTS_SC_EXPORT_CERT_DESC.get(), exportCertParser, 845 exportCertExamples); 846 exportCertSubCommand.addName("exportCertificate", true); 847 exportCertSubCommand.addName("export-cert", true); 848 exportCertSubCommand.addName("exportCert", true); 849 exportCertSubCommand.addName("export", true); 850 851 parser.addSubCommand(exportCertSubCommand); 852 853 854 // Define the "export-private-key" subcommand and all of its arguments. 855 final ArgumentParser exportKeyParser = new ArgumentParser( 856 "export-private-key", INFO_MANAGE_CERTS_SC_EXPORT_KEY_DESC.get()); 857 858 final FileArgument exportKeyKeystore = new FileArgument(null, "keystore", 859 true, 1, null, INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_KS_DESC.get(), 860 true, true, true, false); 861 exportKeyKeystore.addLongIdentifier("keystore-path", true); 862 exportKeyKeystore.addLongIdentifier("keystorePath", true); 863 exportKeyKeystore.addLongIdentifier("keystore-file", true); 864 exportKeyKeystore.addLongIdentifier("keystoreFile", true); 865 exportKeyParser.addArgument(exportKeyKeystore); 866 867 final StringArgument exportKeyKeystorePassword = new StringArgument(null, 868 "keystore-password", false, 1, 869 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 870 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_KS_PW_DESC.get()); 871 exportKeyKeystorePassword.addLongIdentifier("keystorePassword", true); 872 exportKeyKeystorePassword.addLongIdentifier("keystore-passphrase", true); 873 exportKeyKeystorePassword.addLongIdentifier("keystorePassphrase", true); 874 exportKeyKeystorePassword.addLongIdentifier("keystore-pin", true); 875 exportKeyKeystorePassword.addLongIdentifier("keystorePIN", true); 876 exportKeyKeystorePassword.addLongIdentifier("storepass", true); 877 exportKeyKeystorePassword.setSensitive(true); 878 exportKeyParser.addArgument(exportKeyKeystorePassword); 879 880 final FileArgument exportKeyKeystorePasswordFile = new FileArgument(null, 881 "keystore-password-file", false, 1, null, 882 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_KS_PW_FILE_DESC.get(), true, true, 883 true, false); 884 exportKeyKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 885 true); 886 exportKeyKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 887 true); 888 exportKeyKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 889 true); 890 exportKeyKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 891 true); 892 exportKeyKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 893 exportKeyParser.addArgument(exportKeyKeystorePasswordFile); 894 895 final BooleanArgument exportKeyPromptForKeystorePassword = 896 new BooleanArgument(null, "prompt-for-keystore-password", 897 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PROMPT_FOR_KS_PW_DESC.get()); 898 exportKeyPromptForKeystorePassword.addLongIdentifier( 899 "promptForKeystorePassword", true); 900 exportKeyPromptForKeystorePassword.addLongIdentifier( 901 "prompt-for-keystore-passphrase", true); 902 exportKeyPromptForKeystorePassword.addLongIdentifier( 903 "promptForKeystorePassphrase", true); 904 exportKeyPromptForKeystorePassword.addLongIdentifier( 905 "prompt-for-keystore-pin", true); 906 exportKeyPromptForKeystorePassword.addLongIdentifier( 907 "promptForKeystorePIN", true); 908 exportKeyParser.addArgument(exportKeyPromptForKeystorePassword); 909 910 final StringArgument exportKeyPKPassword = new StringArgument(null, 911 "private-key-password", false, 1, 912 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 913 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PK_PW_DESC.get()); 914 exportKeyPKPassword.addLongIdentifier("privateKeyPassword", true); 915 exportKeyPKPassword.addLongIdentifier("private-key-passphrase", true); 916 exportKeyPKPassword.addLongIdentifier("privateKeyPassphrase", true); 917 exportKeyPKPassword.addLongIdentifier("private-key-pin", true); 918 exportKeyPKPassword.addLongIdentifier("privateKeyPIN", true); 919 exportKeyPKPassword.addLongIdentifier("key-password", true); 920 exportKeyPKPassword.addLongIdentifier("keyPassword", true); 921 exportKeyPKPassword.addLongIdentifier("key-passphrase", true); 922 exportKeyPKPassword.addLongIdentifier("keyPassphrase", true); 923 exportKeyPKPassword.addLongIdentifier("key-pin", true); 924 exportKeyPKPassword.addLongIdentifier("keyPIN", true); 925 exportKeyPKPassword.addLongIdentifier("keypass", true); 926 exportKeyPKPassword.setSensitive(true); 927 exportKeyParser.addArgument(exportKeyPKPassword); 928 929 final FileArgument exportKeyPKPasswordFile = new FileArgument(null, 930 "private-key-password-file", false, 1, null, 931 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PK_PW_FILE_DESC.get(), true, true, 932 true, false); 933 exportKeyPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 934 exportKeyPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 935 true); 936 exportKeyPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 937 true); 938 exportKeyPKPasswordFile.addLongIdentifier("private-key-pin-file", 939 true); 940 exportKeyPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 941 exportKeyPKPasswordFile.addLongIdentifier("key-password-file", true); 942 exportKeyPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 943 exportKeyPKPasswordFile.addLongIdentifier("key-passphrase-file", 944 true); 945 exportKeyPKPasswordFile.addLongIdentifier("keyPassphraseFile", 946 true); 947 exportKeyPKPasswordFile.addLongIdentifier("key-pin-file", 948 true); 949 exportKeyPKPasswordFile.addLongIdentifier("keyPINFile", true); 950 exportKeyParser.addArgument(exportKeyPKPasswordFile); 951 952 final BooleanArgument exportKeyPromptForPKPassword = 953 new BooleanArgument(null, "prompt-for-private-key-password", 954 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PROMPT_FOR_PK_PW_DESC.get()); 955 exportKeyPromptForPKPassword.addLongIdentifier( 956 "promptForPrivateKeyPassword", true); 957 exportKeyPromptForPKPassword.addLongIdentifier( 958 "prompt-for-private-key-passphrase", true); 959 exportKeyPromptForPKPassword.addLongIdentifier( 960 "promptForPrivateKeyPassphrase", true); 961 exportKeyPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 962 true); 963 exportKeyPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 964 true); 965 exportKeyPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 966 true); 967 exportKeyPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 968 true); 969 exportKeyPromptForPKPassword.addLongIdentifier( 970 "prompt-for-key-passphrase", true); 971 exportKeyPromptForPKPassword.addLongIdentifier( 972 "promptForKeyPassphrase", true); 973 exportKeyPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 974 exportKeyPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 975 exportKeyParser.addArgument(exportKeyPromptForPKPassword); 976 977 final StringArgument exportKeyKeystoreType = new StringArgument(null, 978 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 979 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_KS_TYPE_DESC.get(), 980 ALLOWED_KEYSTORE_TYPE_VALUES); 981 exportKeyKeystoreType.addLongIdentifier("key-store-type", true); 982 exportKeyKeystoreType.addLongIdentifier("keystoreType", true); 983 exportKeyKeystoreType.addLongIdentifier("keystore-format", true); 984 exportKeyKeystoreType.addLongIdentifier("key-store-format", true); 985 exportKeyKeystoreType.addLongIdentifier("keystoreFormat", true); 986 exportKeyKeystoreType.addLongIdentifier("storetype", true); 987 exportKeyParser.addArgument(exportKeyKeystoreType); 988 989 final StringArgument exportKeyAlias = new StringArgument(null, "alias", 990 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 991 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_ALIAS_DESC.get()); 992 exportKeyAlias.addLongIdentifier("nickname", true); 993 exportKeyParser.addArgument(exportKeyAlias); 994 995 final Set<String> exportKeyOutputFormatAllowedValues = StaticUtils.setOf( 996 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 997 final StringArgument exportKeyOutputFormat = new StringArgument(null, 998 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 999 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_FORMAT_DESC.get(), 1000 exportKeyOutputFormatAllowedValues, "PEM"); 1001 exportKeyOutputFormat.addLongIdentifier("outputFormat", true); 1002 exportKeyParser.addArgument(exportKeyOutputFormat); 1003 1004 final FileArgument exportKeyOutputFile = new FileArgument(null, 1005 "output-file", false, 1, null, 1006 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_FILE_DESC.get(), false, true, 1007 true, false); 1008 exportKeyOutputFile.addLongIdentifier("outputFile", true); 1009 exportKeyOutputFile.addLongIdentifier("export-file", true); 1010 exportKeyOutputFile.addLongIdentifier("exportFile", true); 1011 exportKeyOutputFile.addLongIdentifier("private-key-file", true); 1012 exportKeyOutputFile.addLongIdentifier("privateKeyFile", true); 1013 exportKeyOutputFile.addLongIdentifier("key-file", true); 1014 exportKeyOutputFile.addLongIdentifier("keyFile", true); 1015 exportKeyOutputFile.addLongIdentifier("file", true); 1016 exportKeyOutputFile.addLongIdentifier("filename", true); 1017 exportKeyParser.addArgument(exportKeyOutputFile); 1018 1019 final StringArgument exportKeyEncryptionPassword = new StringArgument(null, 1020 "encryption-password", false, 1, 1021 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1022 INFO_MANAGE_CERTS_SC_EXPIRT_KEY_ARG_ENC_PW_DESC.get()); 1023 exportKeyEncryptionPassword.addLongIdentifier("encryptionPassword", true); 1024 exportKeyParser.addArgument(exportKeyEncryptionPassword); 1025 1026 final FileArgument exportKeyEncryptionPasswordFile = new FileArgument(null, 1027 "encryption-password-file", false, 1, null, 1028 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_ENC_PW_FILE_DESC.get(), true, true, 1029 true, false); 1030 exportKeyEncryptionPasswordFile.addLongIdentifier("encryptionPasswordFile", 1031 true); 1032 exportKeyParser.addArgument(exportKeyEncryptionPasswordFile); 1033 1034 final BooleanArgument exportKeyPromptForEncryptionPassword = 1035 new BooleanArgument(null, "prompt-for-encryption-password", 1, 1036 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PROMPT_FOR_ENC_PW.get()); 1037 exportKeyPromptForEncryptionPassword.addLongIdentifier( 1038 "promptForEncryptionPassword", true); 1039 exportKeyParser.addArgument(exportKeyPromptForEncryptionPassword); 1040 1041 exportKeyParser.addRequiredArgumentSet(exportKeyKeystorePassword, 1042 exportKeyKeystorePasswordFile, exportKeyPromptForKeystorePassword); 1043 exportKeyParser.addExclusiveArgumentSet(exportKeyKeystorePassword, 1044 exportKeyKeystorePasswordFile, exportKeyPromptForKeystorePassword); 1045 exportKeyParser.addExclusiveArgumentSet(exportKeyPKPassword, 1046 exportKeyPKPasswordFile, exportKeyPromptForPKPassword); 1047 exportKeyParser.addExclusiveArgumentSet(exportKeyEncryptionPassword, 1048 exportKeyEncryptionPasswordFile, exportKeyPromptForEncryptionPassword); 1049 1050 final LinkedHashMap<String[],String> exportKeyExamples = 1051 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 1052 exportKeyExamples.put( 1053 new String[] 1054 { 1055 "export-private-key", 1056 "--keystore", getPlatformSpecificPath("config", "keystore"), 1057 "--keystore-password-file", 1058 getPlatformSpecificPath("config", "keystore.pin"), 1059 "--alias", "server-cert" 1060 }, 1061 INFO_MANAGE_CERTS_SC_EXPORT_KEY_EXAMPLE_1.get()); 1062 exportKeyExamples.put( 1063 new String[] 1064 { 1065 "export-private-key", 1066 "--keystore", getPlatformSpecificPath("config", "keystore.p12"), 1067 "--keystore-password-file", 1068 getPlatformSpecificPath("config", "keystore.pin"), 1069 "--private-key-password-file", 1070 getPlatformSpecificPath("config", "server-cert-key.pin"), 1071 "--alias", "server-cert", 1072 "--output-format", "DER", 1073 "--output-file", "server-cert-key.der" 1074 }, 1075 INFO_MANAGE_CERTS_SC_EXPORT_KEY_EXAMPLE_2.get()); 1076 1077 final SubCommand exportKeySubCommand = new SubCommand("export-private-key", 1078 INFO_MANAGE_CERTS_SC_EXPORT_CERT_DESC.get(), exportKeyParser, 1079 exportKeyExamples); 1080 exportKeySubCommand.addName("exportPrivateKey", true); 1081 exportKeySubCommand.addName("export-key", true); 1082 exportKeySubCommand.addName("exportKey", true); 1083 1084 parser.addSubCommand(exportKeySubCommand); 1085 1086 1087 // Define the "import-certificate" subcommand and all of its arguments. 1088 final ArgumentParser importCertParser = new ArgumentParser( 1089 "import-certificate", INFO_MANAGE_CERTS_SC_IMPORT_CERT_DESC.get()); 1090 1091 final FileArgument importCertKeystore = new FileArgument(null, "keystore", 1092 true, 1, null, INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KS_DESC.get(), 1093 false, true, true, false); 1094 importCertKeystore.addLongIdentifier("keystore-path", true); 1095 importCertKeystore.addLongIdentifier("keystorePath", true); 1096 importCertKeystore.addLongIdentifier("keystore-file", true); 1097 importCertKeystore.addLongIdentifier("keystoreFile", true); 1098 importCertParser.addArgument(importCertKeystore); 1099 1100 final StringArgument importCertKeystorePassword = new StringArgument(null, 1101 "keystore-password", false, 1, 1102 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1103 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KS_PW_DESC.get()); 1104 importCertKeystorePassword.addLongIdentifier("keystorePassword", true); 1105 importCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 1106 importCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 1107 importCertKeystorePassword.addLongIdentifier("keystore-pin", true); 1108 importCertKeystorePassword.addLongIdentifier("keystorePIN", true); 1109 importCertKeystorePassword.addLongIdentifier("storepass", true); 1110 importCertKeystorePassword.setSensitive(true); 1111 importCertParser.addArgument(importCertKeystorePassword); 1112 1113 final FileArgument importCertKeystorePasswordFile = new FileArgument(null, 1114 "keystore-password-file", false, 1, null, 1115 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 1116 true, false); 1117 importCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 1118 true); 1119 importCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 1120 true); 1121 importCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 1122 true); 1123 importCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 1124 true); 1125 importCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 1126 importCertParser.addArgument(importCertKeystorePasswordFile); 1127 1128 final BooleanArgument importCertPromptForKeystorePassword = 1129 new BooleanArgument(null, "prompt-for-keystore-password", 1130 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 1131 importCertPromptForKeystorePassword.addLongIdentifier( 1132 "promptForKeystorePassword", true); 1133 importCertPromptForKeystorePassword.addLongIdentifier( 1134 "prompt-for-keystore-passphrase", true); 1135 importCertPromptForKeystorePassword.addLongIdentifier( 1136 "promptForKeystorePassphrase", true); 1137 importCertPromptForKeystorePassword.addLongIdentifier( 1138 "prompt-for-keystore-pin", true); 1139 importCertPromptForKeystorePassword.addLongIdentifier( 1140 "promptForKeystorePIN", true); 1141 importCertParser.addArgument(importCertPromptForKeystorePassword); 1142 1143 final StringArgument importCertKeystoreType = new StringArgument(null, 1144 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 1145 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KS_TYPE_DESC.get(), 1146 ALLOWED_KEYSTORE_TYPE_VALUES); 1147 importCertKeystoreType.addLongIdentifier("key-store-type", true); 1148 importCertKeystoreType.addLongIdentifier("keystoreType", true); 1149 importCertKeystoreType.addLongIdentifier("keystore-format", true); 1150 importCertKeystoreType.addLongIdentifier("key-store-format", true); 1151 importCertKeystoreType.addLongIdentifier("keystoreFormat", true); 1152 importCertKeystoreType.addLongIdentifier("storetype", true); 1153 importCertParser.addArgument(importCertKeystoreType); 1154 1155 final StringArgument importCertAlias = new StringArgument(null, "alias", 1156 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 1157 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_ALIAS_DESC.get()); 1158 importCertAlias.addLongIdentifier("nickname", true); 1159 importCertParser.addArgument(importCertAlias); 1160 1161 final FileArgument importCertCertificateFile = new FileArgument(null, 1162 "certificate-file", true, 0, null, 1163 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_CERT_FILE_DESC.get(), true, true, 1164 true, false); 1165 importCertCertificateFile.addLongIdentifier("certificateFile", true); 1166 importCertCertificateFile.addLongIdentifier("certificate-chain-file", true); 1167 importCertCertificateFile.addLongIdentifier("certificateChainFile", true); 1168 importCertCertificateFile.addLongIdentifier("input-file", true); 1169 importCertCertificateFile.addLongIdentifier("inputFile", true); 1170 importCertCertificateFile.addLongIdentifier("import-file", true); 1171 importCertCertificateFile.addLongIdentifier("importFile", true); 1172 importCertCertificateFile.addLongIdentifier("file", true); 1173 importCertCertificateFile.addLongIdentifier("filename", true); 1174 importCertParser.addArgument(importCertCertificateFile); 1175 1176 final FileArgument importCertPKFile = new FileArgument(null, 1177 "private-key-file", false, 1, null, 1178 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KEY_FILE_DESC.get(), true, true, 1179 true, false); 1180 importCertPKFile.addLongIdentifier("privateKeyFile", true); 1181 importCertPKFile.addLongIdentifier("key-file", true); 1182 importCertPKFile.addLongIdentifier("keyFile", true); 1183 importCertParser.addArgument(importCertPKFile); 1184 1185 final StringArgument importCertPKPassword = new StringArgument(null, 1186 "private-key-password", false, 1, 1187 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1188 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PK_PW_DESC.get()); 1189 importCertPKPassword.addLongIdentifier("privateKeyPassword", true); 1190 importCertPKPassword.addLongIdentifier("private-key-passphrase", true); 1191 importCertPKPassword.addLongIdentifier("privateKeyPassphrase", true); 1192 importCertPKPassword.addLongIdentifier("private-key-pin", true); 1193 importCertPKPassword.addLongIdentifier("privateKeyPIN", true); 1194 importCertPKPassword.addLongIdentifier("key-password", true); 1195 importCertPKPassword.addLongIdentifier("keyPassword", true); 1196 importCertPKPassword.addLongIdentifier("key-passphrase", true); 1197 importCertPKPassword.addLongIdentifier("keyPassphrase", true); 1198 importCertPKPassword.addLongIdentifier("key-pin", true); 1199 importCertPKPassword.addLongIdentifier("keyPIN", true); 1200 importCertPKPassword.addLongIdentifier("keypass", true); 1201 importCertPKPassword.setSensitive(true); 1202 importCertParser.addArgument(importCertPKPassword); 1203 1204 final FileArgument importCertPKPasswordFile = new FileArgument(null, 1205 "private-key-password-file", false, 1, null, 1206 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PK_PW_FILE_DESC.get(), true, true, 1207 true, false); 1208 importCertPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 1209 importCertPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 1210 true); 1211 importCertPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 1212 true); 1213 importCertPKPasswordFile.addLongIdentifier("private-key-pin-file", 1214 true); 1215 importCertPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 1216 importCertPKPasswordFile.addLongIdentifier("key-password-file", true); 1217 importCertPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 1218 importCertPKPasswordFile.addLongIdentifier("key-passphrase-file", 1219 true); 1220 importCertPKPasswordFile.addLongIdentifier("keyPassphraseFile", 1221 true); 1222 importCertPKPasswordFile.addLongIdentifier("key-pin-file", 1223 true); 1224 importCertPKPasswordFile.addLongIdentifier("keyPINFile", true); 1225 importCertParser.addArgument(importCertPKPasswordFile); 1226 1227 final BooleanArgument importCertPromptForPKPassword = 1228 new BooleanArgument(null, "prompt-for-private-key-password", 1229 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PROMPT_FOR_PK_PW_DESC.get()); 1230 importCertPromptForPKPassword.addLongIdentifier( 1231 "promptForPrivateKeyPassword", true); 1232 importCertPromptForPKPassword.addLongIdentifier( 1233 "prompt-for-private-key-passphrase", true); 1234 importCertPromptForPKPassword.addLongIdentifier( 1235 "promptForPrivateKeyPassphrase", true); 1236 importCertPromptForPKPassword.addLongIdentifier( 1237 "prompt-for-private-key-pin", true); 1238 importCertPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 1239 true); 1240 importCertPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 1241 true); 1242 importCertPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 1243 true); 1244 importCertPromptForPKPassword.addLongIdentifier( 1245 "prompt-for-key-passphrase", true); 1246 importCertPromptForPKPassword.addLongIdentifier( 1247 "promptForKeyPassphrase", true); 1248 importCertPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 1249 importCertPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 1250 importCertParser.addArgument(importCertPromptForPKPassword); 1251 1252 final StringArgument importCertEncryptionPassword = new StringArgument(null, 1253 "encryption-password", false, 1, 1254 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1255 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_ENC_PW_DESC.get()); 1256 importCertEncryptionPassword.addLongIdentifier("encryptionPassword", true); 1257 importCertEncryptionPassword.setSensitive(true); 1258 importCertParser.addArgument(importCertEncryptionPassword); 1259 1260 final FileArgument importCertEncryptionPasswordFile = new FileArgument(null, 1261 "encryption-password-file", false, 1, null, 1262 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_ENC_PW_FILE_DESC.get(), true, 1263 true, true, false); 1264 importCertEncryptionPasswordFile.addLongIdentifier("encryptionPasswordFile", 1265 true); 1266 importCertParser.addArgument(importCertEncryptionPasswordFile); 1267 1268 final BooleanArgument importCertPromptForEncryptionPassword = 1269 new BooleanArgument(null, "prompt-for-encryption-password", 1270 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PROMPT_FOR_ENC_PW_DESC.get()); 1271 importCertPromptForEncryptionPassword.addLongIdentifier( 1272 "promptForEncryptionPassword", true); 1273 importCertParser.addArgument(importCertPromptForEncryptionPassword); 1274 1275 final BooleanArgument importCertNoPrompt = new BooleanArgument(null, 1276 "no-prompt", 1, 1277 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_NO_PROMPT_DESC.get()); 1278 importCertNoPrompt.addLongIdentifier("noPrompt", true); 1279 importCertParser.addArgument(importCertNoPrompt); 1280 1281 final BooleanArgument importCertDisplayCommand = new BooleanArgument(null, 1282 "display-keytool-command", 1, 1283 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1284 importCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1285 importCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1286 importCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1287 importCertParser.addArgument(importCertDisplayCommand); 1288 1289 importCertParser.addRequiredArgumentSet(importCertKeystorePassword, 1290 importCertKeystorePasswordFile, importCertPromptForKeystorePassword); 1291 importCertParser.addExclusiveArgumentSet(importCertKeystorePassword, 1292 importCertKeystorePasswordFile, importCertPromptForKeystorePassword); 1293 importCertParser.addExclusiveArgumentSet(importCertPKPassword, 1294 importCertPKPasswordFile, importCertPromptForPKPassword); 1295 importCertParser.addExclusiveArgumentSet(importCertEncryptionPassword, 1296 importCertEncryptionPasswordFile, 1297 importCertPromptForEncryptionPassword); 1298 1299 final LinkedHashMap<String[],String> importCertExamples = 1300 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 1301 importCertExamples.put( 1302 new String[] 1303 { 1304 "import-certificate", 1305 "--keystore", getPlatformSpecificPath("config", "keystore"), 1306 "--keystore-password-file", 1307 getPlatformSpecificPath("config", "keystore.pin"), 1308 "--alias", "server-cert", 1309 "--certificate-file", "server-cert.crt" 1310 }, 1311 INFO_MANAGE_CERTS_SC_IMPORT_CERT_EXAMPLE_1.get("server-cert.crt")); 1312 importCertExamples.put( 1313 new String[] 1314 { 1315 "import-certificate", 1316 "--keystore", getPlatformSpecificPath("config", "keystore"), 1317 "--keystore-password-file", 1318 getPlatformSpecificPath("config", "keystore.pin"), 1319 "--alias", "server-cert", 1320 "--certificate-file", "server-cert.crt", 1321 "--certificate-file", "server-cert-issuer.crt", 1322 "--private-key-file", "server-cert.key", 1323 "--display-keytool-command" 1324 }, 1325 INFO_MANAGE_CERTS_SC_IMPORT_CERT_EXAMPLE_2.get()); 1326 1327 final SubCommand importCertSubCommand = new SubCommand("import-certificate", 1328 INFO_MANAGE_CERTS_SC_IMPORT_CERT_DESC.get(), importCertParser, 1329 importCertExamples); 1330 importCertSubCommand.addName("importCertificate", true); 1331 importCertSubCommand.addName("import-certificates", true); 1332 importCertSubCommand.addName("importCertificates", true); 1333 importCertSubCommand.addName("import-cert", true); 1334 importCertSubCommand.addName("importCert", true); 1335 importCertSubCommand.addName("import-certs", true); 1336 importCertSubCommand.addName("importCerts", true); 1337 importCertSubCommand.addName("import-certificate-chain", true); 1338 importCertSubCommand.addName("importCertificateChain", true); 1339 importCertSubCommand.addName("import-chain", true); 1340 importCertSubCommand.addName("importChain", true); 1341 importCertSubCommand.addName("import", true); 1342 1343 parser.addSubCommand(importCertSubCommand); 1344 1345 1346 // Define the "delete-certificate" subcommand and all of its arguments. 1347 final ArgumentParser deleteCertParser = new ArgumentParser( 1348 "delete-certificate", INFO_MANAGE_CERTS_SC_DELETE_CERT_DESC.get()); 1349 1350 final FileArgument deleteCertKeystore = new FileArgument(null, "keystore", 1351 true, 1, null, INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_DESC.get(), 1352 true, true, true, false); 1353 deleteCertKeystore.addLongIdentifier("keystore-path", true); 1354 deleteCertKeystore.addLongIdentifier("keystorePath", true); 1355 deleteCertKeystore.addLongIdentifier("keystore-file", true); 1356 deleteCertKeystore.addLongIdentifier("keystoreFile", true); 1357 deleteCertParser.addArgument(deleteCertKeystore); 1358 1359 final StringArgument deleteCertKeystorePassword = new StringArgument(null, 1360 "keystore-password", false, 1, 1361 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1362 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_PW_DESC.get()); 1363 deleteCertKeystorePassword.addLongIdentifier("keystorePassword", true); 1364 deleteCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 1365 deleteCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 1366 deleteCertKeystorePassword.addLongIdentifier("keystore-pin", true); 1367 deleteCertKeystorePassword.addLongIdentifier("keystorePIN", true); 1368 deleteCertKeystorePassword.addLongIdentifier("storepass", true); 1369 deleteCertKeystorePassword.setSensitive(true); 1370 deleteCertParser.addArgument(deleteCertKeystorePassword); 1371 1372 final FileArgument deleteCertKeystorePasswordFile = new FileArgument(null, 1373 "keystore-password-file", false, 1, null, 1374 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 1375 true, false); 1376 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 1377 true); 1378 deleteCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 1379 true); 1380 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 1381 true); 1382 deleteCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 1383 true); 1384 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 1385 deleteCertParser.addArgument(deleteCertKeystorePasswordFile); 1386 1387 final BooleanArgument deleteCertPromptForKeystorePassword = 1388 new BooleanArgument(null, "prompt-for-keystore-password", 1389 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 1390 deleteCertPromptForKeystorePassword.addLongIdentifier( 1391 "promptForKeystorePassword", true); 1392 deleteCertPromptForKeystorePassword.addLongIdentifier( 1393 "prompt-for-keystore-passphrase", true); 1394 deleteCertPromptForKeystorePassword.addLongIdentifier( 1395 "promptForKeystorePassphrase", true); 1396 deleteCertPromptForKeystorePassword.addLongIdentifier( 1397 "prompt-for-keystore-pin", true); 1398 deleteCertPromptForKeystorePassword.addLongIdentifier( 1399 "promptForKeystorePIN", true); 1400 deleteCertParser.addArgument(deleteCertPromptForKeystorePassword); 1401 1402 final StringArgument deleteCertKeystoreType = new StringArgument(null, 1403 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 1404 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_TYPE_DESC.get(), 1405 ALLOWED_KEYSTORE_TYPE_VALUES); 1406 deleteCertKeystoreType.addLongIdentifier("key-store-type", true); 1407 deleteCertKeystoreType.addLongIdentifier("keystoreType", true); 1408 deleteCertKeystoreType.addLongIdentifier("keystore-format", true); 1409 deleteCertKeystoreType.addLongIdentifier("key-store-format", true); 1410 deleteCertKeystoreType.addLongIdentifier("keystoreFormat", true); 1411 deleteCertKeystoreType.addLongIdentifier("storetype", true); 1412 deleteCertParser.addArgument(deleteCertKeystoreType); 1413 1414 final StringArgument deleteCertAlias = new StringArgument(null, "alias", 1415 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 1416 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_ALIAS_DESC.get()); 1417 deleteCertAlias.addLongIdentifier("nickname", true); 1418 deleteCertParser.addArgument(deleteCertAlias); 1419 1420 final BooleanArgument deleteCertNoPrompt = new BooleanArgument(null, 1421 "no-prompt", 1, 1422 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_NO_PROMPT_DESC.get()); 1423 deleteCertNoPrompt.addLongIdentifier("noPrompt", true); 1424 deleteCertParser.addArgument(deleteCertNoPrompt); 1425 1426 final BooleanArgument deleteCertDisplayCommand = new BooleanArgument(null, 1427 "display-keytool-command", 1, 1428 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1429 deleteCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1430 deleteCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1431 deleteCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1432 deleteCertParser.addArgument(deleteCertDisplayCommand); 1433 1434 deleteCertParser.addExclusiveArgumentSet(deleteCertKeystorePassword, 1435 deleteCertKeystorePasswordFile, deleteCertPromptForKeystorePassword); 1436 deleteCertParser.addRequiredArgumentSet(deleteCertKeystorePassword, 1437 deleteCertKeystorePasswordFile, deleteCertPromptForKeystorePassword); 1438 1439 final LinkedHashMap<String[],String> deleteCertExamples = 1440 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 1441 deleteCertExamples.put( 1442 new String[] 1443 { 1444 "delete-certificate", 1445 "--keystore", getPlatformSpecificPath("config", "keystore"), 1446 "--alias", "server-cert" 1447 }, 1448 INFO_MANAGE_CERTS_SC_DELETE_CERT_EXAMPLE_1.get( 1449 getPlatformSpecificPath("config", "keystore"))); 1450 1451 final SubCommand deleteCertSubCommand = new SubCommand("delete-certificate", 1452 INFO_MANAGE_CERTS_SC_DELETE_CERT_DESC.get(), deleteCertParser, 1453 deleteCertExamples); 1454 deleteCertSubCommand.addName("deleteCertificate", true); 1455 deleteCertSubCommand.addName("remove-certificate", true); 1456 deleteCertSubCommand.addName("removeCertificate", true); 1457 deleteCertSubCommand.addName("delete", true); 1458 deleteCertSubCommand.addName("remove", true); 1459 1460 parser.addSubCommand(deleteCertSubCommand); 1461 1462 1463 // Define the "generate-self-signed-certificate" subcommand and all of its 1464 // arguments. 1465 final ArgumentParser genCertParser = new ArgumentParser( 1466 "generate-self-signed-certificate", 1467 INFO_MANAGE_CERTS_SC_GEN_CERT_DESC.get()); 1468 1469 final FileArgument genCertKeystore = new FileArgument(null, "keystore", 1470 true, 1, null, INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_DESC.get(), false, 1471 true, true, false); 1472 genCertKeystore.addLongIdentifier("keystore-path", true); 1473 genCertKeystore.addLongIdentifier("keystorePath", true); 1474 genCertKeystore.addLongIdentifier("keystore-file", true); 1475 genCertKeystore.addLongIdentifier("keystoreFile", true); 1476 genCertParser.addArgument(genCertKeystore); 1477 1478 final StringArgument genCertKeystorePassword = new StringArgument(null, 1479 "keystore-password", false, 1, 1480 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1481 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_PW_DESC.get()); 1482 genCertKeystorePassword.addLongIdentifier("keystorePassword", true); 1483 genCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 1484 genCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 1485 genCertKeystorePassword.addLongIdentifier("keystore-pin", true); 1486 genCertKeystorePassword.addLongIdentifier("keystorePIN", true); 1487 genCertKeystorePassword.addLongIdentifier("storepass", true); 1488 genCertKeystorePassword.setSensitive(true); 1489 genCertParser.addArgument(genCertKeystorePassword); 1490 1491 final FileArgument genCertKeystorePasswordFile = new FileArgument(null, 1492 "keystore-password-file", false, 1, null, 1493 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 1494 true, false); 1495 genCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 1496 true); 1497 genCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 1498 true); 1499 genCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 1500 true); 1501 genCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 1502 true); 1503 genCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 1504 genCertParser.addArgument(genCertKeystorePasswordFile); 1505 1506 final BooleanArgument genCertPromptForKeystorePassword = 1507 new BooleanArgument(null, "prompt-for-keystore-password", 1508 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 1509 genCertPromptForKeystorePassword.addLongIdentifier( 1510 "promptForKeystorePassword", true); 1511 genCertPromptForKeystorePassword.addLongIdentifier( 1512 "prompt-for-keystore-passphrase", true); 1513 genCertPromptForKeystorePassword.addLongIdentifier( 1514 "promptForKeystorePassphrase", true); 1515 genCertPromptForKeystorePassword.addLongIdentifier( 1516 "prompt-for-keystore-pin", true); 1517 genCertPromptForKeystorePassword.addLongIdentifier( 1518 "promptForKeystorePIN", true); 1519 genCertParser.addArgument(genCertPromptForKeystorePassword); 1520 1521 final StringArgument genCertPKPassword = new StringArgument(null, 1522 "private-key-password", false, 1, 1523 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1524 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PK_PW_DESC.get()); 1525 genCertPKPassword.addLongIdentifier("privateKeyPassword", true); 1526 genCertPKPassword.addLongIdentifier("private-key-passphrase", true); 1527 genCertPKPassword.addLongIdentifier("privateKeyPassphrase", true); 1528 genCertPKPassword.addLongIdentifier("private-key-pin", true); 1529 genCertPKPassword.addLongIdentifier("privateKeyPIN", true); 1530 genCertPKPassword.addLongIdentifier("key-password", true); 1531 genCertPKPassword.addLongIdentifier("keyPassword", true); 1532 genCertPKPassword.addLongIdentifier("key-passphrase", true); 1533 genCertPKPassword.addLongIdentifier("keyPassphrase", true); 1534 genCertPKPassword.addLongIdentifier("key-pin", true); 1535 genCertPKPassword.addLongIdentifier("keyPIN", true); 1536 genCertPKPassword.addLongIdentifier("keypass", true); 1537 genCertPKPassword.setSensitive(true); 1538 genCertParser.addArgument(genCertPKPassword); 1539 1540 final FileArgument genCertPKPasswordFile = new FileArgument(null, 1541 "private-key-password-file", false, 1, null, 1542 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PK_PW_FILE_DESC.get(), true, true, 1543 true, false); 1544 genCertPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 1545 genCertPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 1546 true); 1547 genCertPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 1548 true); 1549 genCertPKPasswordFile.addLongIdentifier("private-key-pin-file", 1550 true); 1551 genCertPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 1552 genCertPKPasswordFile.addLongIdentifier("key-password-file", true); 1553 genCertPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 1554 genCertPKPasswordFile.addLongIdentifier("key-passphrase-file", 1555 true); 1556 genCertPKPasswordFile.addLongIdentifier("keyPassphraseFile", 1557 true); 1558 genCertPKPasswordFile.addLongIdentifier("key-pin-file", 1559 true); 1560 genCertPKPasswordFile.addLongIdentifier("keyPINFile", true); 1561 genCertParser.addArgument(genCertPKPasswordFile); 1562 1563 final BooleanArgument genCertPromptForPKPassword = 1564 new BooleanArgument(null, "prompt-for-private-key-password", 1565 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PROMPT_FOR_PK_PW_DESC.get()); 1566 genCertPromptForPKPassword.addLongIdentifier( 1567 "promptForPrivateKeyPassword", true); 1568 genCertPromptForPKPassword.addLongIdentifier( 1569 "prompt-for-private-key-passphrase", true); 1570 genCertPromptForPKPassword.addLongIdentifier( 1571 "promptForPrivateKeyPassphrase", true); 1572 genCertPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 1573 true); 1574 genCertPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 1575 true); 1576 genCertPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 1577 true); 1578 genCertPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 1579 true); 1580 genCertPromptForPKPassword.addLongIdentifier( 1581 "prompt-for-key-passphrase", true); 1582 genCertPromptForPKPassword.addLongIdentifier( 1583 "promptForKeyPassphrase", true); 1584 genCertPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 1585 genCertPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 1586 genCertParser.addArgument(genCertPromptForPKPassword); 1587 1588 final StringArgument genCertKeystoreType = new StringArgument(null, 1589 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 1590 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_TYPE_DESC.get(), 1591 ALLOWED_KEYSTORE_TYPE_VALUES); 1592 genCertKeystoreType.addLongIdentifier("key-store-type", true); 1593 genCertKeystoreType.addLongIdentifier("keystoreType", true); 1594 genCertKeystoreType.addLongIdentifier("keystore-format", true); 1595 genCertKeystoreType.addLongIdentifier("key-store-format", true); 1596 genCertKeystoreType.addLongIdentifier("keystoreFormat", true); 1597 genCertKeystoreType.addLongIdentifier("storetype", true); 1598 genCertParser.addArgument(genCertKeystoreType); 1599 1600 final StringArgument genCertAlias = new StringArgument(null, "alias", 1601 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 1602 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_ALIAS_DESC.get()); 1603 genCertAlias.addLongIdentifier("nickname", true); 1604 genCertParser.addArgument(genCertAlias); 1605 1606 final BooleanArgument genCertUseExistingKeyPair = new BooleanArgument(null, 1607 "use-existing-key-pair", 1, 1608 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_USE_EXISTING_KP_DESC.get()); 1609 genCertUseExistingKeyPair.addLongIdentifier("use-existing-keypair", true); 1610 genCertUseExistingKeyPair.addLongIdentifier("useExistingKeypair", true); 1611 genCertUseExistingKeyPair.addLongIdentifier("replace-existing-certificate", 1612 true); 1613 genCertUseExistingKeyPair.addLongIdentifier("replaceExistingCertificate", 1614 true); 1615 genCertUseExistingKeyPair.addLongIdentifier("replace-certificate", true); 1616 genCertUseExistingKeyPair.addLongIdentifier("replaceCertificate", true); 1617 genCertUseExistingKeyPair.addLongIdentifier("replace-existing", true); 1618 genCertUseExistingKeyPair.addLongIdentifier("replaceExisting", true); 1619 genCertUseExistingKeyPair.addLongIdentifier("replace", true); 1620 genCertParser.addArgument(genCertUseExistingKeyPair); 1621 1622 final DNArgument genCertSubjectDN = new DNArgument(null, "subject-dn", 1623 false, 1, null, 1624 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SUBJECT_DN_DESC.get()); 1625 genCertSubjectDN.addLongIdentifier("subjectDN", true); 1626 genCertSubjectDN.addLongIdentifier("subject", true); 1627 genCertSubjectDN.addLongIdentifier("dname", true); 1628 genCertParser.addArgument(genCertSubjectDN); 1629 1630 final IntegerArgument genCertDaysValid = new IntegerArgument(null, 1631 "days-valid", false, 1, null, 1632 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_DAYS_VALID_DESC.get(), 1, 1633 Integer.MAX_VALUE); 1634 genCertDaysValid.addLongIdentifier("daysValid", true); 1635 genCertDaysValid.addLongIdentifier("validity", true); 1636 genCertParser.addArgument(genCertDaysValid); 1637 1638 final TimestampArgument genCertNotBefore = new TimestampArgument(null, 1639 "validity-start-time", false, 1, 1640 INFO_MANAGE_CERTS_PLACEHOLDER_TIMESTAMP.get(), 1641 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_VALIDITY_START_TIME_DESC.get( 1642 "20180102123456")); 1643 genCertNotBefore.addLongIdentifier("validityStartTime", true); 1644 genCertNotBefore.addLongIdentifier("not-before", true); 1645 genCertNotBefore.addLongIdentifier("notBefore", true); 1646 genCertParser.addArgument(genCertNotBefore); 1647 1648 final StringArgument genCertKeyAlgorithm = new StringArgument(null, 1649 "key-algorithm", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1650 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KEY_ALGORITHM_DESC.get()); 1651 genCertKeyAlgorithm.addLongIdentifier("keyAlgorithm", true); 1652 genCertKeyAlgorithm.addLongIdentifier("key-alg", true); 1653 genCertKeyAlgorithm.addLongIdentifier("keyAlg", true); 1654 genCertParser.addArgument(genCertKeyAlgorithm); 1655 1656 final IntegerArgument genCertKeySizeBits = new IntegerArgument(null, 1657 "key-size-bits", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_BITS.get(), 1658 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KEY_SIZE_BITS_DESC.get(), 1, 1659 Integer.MAX_VALUE); 1660 genCertKeySizeBits.addLongIdentifier("keySizeBits", true); 1661 genCertKeySizeBits.addLongIdentifier("key-length-bits", true); 1662 genCertKeySizeBits.addLongIdentifier("keyLengthBits", true); 1663 genCertKeySizeBits.addLongIdentifier("key-size", true); 1664 genCertKeySizeBits.addLongIdentifier("keySize", true); 1665 genCertKeySizeBits.addLongIdentifier("key-length", true); 1666 genCertKeySizeBits.addLongIdentifier("keyLength", true); 1667 genCertParser.addArgument(genCertKeySizeBits); 1668 1669 final StringArgument genCertSignatureAlgorithm = new StringArgument(null, 1670 "signature-algorithm", false, 1, 1671 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1672 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SIG_ALG_DESC.get()); 1673 genCertSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 1674 genCertSignatureAlgorithm.addLongIdentifier("signature-alg", true); 1675 genCertSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 1676 genCertSignatureAlgorithm.addLongIdentifier("sig-alg", true); 1677 genCertSignatureAlgorithm.addLongIdentifier("sigAlg", true); 1678 genCertParser.addArgument(genCertSignatureAlgorithm); 1679 1680 final BooleanArgument genCertInheritExtensions = new BooleanArgument(null, 1681 "inherit-extensions", 1, 1682 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_INHERIT_EXT_DESC.get()); 1683 genCertInheritExtensions.addLongIdentifier("inheritExtensions", true); 1684 genCertParser.addArgument(genCertInheritExtensions); 1685 1686 final StringArgument genCertSubjectAltDNS = new StringArgument(null, 1687 "subject-alternative-name-dns", false, 0, 1688 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1689 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_DNS_DESC.get()); 1690 genCertSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 1691 genCertSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 1692 genCertSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 1693 genCertSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 1694 genCertSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 1695 genCertSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 1696 genCertSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 1697 genCertSubjectAltDNS.addLongIdentifier("san-dns", true); 1698 genCertSubjectAltDNS.addLongIdentifier("sanDNS", true); 1699 genCertSubjectAltDNS.addValueValidator( 1700 new IA5StringArgumentValueValidator(false)); 1701 genCertParser.addArgument(genCertSubjectAltDNS); 1702 1703 final StringArgument genCertSubjectAltIP = new StringArgument(null, 1704 "subject-alternative-name-ip-address", false, 0, 1705 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1706 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_IP_DESC.get()); 1707 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 1708 true); 1709 genCertSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 1710 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 1711 genCertSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 1712 genCertSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 1713 genCertSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 1714 genCertSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 1715 genCertSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 1716 true); 1717 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 1718 genCertSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 1719 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 1720 genCertSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 1721 genCertSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 1722 genCertSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 1723 genCertSubjectAltIP.addLongIdentifier("subjectAltIP", true); 1724 genCertSubjectAltIP.addLongIdentifier("san-ip-address", true); 1725 genCertSubjectAltIP.addLongIdentifier("sanIPAddress", true); 1726 genCertSubjectAltIP.addLongIdentifier("san-ip", true); 1727 genCertSubjectAltIP.addLongIdentifier("sanIP", true); 1728 genCertSubjectAltIP.addValueValidator( 1729 new IPAddressArgumentValueValidator(true, true)); 1730 genCertParser.addArgument(genCertSubjectAltIP); 1731 1732 final StringArgument genCertSubjectAltEmail = new StringArgument(null, 1733 "subject-alternative-name-email-address", false, 0, 1734 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1735 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_EMAIL_DESC.get()); 1736 genCertSubjectAltEmail.addLongIdentifier( 1737 "subjectAlternativeNameEmailAddress", true); 1738 genCertSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 1739 true); 1740 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 1741 true); 1742 genCertSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 1743 true); 1744 genCertSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 1745 true); 1746 genCertSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 1747 genCertSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 1748 genCertSubjectAltEmail.addLongIdentifier( 1749 "subject-alternative-email-address", true); 1750 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 1751 true); 1752 genCertSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 1753 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 1754 genCertSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 1755 genCertSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 1756 genCertSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 1757 genCertSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 1758 genCertSubjectAltEmail.addLongIdentifier("san-email-address", true); 1759 genCertSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 1760 genCertSubjectAltEmail.addLongIdentifier("san-email", true); 1761 genCertSubjectAltEmail.addLongIdentifier("sanEmail", true); 1762 genCertSubjectAltEmail.addValueValidator( 1763 new IA5StringArgumentValueValidator(false)); 1764 genCertParser.addArgument(genCertSubjectAltEmail); 1765 1766 final StringArgument genCertSubjectAltURI = new StringArgument(null, 1767 "subject-alternative-name-uri", false, 0, 1768 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 1769 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_URI_DESC.get()); 1770 genCertSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 1771 genCertSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 1772 genCertSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 1773 genCertSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 1774 genCertSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 1775 genCertSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 1776 genCertSubjectAltURI.addLongIdentifier("subjectAltURI", true); 1777 genCertSubjectAltURI.addLongIdentifier("san-uri", true); 1778 genCertSubjectAltURI.addLongIdentifier("sanURI", true); 1779 genCertParser.addArgument(genCertSubjectAltURI); 1780 1781 final StringArgument genCertSubjectAltOID = new StringArgument(null, 1782 "subject-alternative-name-oid", false, 0, 1783 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 1784 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_OID_DESC.get()); 1785 genCertSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 1786 genCertSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 1787 genCertSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 1788 genCertSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 1789 genCertSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 1790 genCertSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 1791 genCertSubjectAltOID.addLongIdentifier("subjectAltOID", true); 1792 genCertSubjectAltOID.addLongIdentifier("san-oid", true); 1793 genCertSubjectAltOID.addLongIdentifier("sanOID", true); 1794 genCertSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 1795 genCertParser.addArgument(genCertSubjectAltOID); 1796 1797 final BooleanValueArgument genCertBasicConstraintsIsCA = 1798 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 1799 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_IS_CA_DESC.get()); 1800 genCertBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 1801 genCertBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 1802 genCertBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 1803 genCertParser.addArgument(genCertBasicConstraintsIsCA); 1804 1805 final IntegerArgument genCertBasicConstraintsPathLength = 1806 new IntegerArgument(null, "basic-constraints-maximum-path-length", 1807 false, 1, null, 1808 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 1809 Integer.MAX_VALUE); 1810 genCertBasicConstraintsPathLength.addLongIdentifier( 1811 "basicConstraintsMaximumPathLength", true); 1812 genCertBasicConstraintsPathLength.addLongIdentifier( 1813 "basic-constraints-max-path-length", true); 1814 genCertBasicConstraintsPathLength.addLongIdentifier( 1815 "basicConstraintsMaxPathLength", true); 1816 genCertBasicConstraintsPathLength.addLongIdentifier( 1817 "basic-constraints-path-length", true); 1818 genCertBasicConstraintsPathLength.addLongIdentifier( 1819 "basicConstraintsPathLength", true); 1820 genCertBasicConstraintsPathLength.addLongIdentifier( 1821 "bc-maximum-path-length", true); 1822 genCertBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 1823 true); 1824 genCertBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 1825 true); 1826 genCertBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 1827 true); 1828 genCertBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 1829 genCertBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 1830 genCertParser.addArgument(genCertBasicConstraintsPathLength); 1831 1832 final StringArgument genCertKeyUsage = new StringArgument(null, "key-usage", 1833 false, 0, null, INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KU_DESC.get()); 1834 genCertKeyUsage.addLongIdentifier("keyUsage", true); 1835 genCertParser.addArgument(genCertKeyUsage); 1836 1837 final StringArgument genCertExtendedKeyUsage = new StringArgument(null, 1838 "extended-key-usage", false, 0, null, 1839 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_EKU_DESC.get()); 1840 genCertExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 1841 genCertParser.addArgument(genCertExtendedKeyUsage); 1842 1843 final StringArgument genCertExtension = new StringArgument(null, 1844 "extension", false, 0, null, 1845 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_EXT_DESC.get()); 1846 genCertExtension.addLongIdentifier("ext", true); 1847 genCertParser.addArgument(genCertExtension); 1848 1849 final FileArgument genCertOutputFile = new FileArgument(null, "output-file", 1850 false, 1, null, 1851 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_OUTPUT_FILE_DESC.get(), false, true, 1852 true, false); 1853 genCertOutputFile.addLongIdentifier("outputFile", true); 1854 genCertOutputFile.addLongIdentifier("filename", true); 1855 genCertOutputFile.addLongIdentifier("file", true); 1856 genCertParser.addArgument(genCertOutputFile); 1857 1858 final Set<String> genCertOutputFormatAllowedValues = StaticUtils.setOf( 1859 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 1860 final StringArgument genCertOutputFormat = new StringArgument(null, 1861 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 1862 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_FORMAT_DESC.get(), 1863 genCertOutputFormatAllowedValues, "PEM"); 1864 genCertOutputFormat.addLongIdentifier("outputFormat", true); 1865 genCertParser.addArgument(genCertOutputFormat); 1866 1867 final BooleanArgument genCertDisplayCommand = new BooleanArgument(null, 1868 "display-keytool-command", 1, 1869 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1870 genCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1871 genCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1872 genCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1873 genCertParser.addArgument(genCertDisplayCommand); 1874 1875 genCertParser.addRequiredArgumentSet(genCertKeystorePassword, 1876 genCertKeystorePasswordFile, genCertPromptForKeystorePassword); 1877 genCertParser.addExclusiveArgumentSet(genCertKeystorePassword, 1878 genCertKeystorePasswordFile, genCertPromptForKeystorePassword); 1879 genCertParser.addExclusiveArgumentSet(genCertPKPassword, 1880 genCertPKPasswordFile, genCertPromptForPKPassword); 1881 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1882 genCertKeyAlgorithm); 1883 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1884 genCertKeySizeBits); 1885 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1886 genCertSignatureAlgorithm); 1887 genCertParser.addDependentArgumentSet(genCertBasicConstraintsPathLength, 1888 genCertBasicConstraintsIsCA); 1889 genCertParser.addDependentArgumentSet(genCertOutputFormat, 1890 genCertOutputFile); 1891 1892 final LinkedHashMap<String[],String> genCertExamples = 1893 new LinkedHashMap<>(StaticUtils.computeMapCapacity(4)); 1894 genCertExamples.put( 1895 new String[] 1896 { 1897 "generate-self-signed-certificate", 1898 "--keystore", getPlatformSpecificPath("config", "keystore"), 1899 "--keystore-password-file", 1900 getPlatformSpecificPath("config", "keystore.pin"), 1901 "--alias", "server-cert", 1902 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US" 1903 }, 1904 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_1.get()); 1905 genCertExamples.put( 1906 new String[] 1907 { 1908 "generate-self-signed-certificate", 1909 "--keystore", getPlatformSpecificPath("config", "keystore"), 1910 "--keystore-password-file", 1911 getPlatformSpecificPath("config", "keystore.pin"), 1912 "--alias", "server-cert", 1913 "--use-existing-key-pair", 1914 "--inherit-extensions" 1915 }, 1916 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_2.get()); 1917 genCertExamples.put( 1918 new String[] 1919 { 1920 "generate-self-signed-certificate", 1921 "--keystore", getPlatformSpecificPath("config", "keystore"), 1922 "--keystore-password-file", 1923 getPlatformSpecificPath("config", "keystore.pin"), 1924 "--alias", "server-cert", 1925 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US", 1926 "--days-valid", "3650", 1927 "--validity-start-time", "20170101000000", 1928 "--key-algorithm", "RSA", 1929 "--key-size-bits", "4096", 1930 "--signature-algorithm", "SHA256withRSA", 1931 "--subject-alternative-name-dns", "ldap1.example.com", 1932 "--subject-alternative-name-dns", "ldap2.example.com", 1933 "--subject-alternative-name-ip-address", "1.2.3.4", 1934 "--subject-alternative-name-ip-address", "1.2.3.5", 1935 "--extended-key-usage", "server-auth", 1936 "--extended-key-usage", "client-auth", 1937 "--display-keytool-command" 1938 }, 1939 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_3.get()); 1940 genCertExamples.put( 1941 new String[] 1942 { 1943 "generate-self-signed-certificate", 1944 "--keystore", getPlatformSpecificPath("config", "keystore"), 1945 "--keystore-password-file", 1946 getPlatformSpecificPath("config", "keystore.pin"), 1947 "--alias", "ca-cert", 1948 "--subject-dn", 1949 "CN=Example Certification Authority,O=Example Corp,C=US", 1950 "--days-valid", "7300", 1951 "--validity-start-time", "20170101000000", 1952 "--key-algorithm", "EC", 1953 "--key-size-bits", "256", 1954 "--signature-algorithm", "SHA256withECDSA", 1955 "--basic-constraints-is-ca", "true", 1956 "--key-usage", "key-cert-sign", 1957 "--key-usage", "crl-sign", 1958 "--display-keytool-command" 1959 }, 1960 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_4.get()); 1961 1962 final SubCommand genCertSubCommand = new SubCommand( 1963 "generate-self-signed-certificate", 1964 INFO_MANAGE_CERTS_SC_GEN_CERT_DESC.get(), genCertParser, 1965 genCertExamples); 1966 genCertSubCommand.addName("generateSelfSignedCertificate", true); 1967 genCertSubCommand.addName("generate-certificate", true); 1968 genCertSubCommand.addName("generateCertificate", true); 1969 genCertSubCommand.addName("self-signed-certificate", true); 1970 genCertSubCommand.addName("selfSignedCertificate", true); 1971 genCertSubCommand.addName("selfcert", true); 1972 1973 parser.addSubCommand(genCertSubCommand); 1974 1975 1976 // Define the "generate-certificate-signing-request" subcommand and all of 1977 // its arguments. 1978 final ArgumentParser genCSRParser = new ArgumentParser( 1979 "generate-certificate-signing-request", 1980 INFO_MANAGE_CERTS_SC_GEN_CSR_DESC.get()); 1981 1982 final Set<String> genCSROutputFormatAllowedValues = StaticUtils.setOf( 1983 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 1984 final StringArgument genCSROutputFormat = new StringArgument(null, 1985 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 1986 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_FORMAT_DESC.get(), 1987 genCSROutputFormatAllowedValues, "PEM"); 1988 genCSROutputFormat.addLongIdentifier("outputFormat", true); 1989 genCSRParser.addArgument(genCSROutputFormat); 1990 1991 final FileArgument genCSROutputFile = new FileArgument(null, "output-file", 1992 false, 1, null, 1993 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_OUTPUT_FILE_DESC.get(), false, true, 1994 true, false); 1995 genCSROutputFile.addLongIdentifier("outputFile", true); 1996 genCSROutputFile.addLongIdentifier("filename", true); 1997 genCSROutputFile.addLongIdentifier("file", true); 1998 genCSRParser.addArgument(genCSROutputFile); 1999 2000 final FileArgument genCSRKeystore = new FileArgument(null, "keystore", 2001 true, 1, null, INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_DESC.get(), false, 2002 true, true, false); 2003 genCSRKeystore.addLongIdentifier("keystore-path", true); 2004 genCSRKeystore.addLongIdentifier("keystorePath", true); 2005 genCSRKeystore.addLongIdentifier("keystore-file", true); 2006 genCSRKeystore.addLongIdentifier("keystoreFile", true); 2007 genCSRParser.addArgument(genCSRKeystore); 2008 2009 final StringArgument genCSRKeystorePassword = new StringArgument(null, 2010 "keystore-password", false, 1, 2011 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2012 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_PW_DESC.get()); 2013 genCSRKeystorePassword.addLongIdentifier("keystorePassword", true); 2014 genCSRKeystorePassword.addLongIdentifier("keystore-passphrase", true); 2015 genCSRKeystorePassword.addLongIdentifier("keystorePassphrase", true); 2016 genCSRKeystorePassword.addLongIdentifier("keystore-pin", true); 2017 genCSRKeystorePassword.addLongIdentifier("keystorePIN", true); 2018 genCSRKeystorePassword.addLongIdentifier("storepass", true); 2019 genCSRKeystorePassword.setSensitive(true); 2020 genCSRParser.addArgument(genCSRKeystorePassword); 2021 2022 final FileArgument genCSRKeystorePasswordFile = new FileArgument(null, 2023 "keystore-password-file", false, 1, null, 2024 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_PW_FILE_DESC.get(), true, true, 2025 true, false); 2026 genCSRKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 2027 true); 2028 genCSRKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 2029 true); 2030 genCSRKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 2031 true); 2032 genCSRKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 2033 true); 2034 genCSRKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 2035 genCSRParser.addArgument(genCSRKeystorePasswordFile); 2036 2037 final BooleanArgument genCSRPromptForKeystorePassword = 2038 new BooleanArgument(null, "prompt-for-keystore-password", 2039 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PROMPT_FOR_KS_PW_DESC.get()); 2040 genCSRPromptForKeystorePassword.addLongIdentifier( 2041 "promptForKeystorePassword", true); 2042 genCSRPromptForKeystorePassword.addLongIdentifier( 2043 "prompt-for-keystore-passphrase", true); 2044 genCSRPromptForKeystorePassword.addLongIdentifier( 2045 "promptForKeystorePassphrase", true); 2046 genCSRPromptForKeystorePassword.addLongIdentifier( 2047 "prompt-for-keystore-pin", true); 2048 genCSRPromptForKeystorePassword.addLongIdentifier( 2049 "promptForKeystorePIN", true); 2050 genCSRParser.addArgument(genCSRPromptForKeystorePassword); 2051 2052 final StringArgument genCSRPKPassword = new StringArgument(null, 2053 "private-key-password", false, 1, 2054 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2055 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PK_PW_DESC.get()); 2056 genCSRPKPassword.addLongIdentifier("privateKeyPassword", true); 2057 genCSRPKPassword.addLongIdentifier("private-key-passphrase", true); 2058 genCSRPKPassword.addLongIdentifier("privateKeyPassphrase", true); 2059 genCSRPKPassword.addLongIdentifier("private-key-pin", true); 2060 genCSRPKPassword.addLongIdentifier("privateKeyPIN", true); 2061 genCSRPKPassword.addLongIdentifier("key-password", true); 2062 genCSRPKPassword.addLongIdentifier("keyPassword", true); 2063 genCSRPKPassword.addLongIdentifier("key-passphrase", true); 2064 genCSRPKPassword.addLongIdentifier("keyPassphrase", true); 2065 genCSRPKPassword.addLongIdentifier("key-pin", true); 2066 genCSRPKPassword.addLongIdentifier("keyPIN", true); 2067 genCSRPKPassword.addLongIdentifier("keypass", true); 2068 genCSRPKPassword.setSensitive(true); 2069 genCSRParser.addArgument(genCSRPKPassword); 2070 2071 final FileArgument genCSRPKPasswordFile = new FileArgument(null, 2072 "private-key-password-file", false, 1, null, 2073 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PK_PW_FILE_DESC.get(), true, true, 2074 true, false); 2075 genCSRPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 2076 genCSRPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 2077 true); 2078 genCSRPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 2079 true); 2080 genCSRPKPasswordFile.addLongIdentifier("private-key-pin-file", 2081 true); 2082 genCSRPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 2083 genCSRPKPasswordFile.addLongIdentifier("key-password-file", true); 2084 genCSRPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 2085 genCSRPKPasswordFile.addLongIdentifier("key-passphrase-file", 2086 true); 2087 genCSRPKPasswordFile.addLongIdentifier("keyPassphraseFile", 2088 true); 2089 genCSRPKPasswordFile.addLongIdentifier("key-pin-file", 2090 true); 2091 genCSRPKPasswordFile.addLongIdentifier("keyPINFile", true); 2092 genCSRParser.addArgument(genCSRPKPasswordFile); 2093 2094 final BooleanArgument genCSRPromptForPKPassword = 2095 new BooleanArgument(null, "prompt-for-private-key-password", 2096 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PROMPT_FOR_PK_PW_DESC.get()); 2097 genCSRPromptForPKPassword.addLongIdentifier( 2098 "promptForPrivateKeyPassword", true); 2099 genCSRPromptForPKPassword.addLongIdentifier( 2100 "prompt-for-private-key-passphrase", true); 2101 genCSRPromptForPKPassword.addLongIdentifier( 2102 "promptForPrivateKeyPassphrase", true); 2103 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 2104 true); 2105 genCSRPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 2106 true); 2107 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 2108 true); 2109 genCSRPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 2110 true); 2111 genCSRPromptForPKPassword.addLongIdentifier( 2112 "prompt-for-key-passphrase", true); 2113 genCSRPromptForPKPassword.addLongIdentifier( 2114 "promptForKeyPassphrase", true); 2115 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 2116 genCSRPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 2117 genCSRParser.addArgument(genCSRPromptForPKPassword); 2118 2119 final StringArgument genCSRKeystoreType = new StringArgument(null, 2120 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 2121 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_TYPE_DESC.get(), 2122 ALLOWED_KEYSTORE_TYPE_VALUES); 2123 genCSRKeystoreType.addLongIdentifier("key-store-type", true); 2124 genCSRKeystoreType.addLongIdentifier("keystoreType", true); 2125 genCSRKeystoreType.addLongIdentifier("keystore-format", true); 2126 genCSRKeystoreType.addLongIdentifier("key-store-format", true); 2127 genCSRKeystoreType.addLongIdentifier("keystoreFormat", true); 2128 genCSRKeystoreType.addLongIdentifier("storetype", true); 2129 genCSRParser.addArgument(genCSRKeystoreType); 2130 2131 final StringArgument genCSRAlias = new StringArgument(null, "alias", 2132 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 2133 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_ALIAS_DESC.get()); 2134 genCSRAlias.addLongIdentifier("nickname", true); 2135 genCSRParser.addArgument(genCSRAlias); 2136 2137 final BooleanArgument genCSRUseExistingKeyPair = new BooleanArgument(null, 2138 "use-existing-key-pair", 1, 2139 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_USE_EXISTING_KP_DESC.get()); 2140 genCSRUseExistingKeyPair.addLongIdentifier("use-existing-keypair", true); 2141 genCSRUseExistingKeyPair.addLongIdentifier("useExistingKeyPair", true); 2142 genCSRUseExistingKeyPair.addLongIdentifier("replace-existing-certificate", 2143 true); 2144 genCSRUseExistingKeyPair.addLongIdentifier("replaceExistingCertificate", 2145 true); 2146 genCSRUseExistingKeyPair.addLongIdentifier("replace-certificate", true); 2147 genCSRUseExistingKeyPair.addLongIdentifier("replaceCertificate", true); 2148 genCSRUseExistingKeyPair.addLongIdentifier("replace-existing", true); 2149 genCSRUseExistingKeyPair.addLongIdentifier("replaceExisting", true); 2150 genCSRUseExistingKeyPair.addLongIdentifier("replace", true); 2151 genCSRParser.addArgument(genCSRUseExistingKeyPair); 2152 2153 final DNArgument genCSRSubjectDN = new DNArgument(null, "subject-dn", 2154 false, 1, null, 2155 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SUBJECT_DN_DESC.get()); 2156 genCSRSubjectDN.addLongIdentifier("subjectDN", true); 2157 genCSRSubjectDN.addLongIdentifier("subject", true); 2158 genCSRSubjectDN.addLongIdentifier("dname", true); 2159 genCSRParser.addArgument(genCSRSubjectDN); 2160 2161 final StringArgument genCSRKeyAlgorithm = new StringArgument(null, 2162 "key-algorithm", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2163 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KEY_ALGORITHM_DESC.get()); 2164 genCSRKeyAlgorithm.addLongIdentifier("keyAlgorithm", true); 2165 genCSRKeyAlgorithm.addLongIdentifier("key-alg", true); 2166 genCSRKeyAlgorithm.addLongIdentifier("keyAlg", true); 2167 genCSRParser.addArgument(genCSRKeyAlgorithm); 2168 2169 final IntegerArgument genCSRKeySizeBits = new IntegerArgument(null, 2170 "key-size-bits", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_BITS.get(), 2171 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KEY_SIZE_BITS_DESC.get(), 1, 2172 Integer.MAX_VALUE); 2173 genCSRKeySizeBits.addLongIdentifier("keySizeBits", true); 2174 genCSRKeySizeBits.addLongIdentifier("key-length-bits", true); 2175 genCSRKeySizeBits.addLongIdentifier("keyLengthBits", true); 2176 genCSRKeySizeBits.addLongIdentifier("key-size", true); 2177 genCSRKeySizeBits.addLongIdentifier("keySize", true); 2178 genCSRKeySizeBits.addLongIdentifier("key-length", true); 2179 genCSRKeySizeBits.addLongIdentifier("keyLength", true); 2180 genCSRParser.addArgument(genCSRKeySizeBits); 2181 2182 final StringArgument genCSRSignatureAlgorithm = new StringArgument(null, 2183 "signature-algorithm", false, 1, 2184 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2185 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SIG_ALG_DESC.get()); 2186 genCSRSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 2187 genCSRSignatureAlgorithm.addLongIdentifier("signature-alg", true); 2188 genCSRSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 2189 genCSRSignatureAlgorithm.addLongIdentifier("sig-alg", true); 2190 genCSRSignatureAlgorithm.addLongIdentifier("sigAlg", true); 2191 genCSRParser.addArgument(genCSRSignatureAlgorithm); 2192 2193 final BooleanArgument genCSRInheritExtensions = new BooleanArgument(null, 2194 "inherit-extensions", 1, 2195 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_INHERIT_EXT_DESC.get()); 2196 genCSRInheritExtensions.addLongIdentifier("inheritExtensions", true); 2197 genCSRParser.addArgument(genCSRInheritExtensions); 2198 2199 final StringArgument genCSRSubjectAltDNS = new StringArgument(null, 2200 "subject-alternative-name-dns", false, 0, 2201 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2202 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_DNS_DESC.get()); 2203 genCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 2204 genCSRSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 2205 genCSRSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 2206 genCSRSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 2207 genCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 2208 genCSRSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 2209 genCSRSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 2210 genCSRSubjectAltDNS.addLongIdentifier("san-dns", true); 2211 genCSRSubjectAltDNS.addLongIdentifier("sanDNS", true); 2212 genCSRSubjectAltDNS.addValueValidator( 2213 new IA5StringArgumentValueValidator(false)); 2214 genCSRParser.addArgument(genCSRSubjectAltDNS); 2215 2216 final StringArgument genCSRSubjectAltIP = new StringArgument(null, 2217 "subject-alternative-name-ip-address", false, 0, 2218 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2219 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_IP_DESC.get()); 2220 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 2221 true); 2222 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 2223 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 2224 genCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 2225 genCSRSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 2226 genCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 2227 genCSRSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 2228 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 2229 true); 2230 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 2231 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 2232 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 2233 genCSRSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 2234 genCSRSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 2235 genCSRSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 2236 genCSRSubjectAltIP.addLongIdentifier("subjectAltIP", true); 2237 genCSRSubjectAltIP.addLongIdentifier("san-ip-address", true); 2238 genCSRSubjectAltIP.addLongIdentifier("sanIPAddress", true); 2239 genCSRSubjectAltIP.addLongIdentifier("san-ip", true); 2240 genCSRSubjectAltIP.addLongIdentifier("sanIP", true); 2241 genCSRSubjectAltIP.addValueValidator( 2242 new IPAddressArgumentValueValidator(true, true)); 2243 genCSRParser.addArgument(genCSRSubjectAltIP); 2244 2245 final StringArgument genCSRSubjectAltEmail = new StringArgument(null, 2246 "subject-alternative-name-email-address", false, 0, 2247 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2248 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_EMAIL_DESC.get()); 2249 genCSRSubjectAltEmail.addLongIdentifier( 2250 "subjectAlternativeNameEmailAddress", true); 2251 genCSRSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 2252 true); 2253 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 2254 true); 2255 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 2256 true); 2257 genCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 2258 true); 2259 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 2260 genCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 2261 genCSRSubjectAltEmail.addLongIdentifier( 2262 "subject-alternative-email-address", true); 2263 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 2264 true); 2265 genCSRSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 2266 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 2267 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 2268 genCSRSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 2269 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 2270 genCSRSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 2271 genCSRSubjectAltEmail.addLongIdentifier("san-email-address", true); 2272 genCSRSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 2273 genCSRSubjectAltEmail.addLongIdentifier("san-email", true); 2274 genCSRSubjectAltEmail.addLongIdentifier("sanEmail", true); 2275 genCSRSubjectAltEmail.addValueValidator( 2276 new IA5StringArgumentValueValidator(false)); 2277 genCSRParser.addArgument(genCSRSubjectAltEmail); 2278 2279 final StringArgument genCSRSubjectAltURI = new StringArgument(null, 2280 "subject-alternative-name-uri", false, 0, 2281 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2282 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_URI_DESC.get()); 2283 genCSRSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 2284 genCSRSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 2285 genCSRSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 2286 genCSRSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 2287 genCSRSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 2288 genCSRSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 2289 genCSRSubjectAltURI.addLongIdentifier("subjectAltURI", true); 2290 genCSRSubjectAltURI.addLongIdentifier("san-uri", true); 2291 genCSRSubjectAltURI.addLongIdentifier("sanURI", true); 2292 genCSRParser.addArgument(genCSRSubjectAltURI); 2293 2294 final StringArgument genCSRSubjectAltOID = new StringArgument(null, 2295 "subject-alternative-name-oid", false, 0, 2296 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2297 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_OID_DESC.get()); 2298 genCSRSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 2299 genCSRSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 2300 genCSRSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 2301 genCSRSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 2302 genCSRSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 2303 genCSRSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 2304 genCSRSubjectAltOID.addLongIdentifier("subjectAltOID", true); 2305 genCSRSubjectAltOID.addLongIdentifier("san-oid", true); 2306 genCSRSubjectAltOID.addLongIdentifier("sanOID", true); 2307 genCSRSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2308 genCSRParser.addArgument(genCSRSubjectAltOID); 2309 2310 final BooleanValueArgument genCSRBasicConstraintsIsCA = 2311 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 2312 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_BC_IS_CA_DESC.get()); 2313 genCSRBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 2314 genCSRBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 2315 genCSRBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 2316 genCSRParser.addArgument(genCSRBasicConstraintsIsCA); 2317 2318 final IntegerArgument genCSRBasicConstraintsPathLength = 2319 new IntegerArgument(null, "basic-constraints-maximum-path-length", 2320 false, 1, null, 2321 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 2322 Integer.MAX_VALUE); 2323 genCSRBasicConstraintsPathLength.addLongIdentifier( 2324 "basicConstraintsMaximumPathLength", true); 2325 genCSRBasicConstraintsPathLength.addLongIdentifier( 2326 "basic-constraints-max-path-length", true); 2327 genCSRBasicConstraintsPathLength.addLongIdentifier( 2328 "basicConstraintsMaxPathLength", true); 2329 genCSRBasicConstraintsPathLength.addLongIdentifier( 2330 "basic-constraints-path-length", true); 2331 genCSRBasicConstraintsPathLength.addLongIdentifier( 2332 "basicConstraintsPathLength", true); 2333 genCSRBasicConstraintsPathLength.addLongIdentifier( 2334 "bc-maximum-path-length", true); 2335 genCSRBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 2336 true); 2337 genCSRBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 2338 true); 2339 genCSRBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 2340 true); 2341 genCSRBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 2342 genCSRBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 2343 genCSRParser.addArgument(genCSRBasicConstraintsPathLength); 2344 2345 final StringArgument genCSRKeyUsage = new StringArgument(null, "key-usage", 2346 false, 0, null, INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KU_DESC.get()); 2347 genCSRKeyUsage.addLongIdentifier("keyUsage", true); 2348 genCSRParser.addArgument(genCSRKeyUsage); 2349 2350 final StringArgument genCSRExtendedKeyUsage = new StringArgument(null, 2351 "extended-key-usage", false, 0, null, 2352 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_EKU_DESC.get()); 2353 genCSRExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 2354 genCSRParser.addArgument(genCSRExtendedKeyUsage); 2355 2356 final StringArgument genCSRExtension = new StringArgument(null, 2357 "extension", false, 0, null, 2358 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_EXT_DESC.get()); 2359 genCSRExtension.addLongIdentifier("ext", true); 2360 genCSRParser.addArgument(genCSRExtension); 2361 2362 final BooleanArgument genCSRDisplayCommand = new BooleanArgument(null, 2363 "display-keytool-command", 1, 2364 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 2365 genCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 2366 genCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 2367 genCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 2368 genCSRParser.addArgument(genCSRDisplayCommand); 2369 2370 genCSRParser.addRequiredArgumentSet(genCSRKeystorePassword, 2371 genCSRKeystorePasswordFile, genCSRPromptForKeystorePassword); 2372 genCSRParser.addExclusiveArgumentSet(genCSRKeystorePassword, 2373 genCSRKeystorePasswordFile, genCSRPromptForKeystorePassword); 2374 genCSRParser.addExclusiveArgumentSet(genCSRPKPassword, 2375 genCSRPKPasswordFile, genCSRPromptForPKPassword); 2376 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2377 genCSRKeyAlgorithm); 2378 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2379 genCSRKeySizeBits); 2380 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2381 genCSRSignatureAlgorithm); 2382 genCSRParser.addDependentArgumentSet(genCSRBasicConstraintsPathLength, 2383 genCSRBasicConstraintsIsCA); 2384 2385 final LinkedHashMap<String[],String> genCSRExamples = 2386 new LinkedHashMap<>(StaticUtils.computeMapCapacity(3)); 2387 genCSRExamples.put( 2388 new String[] 2389 { 2390 "generate-certificate-signing-request", 2391 "--keystore", getPlatformSpecificPath("config", "keystore"), 2392 "--keystore-password-file", 2393 getPlatformSpecificPath("config", "keystore.pin"), 2394 "--alias", "server-cert", 2395 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US" 2396 }, 2397 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_1.get()); 2398 genCSRExamples.put( 2399 new String[] 2400 { 2401 "generate-certificate-signing-request", 2402 "--keystore", getPlatformSpecificPath("config", "keystore"), 2403 "--keystore-password-file", 2404 getPlatformSpecificPath("config", "keystore.pin"), 2405 "--alias", "server-cert", 2406 "--use-existing-key-pair", 2407 "--inherit-extensions", 2408 "--output-file", "server-cert.csr" 2409 }, 2410 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_2.get()); 2411 genCSRExamples.put( 2412 new String[] 2413 { 2414 "generate-certificate-signing-request", 2415 "--keystore", getPlatformSpecificPath("config", "keystore"), 2416 "--keystore-password-file", 2417 getPlatformSpecificPath("config", "keystore.pin"), 2418 "--alias", "server-cert", 2419 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US", 2420 "--key-algorithm", "EC", 2421 "--key-size-bits", "256", 2422 "--signature-algorithm", "SHA256withECDSA", 2423 "--subject-alternative-name-dns", "ldap1.example.com", 2424 "--subject-alternative-name-dns", "ldap2.example.com", 2425 "--subject-alternative-name-ip-address", "1.2.3.4", 2426 "--subject-alternative-name-ip-address", "1.2.3.5", 2427 "--extended-key-usage", "server-auth", 2428 "--extended-key-usage", "client-auth", 2429 "--output-file", "server-cert.csr", 2430 "--display-keytool-command" 2431 }, 2432 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_3.get()); 2433 2434 final SubCommand genCSRSubCommand = new SubCommand( 2435 "generate-certificate-signing-request", 2436 INFO_MANAGE_CERTS_SC_GEN_CSR_DESC.get(), genCSRParser, 2437 genCSRExamples); 2438 genCSRSubCommand.addName("generateCertificateSigningRequest", true); 2439 genCSRSubCommand.addName("generate-certificate-request", true); 2440 genCSRSubCommand.addName("generateCertificateRequest", true); 2441 genCSRSubCommand.addName("generate-csr", true); 2442 genCSRSubCommand.addName("generateCSR", true); 2443 genCSRSubCommand.addName("certificate-signing-request", true); 2444 genCSRSubCommand.addName("certificateSigningRequest", true); 2445 genCSRSubCommand.addName("csr", true); 2446 genCSRSubCommand.addName("certreq", true); 2447 2448 parser.addSubCommand(genCSRSubCommand); 2449 2450 2451 // Define the "sign-certificate-signing-request" subcommand and all of its 2452 // arguments. 2453 final ArgumentParser signCSRParser = new ArgumentParser( 2454 "sign-certificate-signing-request", 2455 INFO_MANAGE_CERTS_SC_SIGN_CSR_DESC.get()); 2456 2457 final FileArgument signCSRInputFile = new FileArgument(null, 2458 "request-input-file", true, 1, null, 2459 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_INPUT_FILE_DESC.get(), true, true, 2460 true, false); 2461 signCSRInputFile.addLongIdentifier("requestInputFile", true); 2462 signCSRInputFile.addLongIdentifier("certificate-signing-request", true); 2463 signCSRInputFile.addLongIdentifier("certificateSigningRequest", true); 2464 signCSRInputFile.addLongIdentifier("input-file", false); 2465 signCSRInputFile.addLongIdentifier("inputFile", true); 2466 signCSRInputFile.addLongIdentifier("csr", true); 2467 signCSRParser.addArgument(signCSRInputFile); 2468 2469 final FileArgument signCSROutputFile = new FileArgument(null, 2470 "certificate-output-file", false, 1, null, 2471 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_OUTPUT_FILE_DESC.get(), false, true, 2472 true, false); 2473 signCSROutputFile.addLongIdentifier("certificateOutputFile", true); 2474 signCSROutputFile.addLongIdentifier("output-file", false); 2475 signCSROutputFile.addLongIdentifier("outputFile", true); 2476 signCSROutputFile.addLongIdentifier("certificate-file", true); 2477 signCSROutputFile.addLongIdentifier("certificateFile", true); 2478 signCSRParser.addArgument(signCSROutputFile); 2479 2480 final Set<String> signCSROutputFormatAllowedValues = StaticUtils.setOf( 2481 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 2482 final StringArgument signCSROutputFormat = new StringArgument(null, 2483 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 2484 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_FORMAT_DESC.get(), 2485 signCSROutputFormatAllowedValues, "PEM"); 2486 signCSROutputFormat.addLongIdentifier("outputFormat", true); 2487 signCSRParser.addArgument(signCSROutputFormat); 2488 2489 final FileArgument signCSRKeystore = new FileArgument(null, "keystore", 2490 true, 1, null, INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_DESC.get(), true, 2491 true, true, false); 2492 signCSRKeystore.addLongIdentifier("keystore-path", true); 2493 signCSRKeystore.addLongIdentifier("keystorePath", true); 2494 signCSRKeystore.addLongIdentifier("keystore-file", true); 2495 signCSRKeystore.addLongIdentifier("keystoreFile", true); 2496 signCSRParser.addArgument(signCSRKeystore); 2497 2498 final StringArgument signCSRKeystorePassword = new StringArgument(null, 2499 "keystore-password", false, 1, 2500 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2501 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_PW_DESC.get()); 2502 signCSRKeystorePassword.addLongIdentifier("keystorePassword", true); 2503 signCSRKeystorePassword.addLongIdentifier("keystore-passphrase", true); 2504 signCSRKeystorePassword.addLongIdentifier("keystorePassphrase", true); 2505 signCSRKeystorePassword.addLongIdentifier("keystore-pin", true); 2506 signCSRKeystorePassword.addLongIdentifier("keystorePIN", true); 2507 signCSRKeystorePassword.addLongIdentifier("storepass", true); 2508 signCSRKeystorePassword.setSensitive(true); 2509 signCSRParser.addArgument(signCSRKeystorePassword); 2510 2511 final FileArgument signCSRKeystorePasswordFile = new FileArgument(null, 2512 "keystore-password-file", false, 1, null, 2513 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_PW_FILE_DESC.get(), true, true, 2514 true, false); 2515 signCSRKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 2516 true); 2517 signCSRKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 2518 true); 2519 signCSRKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 2520 true); 2521 signCSRKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 2522 true); 2523 signCSRKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 2524 signCSRParser.addArgument(signCSRKeystorePasswordFile); 2525 2526 final BooleanArgument signCSRPromptForKeystorePassword = 2527 new BooleanArgument(null, "prompt-for-keystore-password", 2528 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PROMPT_FOR_KS_PW_DESC.get()); 2529 signCSRPromptForKeystorePassword.addLongIdentifier( 2530 "promptForKeystorePassword", true); 2531 signCSRPromptForKeystorePassword.addLongIdentifier( 2532 "prompt-for-keystore-passphrase", true); 2533 signCSRPromptForKeystorePassword.addLongIdentifier( 2534 "promptForKeystorePassphrase", true); 2535 signCSRPromptForKeystorePassword.addLongIdentifier( 2536 "prompt-for-keystore-pin", true); 2537 signCSRPromptForKeystorePassword.addLongIdentifier( 2538 "promptForKeystorePIN", true); 2539 signCSRParser.addArgument(signCSRPromptForKeystorePassword); 2540 2541 final StringArgument signCSRPKPassword = new StringArgument(null, 2542 "private-key-password", false, 1, 2543 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2544 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PK_PW_DESC.get()); 2545 signCSRPKPassword.addLongIdentifier("privateKeyPassword", true); 2546 signCSRPKPassword.addLongIdentifier("private-key-passphrase", true); 2547 signCSRPKPassword.addLongIdentifier("privateKeyPassphrase", true); 2548 signCSRPKPassword.addLongIdentifier("private-key-pin", true); 2549 signCSRPKPassword.addLongIdentifier("privateKeyPIN", true); 2550 signCSRPKPassword.addLongIdentifier("key-password", true); 2551 signCSRPKPassword.addLongIdentifier("keyPassword", true); 2552 signCSRPKPassword.addLongIdentifier("key-passphrase", true); 2553 signCSRPKPassword.addLongIdentifier("keyPassphrase", true); 2554 signCSRPKPassword.addLongIdentifier("key-pin", true); 2555 signCSRPKPassword.addLongIdentifier("keyPIN", true); 2556 signCSRPKPassword.addLongIdentifier("keypass", true); 2557 signCSRPKPassword.setSensitive(true); 2558 signCSRParser.addArgument(signCSRPKPassword); 2559 2560 final FileArgument signCSRPKPasswordFile = new FileArgument(null, 2561 "private-key-password-file", false, 1, null, 2562 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PK_PW_FILE_DESC.get(), true, true, 2563 true, false); 2564 signCSRPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 2565 signCSRPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 2566 true); 2567 signCSRPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 2568 true); 2569 signCSRPKPasswordFile.addLongIdentifier("private-key-pin-file", 2570 true); 2571 signCSRPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 2572 signCSRPKPasswordFile.addLongIdentifier("key-password-file", true); 2573 signCSRPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 2574 signCSRPKPasswordFile.addLongIdentifier("key-passphrase-file", 2575 true); 2576 signCSRPKPasswordFile.addLongIdentifier("keyPassphraseFile", 2577 true); 2578 signCSRPKPasswordFile.addLongIdentifier("key-pin-file", 2579 true); 2580 signCSRPKPasswordFile.addLongIdentifier("keyPINFile", true); 2581 signCSRParser.addArgument(signCSRPKPasswordFile); 2582 2583 final BooleanArgument signCSRPromptForPKPassword = 2584 new BooleanArgument(null, "prompt-for-private-key-password", 2585 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PROMPT_FOR_PK_PW_DESC.get()); 2586 signCSRPromptForPKPassword.addLongIdentifier( 2587 "promptForPrivateKeyPassword", true); 2588 signCSRPromptForPKPassword.addLongIdentifier( 2589 "prompt-for-private-key-passphrase", true); 2590 signCSRPromptForPKPassword.addLongIdentifier( 2591 "promptForPrivateKeyPassphrase", true); 2592 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 2593 true); 2594 signCSRPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 2595 true); 2596 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 2597 true); 2598 signCSRPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 2599 true); 2600 signCSRPromptForPKPassword.addLongIdentifier( 2601 "prompt-for-key-passphrase", true); 2602 signCSRPromptForPKPassword.addLongIdentifier( 2603 "promptForKeyPassphrase", true); 2604 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 2605 signCSRPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 2606 signCSRParser.addArgument(signCSRPromptForPKPassword); 2607 2608 final StringArgument signCSRKeystoreType = new StringArgument(null, 2609 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 2610 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_TYPE_DESC.get(), 2611 ALLOWED_KEYSTORE_TYPE_VALUES); 2612 signCSRKeystoreType.addLongIdentifier("key-store-type", true); 2613 signCSRKeystoreType.addLongIdentifier("keystoreType", true); 2614 signCSRKeystoreType.addLongIdentifier("keystore-format", true); 2615 signCSRKeystoreType.addLongIdentifier("key-store-format", true); 2616 signCSRKeystoreType.addLongIdentifier("keystoreFormat", true); 2617 signCSRKeystoreType.addLongIdentifier("storetype", true); 2618 signCSRParser.addArgument(signCSRKeystoreType); 2619 2620 final StringArgument signCSRAlias = new StringArgument(null, 2621 "signing-certificate-alias", 2622 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 2623 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_ALIAS_DESC.get()); 2624 signCSRAlias.addLongIdentifier("signingCertificateAlias", true); 2625 signCSRAlias.addLongIdentifier("signing-certificate-nickname", true); 2626 signCSRAlias.addLongIdentifier("signingCertificateNickname", true); 2627 signCSRAlias.addLongIdentifier("alias", true); 2628 signCSRAlias.addLongIdentifier("nickname", true); 2629 signCSRParser.addArgument(signCSRAlias); 2630 2631 final DNArgument signCSRSubjectDN = new DNArgument(null, "subject-dn", 2632 false, 1, null, 2633 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SUBJECT_DN_DESC.get()); 2634 signCSRSubjectDN.addLongIdentifier("subjectDN", true); 2635 signCSRSubjectDN.addLongIdentifier("subject", true); 2636 signCSRSubjectDN.addLongIdentifier("dname", true); 2637 signCSRParser.addArgument(signCSRSubjectDN); 2638 2639 final IntegerArgument signCSRDaysValid = new IntegerArgument(null, 2640 "days-valid", false, 1, null, 2641 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_DAYS_VALID_DESC.get(), 1, 2642 Integer.MAX_VALUE); 2643 signCSRDaysValid.addLongIdentifier("daysValid", true); 2644 signCSRDaysValid.addLongIdentifier("validity", true); 2645 signCSRParser.addArgument(signCSRDaysValid); 2646 2647 final TimestampArgument signCSRNotBefore = new TimestampArgument(null, 2648 "validity-start-time", false, 1, 2649 INFO_MANAGE_CERTS_PLACEHOLDER_TIMESTAMP.get(), 2650 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_VALIDITY_START_TIME_DESC.get( 2651 "20180102123456")); 2652 signCSRNotBefore.addLongIdentifier("validityStartTime", true); 2653 signCSRNotBefore.addLongIdentifier("not-before", true); 2654 signCSRNotBefore.addLongIdentifier("notBefore", true); 2655 signCSRParser.addArgument(signCSRNotBefore); 2656 2657 final StringArgument signCSRSignatureAlgorithm = new StringArgument(null, 2658 "signature-algorithm", false, 1, 2659 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2660 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SIG_ALG_DESC.get()); 2661 signCSRSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 2662 signCSRSignatureAlgorithm.addLongIdentifier("signature-alg", true); 2663 signCSRSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 2664 signCSRSignatureAlgorithm.addLongIdentifier("sig-alg", true); 2665 signCSRSignatureAlgorithm.addLongIdentifier("sigAlg", true); 2666 signCSRParser.addArgument(signCSRSignatureAlgorithm); 2667 2668 final BooleanArgument signCSRIncludeExtensions = new BooleanArgument(null, 2669 "include-requested-extensions", 1, 2670 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_INCLUDE_EXT_DESC.get()); 2671 signCSRIncludeExtensions.addLongIdentifier("includeRequestedExtensions", 2672 true); 2673 signCSRParser.addArgument(signCSRIncludeExtensions); 2674 2675 final StringArgument signCSRSubjectAltDNS = new StringArgument(null, 2676 "subject-alternative-name-dns", false, 0, 2677 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2678 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_DNS_DESC.get()); 2679 signCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 2680 signCSRSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 2681 signCSRSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 2682 signCSRSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 2683 signCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 2684 signCSRSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 2685 signCSRSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 2686 signCSRSubjectAltDNS.addLongIdentifier("san-dns", true); 2687 signCSRSubjectAltDNS.addLongIdentifier("sanDNS", true); 2688 signCSRSubjectAltDNS.addValueValidator( 2689 new IA5StringArgumentValueValidator(false)); 2690 signCSRParser.addArgument(signCSRSubjectAltDNS); 2691 2692 final StringArgument signCSRSubjectAltIP = new StringArgument(null, 2693 "subject-alternative-name-ip-address", false, 0, 2694 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2695 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_IP_DESC.get()); 2696 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 2697 true); 2698 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 2699 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 2700 signCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 2701 signCSRSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 2702 signCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 2703 signCSRSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 2704 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 2705 true); 2706 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 2707 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 2708 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 2709 signCSRSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 2710 signCSRSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 2711 signCSRSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 2712 signCSRSubjectAltIP.addLongIdentifier("subjectAltIP", true); 2713 signCSRSubjectAltIP.addLongIdentifier("san-ip-address", true); 2714 signCSRSubjectAltIP.addLongIdentifier("sanIPAddress", true); 2715 signCSRSubjectAltIP.addLongIdentifier("san-ip", true); 2716 signCSRSubjectAltIP.addLongIdentifier("sanIP", true); 2717 signCSRSubjectAltIP.addValueValidator( 2718 new IPAddressArgumentValueValidator(true, true)); 2719 signCSRParser.addArgument(signCSRSubjectAltIP); 2720 2721 final StringArgument signCSRSubjectAltEmail = new StringArgument(null, 2722 "subject-alternative-name-email-address", false, 0, 2723 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2724 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_EMAIL_DESC.get()); 2725 signCSRSubjectAltEmail.addLongIdentifier( 2726 "subjectAlternativeNameEmailAddress", true); 2727 signCSRSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 2728 true); 2729 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 2730 true); 2731 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 2732 true); 2733 signCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 2734 true); 2735 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 2736 signCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 2737 signCSRSubjectAltEmail.addLongIdentifier( 2738 "subject-alternative-email-address", true); 2739 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 2740 true); 2741 signCSRSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 2742 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 2743 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 2744 signCSRSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 2745 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 2746 signCSRSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 2747 signCSRSubjectAltEmail.addLongIdentifier("san-email-address", true); 2748 signCSRSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 2749 signCSRSubjectAltEmail.addLongIdentifier("san-email", true); 2750 signCSRSubjectAltEmail.addLongIdentifier("sanEmail", true); 2751 signCSRSubjectAltEmail.addValueValidator( 2752 new IA5StringArgumentValueValidator(false)); 2753 signCSRParser.addArgument(signCSRSubjectAltEmail); 2754 2755 final StringArgument signCSRSubjectAltURI = new StringArgument(null, 2756 "subject-alternative-name-uri", false, 0, 2757 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2758 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_URI_DESC.get()); 2759 signCSRSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 2760 signCSRSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 2761 signCSRSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 2762 signCSRSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 2763 signCSRSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 2764 signCSRSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 2765 signCSRSubjectAltURI.addLongIdentifier("subjectAltURI", true); 2766 signCSRSubjectAltURI.addLongIdentifier("san-uri", true); 2767 signCSRSubjectAltURI.addLongIdentifier("sanURI", true); 2768 signCSRParser.addArgument(signCSRSubjectAltURI); 2769 2770 final StringArgument signCSRSubjectAltOID = new StringArgument(null, 2771 "subject-alternative-name-oid", false, 0, 2772 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2773 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_OID_DESC.get()); 2774 signCSRSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 2775 signCSRSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 2776 signCSRSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 2777 signCSRSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 2778 signCSRSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 2779 signCSRSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 2780 signCSRSubjectAltOID.addLongIdentifier("subjectAltOID", true); 2781 signCSRSubjectAltOID.addLongIdentifier("san-oid", true); 2782 signCSRSubjectAltOID.addLongIdentifier("sanOID", true); 2783 signCSRSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2784 signCSRParser.addArgument(signCSRSubjectAltOID); 2785 2786 final StringArgument signCSRIssuerAltDNS = new StringArgument(null, 2787 "issuer-alternative-name-dns", false, 0, 2788 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2789 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_DNS_DESC.get()); 2790 signCSRIssuerAltDNS.addLongIdentifier("issuerAlternativeNameDNS", true); 2791 signCSRIssuerAltDNS.addLongIdentifier("issuer-alt-name-dns", true); 2792 signCSRIssuerAltDNS.addLongIdentifier("issuerAltNameDNS", true); 2793 signCSRIssuerAltDNS.addLongIdentifier("issuer-alternative-dns", true); 2794 signCSRIssuerAltDNS.addLongIdentifier("issuerAlternativeDNS", true); 2795 signCSRIssuerAltDNS.addLongIdentifier("issuer-alt-dns", true); 2796 signCSRIssuerAltDNS.addLongIdentifier("issuerAltDNS", true); 2797 signCSRIssuerAltDNS.addLongIdentifier("ian-dns", true); 2798 signCSRIssuerAltDNS.addLongIdentifier("ianDNS", true); 2799 signCSRIssuerAltDNS.addValueValidator( 2800 new IA5StringArgumentValueValidator(false)); 2801 signCSRParser.addArgument(signCSRIssuerAltDNS); 2802 2803 final StringArgument signCSRIssuerAltIP = new StringArgument(null, 2804 "issuer-alternative-name-ip-address", false, 0, 2805 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2806 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_IP_DESC.get()); 2807 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeNameIPAddress", 2808 true); 2809 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-name-ip", true); 2810 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeNameIP", true); 2811 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-name-ip-address", true); 2812 signCSRIssuerAltIP.addLongIdentifier("issuerAltNameIPAddress", true); 2813 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-name-ip", true); 2814 signCSRIssuerAltIP.addLongIdentifier("issuerAltNameIP", true); 2815 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-ip-address", 2816 true); 2817 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeIPAddress", true); 2818 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-ip", true); 2819 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeIP", true); 2820 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-ip-address", true); 2821 signCSRIssuerAltIP.addLongIdentifier("issuerAltIPAddress", true); 2822 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-ip", true); 2823 signCSRIssuerAltIP.addLongIdentifier("issuerAltIP", true); 2824 signCSRIssuerAltIP.addLongIdentifier("ian-ip-address", true); 2825 signCSRIssuerAltIP.addLongIdentifier("ianIPAddress", true); 2826 signCSRIssuerAltIP.addLongIdentifier("ian-ip", true); 2827 signCSRIssuerAltIP.addLongIdentifier("ianIP", true); 2828 signCSRIssuerAltIP.addValueValidator( 2829 new IPAddressArgumentValueValidator(true, true)); 2830 signCSRParser.addArgument(signCSRIssuerAltIP); 2831 2832 final StringArgument signCSRIssuerAltEmail = new StringArgument(null, 2833 "issuer-alternative-name-email-address", false, 0, 2834 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2835 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_EMAIL_DESC.get()); 2836 signCSRIssuerAltEmail.addLongIdentifier( 2837 "issuerAlternativeNameEmailAddress", true); 2838 signCSRIssuerAltEmail.addLongIdentifier("issuer-alternative-name-email", 2839 true); 2840 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeNameEmail", 2841 true); 2842 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-name-email-address", 2843 true); 2844 signCSRIssuerAltEmail.addLongIdentifier("issuerAltNameEmailAddress", 2845 true); 2846 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-name-email", true); 2847 signCSRIssuerAltEmail.addLongIdentifier("issuerAltNameEmail", true); 2848 signCSRIssuerAltEmail.addLongIdentifier( 2849 "issuer-alternative-email-address", true); 2850 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeEmailAddress", 2851 true); 2852 signCSRIssuerAltEmail.addLongIdentifier("issuer-alternative-email", true); 2853 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeEmail", true); 2854 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-email-address", true); 2855 signCSRIssuerAltEmail.addLongIdentifier("issuerAltEmailAddress", true); 2856 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-email", true); 2857 signCSRIssuerAltEmail.addLongIdentifier("issuerAltEmail", true); 2858 signCSRIssuerAltEmail.addLongIdentifier("ian-email-address", true); 2859 signCSRIssuerAltEmail.addLongIdentifier("ianEmailAddress", true); 2860 signCSRIssuerAltEmail.addLongIdentifier("ian-email", true); 2861 signCSRIssuerAltEmail.addLongIdentifier("ianEmail", true); 2862 signCSRIssuerAltEmail.addValueValidator( 2863 new IA5StringArgumentValueValidator(false)); 2864 signCSRParser.addArgument(signCSRIssuerAltEmail); 2865 2866 final StringArgument signCSRIssuerAltURI = new StringArgument(null, 2867 "issuer-alternative-name-uri", false, 0, 2868 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2869 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_URI_DESC.get()); 2870 signCSRIssuerAltURI.addLongIdentifier("issuerAlternativeNameURI", true); 2871 signCSRIssuerAltURI.addLongIdentifier("issuer-alt-name-uri", true); 2872 signCSRIssuerAltURI.addLongIdentifier("issuerAltNameURI", true); 2873 signCSRIssuerAltURI.addLongIdentifier("issuer-alternative-uri", true); 2874 signCSRIssuerAltURI.addLongIdentifier("issuerAlternativeURI", true); 2875 signCSRIssuerAltURI.addLongIdentifier("issuer-alt-uri", true); 2876 signCSRIssuerAltURI.addLongIdentifier("issuerAltURI", true); 2877 signCSRIssuerAltURI.addLongIdentifier("ian-uri", true); 2878 signCSRIssuerAltURI.addLongIdentifier("ianURI", true); 2879 signCSRParser.addArgument(signCSRIssuerAltURI); 2880 2881 final StringArgument signCSRIssuerAltOID = new StringArgument(null, 2882 "issuer-alternative-name-oid", false, 0, 2883 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2884 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_OID_DESC.get()); 2885 signCSRIssuerAltOID.addLongIdentifier("issuerAlternativeNameOID", true); 2886 signCSRIssuerAltOID.addLongIdentifier("issuer-alt-name-oid", true); 2887 signCSRIssuerAltOID.addLongIdentifier("issuerAltNameOID", true); 2888 signCSRIssuerAltOID.addLongIdentifier("issuer-alternative-oid", true); 2889 signCSRIssuerAltOID.addLongIdentifier("issuerAlternativeOID", true); 2890 signCSRIssuerAltOID.addLongIdentifier("issuer-alt-oid", true); 2891 signCSRIssuerAltOID.addLongIdentifier("issuerAltOID", true); 2892 signCSRIssuerAltOID.addLongIdentifier("ian-oid", true); 2893 signCSRIssuerAltOID.addLongIdentifier("ianOID", true); 2894 signCSRIssuerAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2895 signCSRParser.addArgument(signCSRIssuerAltOID); 2896 2897 final BooleanValueArgument signCSRBasicConstraintsIsCA = 2898 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 2899 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_BC_IS_CA_DESC.get()); 2900 signCSRBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 2901 signCSRBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 2902 signCSRBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 2903 signCSRParser.addArgument(signCSRBasicConstraintsIsCA); 2904 2905 final IntegerArgument signCSRBasicConstraintsPathLength = 2906 new IntegerArgument(null, "basic-constraints-maximum-path-length", 2907 false, 1, null, 2908 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 2909 Integer.MAX_VALUE); 2910 signCSRBasicConstraintsPathLength.addLongIdentifier( 2911 "basicConstraintsMaximumPathLength", true); 2912 signCSRBasicConstraintsPathLength.addLongIdentifier( 2913 "basic-constraints-max-path-length", true); 2914 signCSRBasicConstraintsPathLength.addLongIdentifier( 2915 "basicConstraintsMaxPathLength", true); 2916 signCSRBasicConstraintsPathLength.addLongIdentifier( 2917 "basic-constraints-path-length", true); 2918 signCSRBasicConstraintsPathLength.addLongIdentifier( 2919 "basicConstraintsPathLength", true); 2920 signCSRBasicConstraintsPathLength.addLongIdentifier( 2921 "bc-maximum-path-length", true); 2922 signCSRBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 2923 true); 2924 signCSRBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 2925 true); 2926 signCSRBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 2927 true); 2928 signCSRBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 2929 signCSRBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 2930 signCSRParser.addArgument(signCSRBasicConstraintsPathLength); 2931 2932 final StringArgument signCSRKeyUsage = new StringArgument(null, "key-usage", 2933 false, 0, null, INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KU_DESC.get()); 2934 signCSRKeyUsage.addLongIdentifier("keyUsage", true); 2935 signCSRParser.addArgument(signCSRKeyUsage); 2936 2937 final StringArgument signCSRExtendedKeyUsage = new StringArgument(null, 2938 "extended-key-usage", false, 0, null, 2939 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_EKU_DESC.get()); 2940 signCSRExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 2941 signCSRParser.addArgument(signCSRExtendedKeyUsage); 2942 2943 final StringArgument signCSRExtension = new StringArgument(null, 2944 "extension", false, 0, null, 2945 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_EXT_DESC.get()); 2946 signCSRExtension.addLongIdentifier("ext", true); 2947 signCSRParser.addArgument(signCSRExtension); 2948 2949 final BooleanArgument signCSRNoPrompt = new BooleanArgument(null, 2950 "no-prompt", 1, 2951 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_NO_PROMPT_DESC.get()); 2952 signCSRNoPrompt.addLongIdentifier("noPrompt", true); 2953 signCSRParser.addArgument(signCSRNoPrompt); 2954 2955 final BooleanArgument signCSRDisplayCommand = new BooleanArgument(null, 2956 "display-keytool-command", 1, 2957 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 2958 signCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 2959 signCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 2960 signCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 2961 signCSRParser.addArgument(signCSRDisplayCommand); 2962 2963 signCSRParser.addRequiredArgumentSet(signCSRKeystorePassword, 2964 signCSRKeystorePasswordFile, signCSRPromptForKeystorePassword); 2965 signCSRParser.addExclusiveArgumentSet(signCSRKeystorePassword, 2966 signCSRKeystorePasswordFile, signCSRPromptForKeystorePassword); 2967 signCSRParser.addExclusiveArgumentSet(signCSRPKPassword, 2968 signCSRPKPasswordFile, signCSRPromptForPKPassword); 2969 signCSRParser.addDependentArgumentSet(signCSRBasicConstraintsPathLength, 2970 signCSRBasicConstraintsIsCA); 2971 2972 final LinkedHashMap<String[],String> signCSRExamples = 2973 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 2974 signCSRExamples.put( 2975 new String[] 2976 { 2977 "sign-certificate-signing-request", 2978 "--request-input-file", "server-cert.csr", 2979 "--keystore", getPlatformSpecificPath("config", "keystore"), 2980 "--keystore-password-file", 2981 getPlatformSpecificPath("config", "keystore.pin"), 2982 "--signing-certificate-alias", "ca-cert", 2983 "--include-requested-extensions" 2984 }, 2985 INFO_MANAGE_CERTS_SC_SIGN_CSR_EXAMPLE_1.get( 2986 getPlatformSpecificPath("config", "keystore"))); 2987 signCSRExamples.put( 2988 new String[] 2989 { 2990 "sign-certificate-signing-request", 2991 "--request-input-file", "server-cert.csr", 2992 "--certificate-output-file", "server-cert.der", 2993 "--output-format", "DER", 2994 "--keystore", getPlatformSpecificPath("config", "keystore"), 2995 "--keystore-password-file", 2996 getPlatformSpecificPath("config", "keystore.pin"), 2997 "--signing-certificate-alias", "ca-cert", 2998 "--days-valid", "730", 2999 "--validity-start-time", "20170101000000", 3000 "--include-requested-extensions", 3001 "--issuer-alternative-name-email-address", "ca@example.com", 3002 }, 3003 INFO_MANAGE_CERTS_SC_SIGN_CSR_EXAMPLE_2.get( 3004 getPlatformSpecificPath("config", "keystore"))); 3005 3006 final SubCommand signCSRSubCommand = new SubCommand( 3007 "sign-certificate-signing-request", 3008 INFO_MANAGE_CERTS_SC_SIGN_CSR_DESC.get(), signCSRParser, 3009 signCSRExamples); 3010 signCSRSubCommand.addName("signCertificateSigningRequest", true); 3011 signCSRSubCommand.addName("sign-certificate-request", true); 3012 signCSRSubCommand.addName("signCertificateRequest", true); 3013 signCSRSubCommand.addName("sign-certificate", true); 3014 signCSRSubCommand.addName("signCertificate", true); 3015 signCSRSubCommand.addName("sign-csr", true); 3016 signCSRSubCommand.addName("signCSR", true); 3017 signCSRSubCommand.addName("sign", true); 3018 signCSRSubCommand.addName("gencert", true); 3019 3020 parser.addSubCommand(signCSRSubCommand); 3021 3022 3023 // Define the "change-certificate-alias" subcommand and all of its 3024 // arguments. 3025 final ArgumentParser changeAliasParser = new ArgumentParser( 3026 "change-certificate-alias", 3027 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_DESC.get()); 3028 3029 final FileArgument changeAliasKeystore = new FileArgument(null, "keystore", 3030 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_DESC.get(), 3031 true, true, true, false); 3032 changeAliasKeystore.addLongIdentifier("keystore-path", true); 3033 changeAliasKeystore.addLongIdentifier("keystorePath", true); 3034 changeAliasKeystore.addLongIdentifier("keystore-file", true); 3035 changeAliasKeystore.addLongIdentifier("keystoreFile", true); 3036 changeAliasParser.addArgument(changeAliasKeystore); 3037 3038 final StringArgument changeAliasKeystorePassword = new StringArgument(null, 3039 "keystore-password", false, 1, 3040 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3041 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_PW_DESC.get()); 3042 changeAliasKeystorePassword.addLongIdentifier("keystorePassword", true); 3043 changeAliasKeystorePassword.addLongIdentifier("keystore-passphrase", true); 3044 changeAliasKeystorePassword.addLongIdentifier("keystorePassphrase", true); 3045 changeAliasKeystorePassword.addLongIdentifier("keystore-pin", true); 3046 changeAliasKeystorePassword.addLongIdentifier("keystorePIN", true); 3047 changeAliasKeystorePassword.addLongIdentifier("storepass", true); 3048 changeAliasKeystorePassword.setSensitive(true); 3049 changeAliasParser.addArgument(changeAliasKeystorePassword); 3050 3051 final FileArgument changeAliasKeystorePasswordFile = new FileArgument(null, 3052 "keystore-password-file", false, 1, null, 3053 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_PW_FILE_DESC.get(), true, 3054 true, true, false); 3055 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 3056 true); 3057 changeAliasKeystorePasswordFile.addLongIdentifier( 3058 "keystore-passphrase-file", true); 3059 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 3060 true); 3061 changeAliasKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 3062 true); 3063 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 3064 changeAliasParser.addArgument(changeAliasKeystorePasswordFile); 3065 3066 final BooleanArgument changeAliasPromptForKeystorePassword = 3067 new BooleanArgument(null, "prompt-for-keystore-password", 3068 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PROMPT_FOR_KS_PW_DESC.get()); 3069 changeAliasPromptForKeystorePassword.addLongIdentifier( 3070 "promptForKeystorePassword", true); 3071 changeAliasPromptForKeystorePassword.addLongIdentifier( 3072 "prompt-for-keystore-passphrase", true); 3073 changeAliasPromptForKeystorePassword.addLongIdentifier( 3074 "promptForKeystorePassphrase", true); 3075 changeAliasPromptForKeystorePassword.addLongIdentifier( 3076 "prompt-for-keystore-pin", true); 3077 changeAliasPromptForKeystorePassword.addLongIdentifier( 3078 "promptForKeystorePIN", true); 3079 changeAliasParser.addArgument(changeAliasPromptForKeystorePassword); 3080 3081 final StringArgument changeAliasPKPassword = new StringArgument(null, 3082 "private-key-password", false, 1, 3083 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3084 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PK_PW_DESC.get()); 3085 changeAliasPKPassword.addLongIdentifier("privateKeyPassword", true); 3086 changeAliasPKPassword.addLongIdentifier("private-key-passphrase", true); 3087 changeAliasPKPassword.addLongIdentifier("privateKeyPassphrase", true); 3088 changeAliasPKPassword.addLongIdentifier("private-key-pin", true); 3089 changeAliasPKPassword.addLongIdentifier("privateKeyPIN", true); 3090 changeAliasPKPassword.addLongIdentifier("key-password", true); 3091 changeAliasPKPassword.addLongIdentifier("keyPassword", true); 3092 changeAliasPKPassword.addLongIdentifier("key-passphrase", true); 3093 changeAliasPKPassword.addLongIdentifier("keyPassphrase", true); 3094 changeAliasPKPassword.addLongIdentifier("key-pin", true); 3095 changeAliasPKPassword.addLongIdentifier("keyPIN", true); 3096 changeAliasPKPassword.addLongIdentifier("keypass", true); 3097 changeAliasPKPassword.setSensitive(true); 3098 changeAliasParser.addArgument(changeAliasPKPassword); 3099 3100 final FileArgument changeAliasPKPasswordFile = new FileArgument(null, 3101 "private-key-password-file", false, 1, null, 3102 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PK_PW_FILE_DESC.get(), true, 3103 true, true, false); 3104 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 3105 changeAliasPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 3106 true); 3107 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 3108 true); 3109 changeAliasPKPasswordFile.addLongIdentifier("private-key-pin-file", 3110 true); 3111 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 3112 changeAliasPKPasswordFile.addLongIdentifier("key-password-file", true); 3113 changeAliasPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 3114 changeAliasPKPasswordFile.addLongIdentifier("key-passphrase-file", 3115 true); 3116 changeAliasPKPasswordFile.addLongIdentifier("keyPassphraseFile", 3117 true); 3118 changeAliasPKPasswordFile.addLongIdentifier("key-pin-file", 3119 true); 3120 changeAliasPKPasswordFile.addLongIdentifier("keyPINFile", true); 3121 changeAliasParser.addArgument(changeAliasPKPasswordFile); 3122 3123 final BooleanArgument changeAliasPromptForPKPassword = 3124 new BooleanArgument(null, "prompt-for-private-key-password", 3125 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PROMPT_FOR_PK_PW_DESC.get()); 3126 changeAliasPromptForPKPassword.addLongIdentifier( 3127 "promptForPrivateKeyPassword", true); 3128 changeAliasPromptForPKPassword.addLongIdentifier( 3129 "prompt-for-private-key-passphrase", true); 3130 changeAliasPromptForPKPassword.addLongIdentifier( 3131 "promptForPrivateKeyPassphrase", true); 3132 changeAliasPromptForPKPassword.addLongIdentifier( 3133 "prompt-for-private-key-pin", true); 3134 changeAliasPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 3135 true); 3136 changeAliasPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 3137 true); 3138 changeAliasPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 3139 true); 3140 changeAliasPromptForPKPassword.addLongIdentifier( 3141 "prompt-for-key-passphrase", true); 3142 changeAliasPromptForPKPassword.addLongIdentifier( 3143 "promptForKeyPassphrase", true); 3144 changeAliasPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", 3145 true); 3146 changeAliasPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 3147 changeAliasParser.addArgument(changeAliasPromptForPKPassword); 3148 3149 final StringArgument changeAliasKeystoreType = new StringArgument(null, 3150 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3151 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_TYPE_DESC.get(), 3152 ALLOWED_KEYSTORE_TYPE_VALUES); 3153 changeAliasKeystoreType.addLongIdentifier("key-store-type", true); 3154 changeAliasKeystoreType.addLongIdentifier("keystoreType", true); 3155 changeAliasKeystoreType.addLongIdentifier("keystore-format", true); 3156 changeAliasKeystoreType.addLongIdentifier("key-store-format", true); 3157 changeAliasKeystoreType.addLongIdentifier("keystoreFormat", true); 3158 changeAliasKeystoreType.addLongIdentifier("storetype", true); 3159 changeAliasParser.addArgument(changeAliasKeystoreType); 3160 3161 final StringArgument changeAliasCurrentAlias = new StringArgument(null, 3162 "current-alias", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3163 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_CURRENT_ALIAS_DESC.get()); 3164 changeAliasCurrentAlias.addLongIdentifier("currentAlias", true); 3165 changeAliasCurrentAlias.addLongIdentifier("old-alias", true); 3166 changeAliasCurrentAlias.addLongIdentifier("oldAlias", true); 3167 changeAliasCurrentAlias.addLongIdentifier("source-alias", true); 3168 changeAliasCurrentAlias.addLongIdentifier("sourceAlias", true); 3169 changeAliasCurrentAlias.addLongIdentifier("alias", true); 3170 changeAliasCurrentAlias.addLongIdentifier("current-nickname", true); 3171 changeAliasCurrentAlias.addLongIdentifier("currentNickname", true); 3172 changeAliasCurrentAlias.addLongIdentifier("old-nickname", true); 3173 changeAliasCurrentAlias.addLongIdentifier("oldNickname", true); 3174 changeAliasCurrentAlias.addLongIdentifier("source-nickname", true); 3175 changeAliasCurrentAlias.addLongIdentifier("sourceNickname", true); 3176 changeAliasCurrentAlias.addLongIdentifier("nickname", true); 3177 changeAliasCurrentAlias.addLongIdentifier("from", false); 3178 changeAliasParser.addArgument(changeAliasCurrentAlias); 3179 3180 final StringArgument changeAliasNewAlias = new StringArgument(null, 3181 "new-alias", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3182 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_NEW_ALIAS_DESC.get()); 3183 changeAliasNewAlias.addLongIdentifier("newAlias", true); 3184 changeAliasNewAlias.addLongIdentifier("destination-alias", true); 3185 changeAliasNewAlias.addLongIdentifier("destinationAlias", true); 3186 changeAliasNewAlias.addLongIdentifier("new-nickname", true); 3187 changeAliasNewAlias.addLongIdentifier("newNickname", true); 3188 changeAliasNewAlias.addLongIdentifier("destination-nickname", true); 3189 changeAliasNewAlias.addLongIdentifier("destinationNickname", true); 3190 changeAliasNewAlias.addLongIdentifier("to", false); 3191 changeAliasParser.addArgument(changeAliasNewAlias); 3192 3193 final BooleanArgument changeAliasDisplayCommand = new BooleanArgument(null, 3194 "display-keytool-command", 1, 3195 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_DISPLAY_COMMAND_DESC.get()); 3196 changeAliasDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3197 changeAliasDisplayCommand.addLongIdentifier("show-keytool-command", true); 3198 changeAliasDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3199 changeAliasParser.addArgument(changeAliasDisplayCommand); 3200 3201 changeAliasParser.addRequiredArgumentSet(changeAliasKeystorePassword, 3202 changeAliasKeystorePasswordFile, changeAliasPromptForKeystorePassword); 3203 changeAliasParser.addExclusiveArgumentSet(changeAliasKeystorePassword, 3204 changeAliasKeystorePasswordFile, changeAliasPromptForKeystorePassword); 3205 changeAliasParser.addExclusiveArgumentSet(changeAliasPKPassword, 3206 changeAliasPKPasswordFile, changeAliasPromptForPKPassword); 3207 3208 final LinkedHashMap<String[],String> changeAliasExamples = 3209 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3210 changeAliasExamples.put( 3211 new String[] 3212 { 3213 "change-certificate-alias", 3214 "--keystore", getPlatformSpecificPath("config", "keystore"), 3215 "--keystore-password-file", 3216 getPlatformSpecificPath("config", "keystore.pin"), 3217 "--current-alias", "server-cert", 3218 "--new-alias", "server-certificate", 3219 "--display-keytool-command" 3220 }, 3221 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_EXAMPLE_1.get()); 3222 3223 final SubCommand changeAliasSubCommand = new SubCommand( 3224 "change-certificate-alias", 3225 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_DESC.get(), changeAliasParser, 3226 changeAliasExamples); 3227 changeAliasSubCommand.addName("changeCertificateAlias", true); 3228 changeAliasSubCommand.addName("change-alias", true); 3229 changeAliasSubCommand.addName("changeAlias", true); 3230 changeAliasSubCommand.addName("rename-certificate", true); 3231 changeAliasSubCommand.addName("renameCertificate", true); 3232 changeAliasSubCommand.addName("rename", true); 3233 3234 parser.addSubCommand(changeAliasSubCommand); 3235 3236 3237 // Define the "change-keystore-password" subcommand and all of its 3238 // arguments. 3239 final ArgumentParser changeKSPWParser = new ArgumentParser( 3240 "change-keystore-password", 3241 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_DESC.get()); 3242 3243 final FileArgument changeKSPWKeystore = new FileArgument(null, "keystore", 3244 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_KS_DESC.get(), 3245 true, true, true, false); 3246 changeKSPWKeystore.addLongIdentifier("keystore-path", true); 3247 changeKSPWKeystore.addLongIdentifier("keystorePath", true); 3248 changeKSPWKeystore.addLongIdentifier("keystore-file", true); 3249 changeKSPWKeystore.addLongIdentifier("keystoreFile", true); 3250 changeKSPWParser.addArgument(changeKSPWKeystore); 3251 3252 final StringArgument changeKSPWCurrentPassword = new StringArgument(null, 3253 "current-keystore-password", false, 1, 3254 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3255 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_CURRENT_PW_DESC.get()); 3256 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePassword", 3257 true); 3258 changeKSPWCurrentPassword.addLongIdentifier("current-keystore-passphrase", 3259 true); 3260 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePassphrase", 3261 true); 3262 changeKSPWCurrentPassword.addLongIdentifier("current-keystore-pin", true); 3263 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePIN", true); 3264 changeKSPWCurrentPassword.addLongIdentifier("storepass", true); 3265 changeKSPWCurrentPassword.setSensitive(true); 3266 changeKSPWParser.addArgument(changeKSPWCurrentPassword); 3267 3268 final FileArgument changeKSPWCurrentPasswordFile = new FileArgument(null, 3269 "current-keystore-password-file", false, 1, null, 3270 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_CURRENT_PW_FILE_DESC.get(), true, 3271 true, true, false); 3272 changeKSPWCurrentPasswordFile.addLongIdentifier( 3273 "currentKeystorePasswordFile", true); 3274 changeKSPWCurrentPasswordFile.addLongIdentifier( 3275 "current-keystore-passphrase-file", true); 3276 changeKSPWCurrentPasswordFile.addLongIdentifier( 3277 "currentKeystorePassphraseFile", true); 3278 changeKSPWCurrentPasswordFile.addLongIdentifier("current-keystore-pin-file", 3279 true); 3280 changeKSPWCurrentPasswordFile.addLongIdentifier("currentKeystorePINFile", 3281 true); 3282 changeKSPWParser.addArgument(changeKSPWCurrentPasswordFile); 3283 3284 final BooleanArgument changeKSPWPromptForCurrentPassword = 3285 new BooleanArgument(null, "prompt-for-current-keystore-password", 3286 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_PROMPT_FOR_CURRENT_PW_DESC.get()); 3287 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3288 "promptForCurrentKeystorePassword", true); 3289 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3290 "prompt-for-current-keystore-passphrase", true); 3291 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3292 "promptForCurrentKeystorePassphrase", true); 3293 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3294 "prompt-for-current-keystore-pin", true); 3295 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3296 "promptForCurrentKeystorePIN", true); 3297 changeKSPWParser.addArgument(changeKSPWPromptForCurrentPassword); 3298 3299 final StringArgument changeKSPWNewPassword = new StringArgument(null, 3300 "new-keystore-password", false, 1, 3301 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3302 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_NEW_PW_DESC.get()); 3303 changeKSPWNewPassword.addLongIdentifier("newKeystorePassword", 3304 true); 3305 changeKSPWNewPassword.addLongIdentifier("new-keystore-passphrase", 3306 true); 3307 changeKSPWNewPassword.addLongIdentifier("newKeystorePassphrase", 3308 true); 3309 changeKSPWNewPassword.addLongIdentifier("new-keystore-pin", true); 3310 changeKSPWNewPassword.addLongIdentifier("newKeystorePIN", true); 3311 changeKSPWNewPassword.addLongIdentifier("new", true); 3312 changeKSPWNewPassword.setSensitive(true); 3313 changeKSPWParser.addArgument(changeKSPWNewPassword); 3314 3315 final FileArgument changeKSPWNewPasswordFile = new FileArgument(null, 3316 "new-keystore-password-file", false, 1, null, 3317 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_NEW_PW_FILE_DESC.get(), true, 3318 true, true, false); 3319 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePasswordFile", 3320 true); 3321 changeKSPWNewPasswordFile.addLongIdentifier("new-keystore-passphrase-file", 3322 true); 3323 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePassphraseFile", 3324 true); 3325 changeKSPWNewPasswordFile.addLongIdentifier("new-keystore-pin-file", true); 3326 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePINFile", true); 3327 changeKSPWParser.addArgument(changeKSPWNewPasswordFile); 3328 3329 final BooleanArgument changeKSPWPromptForNewPassword = 3330 new BooleanArgument(null, "prompt-for-new-keystore-password", 3331 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_PROMPT_FOR_NEW_PW_DESC.get()); 3332 changeKSPWPromptForNewPassword.addLongIdentifier( 3333 "promptForNewKeystorePassword", true); 3334 changeKSPWPromptForNewPassword.addLongIdentifier( 3335 "prompt-for-new-keystore-passphrase", true); 3336 changeKSPWPromptForNewPassword.addLongIdentifier( 3337 "promptForNewKeystorePassphrase", true); 3338 changeKSPWPromptForNewPassword.addLongIdentifier( 3339 "prompt-for-new-keystore-pin", true); 3340 changeKSPWPromptForNewPassword.addLongIdentifier( 3341 "promptForNewKeystorePIN", true); 3342 changeKSPWParser.addArgument(changeKSPWPromptForNewPassword); 3343 3344 final BooleanArgument changeKSPWDisplayCommand = new BooleanArgument(null, 3345 "display-keytool-command", 1, 3346 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_DISPLAY_COMMAND_DESC.get()); 3347 changeKSPWDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3348 changeKSPWDisplayCommand.addLongIdentifier("show-keytool-command", true); 3349 changeKSPWDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3350 changeKSPWParser.addArgument(changeKSPWDisplayCommand); 3351 3352 changeKSPWParser.addRequiredArgumentSet(changeKSPWCurrentPassword, 3353 changeKSPWCurrentPasswordFile, changeKSPWPromptForCurrentPassword); 3354 changeKSPWParser.addExclusiveArgumentSet(changeKSPWCurrentPassword, 3355 changeKSPWCurrentPasswordFile, changeKSPWPromptForCurrentPassword); 3356 changeKSPWParser.addRequiredArgumentSet(changeKSPWNewPassword, 3357 changeKSPWNewPasswordFile, changeKSPWPromptForNewPassword); 3358 changeKSPWParser.addExclusiveArgumentSet(changeKSPWNewPassword, 3359 changeKSPWNewPasswordFile, changeKSPWPromptForNewPassword); 3360 3361 final LinkedHashMap<String[],String> changeKSPWExamples = 3362 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3363 changeKSPWExamples.put( 3364 new String[] 3365 { 3366 "change-keystore-password", 3367 "--keystore", getPlatformSpecificPath("config", "keystore"), 3368 "--current-keystore-password-file", 3369 getPlatformSpecificPath("config", "current.pin"), 3370 "--new-keystore-password-file", 3371 getPlatformSpecificPath("config", "new.pin"), 3372 "--display-keytool-command" 3373 }, 3374 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_EXAMPLE_1.get( 3375 getPlatformSpecificPath("config", "keystore"), 3376 getPlatformSpecificPath("config", "current.pin"), 3377 getPlatformSpecificPath("config", "new.pin"))); 3378 3379 final SubCommand changeKSPWSubCommand = new SubCommand( 3380 "change-keystore-password", 3381 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_DESC.get(), changeKSPWParser, 3382 changeKSPWExamples); 3383 changeKSPWSubCommand.addName("changeKeystorePassword", true); 3384 changeKSPWSubCommand.addName("change-keystore-passphrase", true); 3385 changeKSPWSubCommand.addName("changeKeystorePassphrase", true); 3386 changeKSPWSubCommand.addName("change-keystore-pin", true); 3387 changeKSPWSubCommand.addName("changeKeystorePIN", true); 3388 changeKSPWSubCommand.addName("storepasswd", true); 3389 3390 parser.addSubCommand(changeKSPWSubCommand); 3391 3392 3393 // Define the "change-private-key-password" subcommand and all of its 3394 // arguments. 3395 final ArgumentParser changePKPWParser = new ArgumentParser( 3396 "change-private-key-password", 3397 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_DESC.get()); 3398 3399 final FileArgument changePKPWKeystore = new FileArgument(null, "keystore", 3400 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_DESC.get(), 3401 true, true, true, false); 3402 changePKPWKeystore.addLongIdentifier("keystore-path", true); 3403 changePKPWKeystore.addLongIdentifier("keystorePath", true); 3404 changePKPWKeystore.addLongIdentifier("keystore-file", true); 3405 changePKPWKeystore.addLongIdentifier("keystoreFile", true); 3406 changePKPWParser.addArgument(changePKPWKeystore); 3407 3408 final StringArgument changePKPWKeystorePassword = new StringArgument(null, 3409 "keystore-password", false, 1, 3410 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3411 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_PW_DESC.get()); 3412 changePKPWKeystorePassword.addLongIdentifier("keystorePassword", true); 3413 changePKPWKeystorePassword.addLongIdentifier("keystore-passphrase", true); 3414 changePKPWKeystorePassword.addLongIdentifier("keystorePassphrase", true); 3415 changePKPWKeystorePassword.addLongIdentifier("keystore-pin", true); 3416 changePKPWKeystorePassword.addLongIdentifier("keystorePIN", true); 3417 changePKPWKeystorePassword.addLongIdentifier("storepass", true); 3418 changePKPWKeystorePassword.setSensitive(true); 3419 changePKPWParser.addArgument(changePKPWKeystorePassword); 3420 3421 final FileArgument changePKPWKeystorePasswordFile = new FileArgument(null, 3422 "keystore-password-file", false, 1, null, 3423 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_PW_FILE_DESC.get(), true, 3424 true, true, false); 3425 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 3426 true); 3427 changePKPWKeystorePasswordFile.addLongIdentifier( 3428 "keystore-passphrase-file", true); 3429 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 3430 true); 3431 changePKPWKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 3432 true); 3433 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 3434 changePKPWParser.addArgument(changePKPWKeystorePasswordFile); 3435 3436 final BooleanArgument changePKPWPromptForKeystorePassword = 3437 new BooleanArgument(null, "prompt-for-keystore-password", 3438 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_KS_PW_DESC.get()); 3439 changePKPWPromptForKeystorePassword.addLongIdentifier( 3440 "promptForKeystorePassword", true); 3441 changePKPWPromptForKeystorePassword.addLongIdentifier( 3442 "prompt-for-keystore-passphrase", true); 3443 changePKPWPromptForKeystorePassword.addLongIdentifier( 3444 "promptForKeystorePassphrase", true); 3445 changePKPWPromptForKeystorePassword.addLongIdentifier( 3446 "prompt-for-keystore-pin", true); 3447 changePKPWPromptForKeystorePassword.addLongIdentifier( 3448 "promptForKeystorePIN", true); 3449 changePKPWParser.addArgument(changePKPWPromptForKeystorePassword); 3450 3451 final StringArgument changePKPWKeystoreType = new StringArgument(null, 3452 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3453 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_TYPE_DESC.get(), 3454 ALLOWED_KEYSTORE_TYPE_VALUES); 3455 changePKPWKeystoreType.addLongIdentifier("key-store-type", true); 3456 changePKPWKeystoreType.addLongIdentifier("keystoreType", true); 3457 changePKPWKeystoreType.addLongIdentifier("keystore-format", true); 3458 changePKPWKeystoreType.addLongIdentifier("key-store-format", true); 3459 changePKPWKeystoreType.addLongIdentifier("keystoreFormat", true); 3460 changePKPWKeystoreType.addLongIdentifier("storetype", true); 3461 changePKPWParser.addArgument(changePKPWKeystoreType); 3462 3463 final StringArgument changePKPWAlias = new StringArgument(null, "alias", 3464 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3465 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_ALIAS_DESC.get()); 3466 changePKPWAlias.addLongIdentifier("nickname", true); 3467 changePKPWParser.addArgument(changePKPWAlias); 3468 3469 final StringArgument changePKPWCurrentPassword = new StringArgument(null, 3470 "current-private-key-password", false, 1, 3471 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3472 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_CURRENT_PW_DESC.get()); 3473 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPassword", 3474 true); 3475 changePKPWCurrentPassword.addLongIdentifier( 3476 "current-private-key-passphrase", true); 3477 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPassphrase", 3478 true); 3479 changePKPWCurrentPassword.addLongIdentifier("current-private-key-pin", 3480 true); 3481 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPIN", true); 3482 changePKPWCurrentPassword.addLongIdentifier("keypass", true); 3483 changePKPWCurrentPassword.setSensitive(true); 3484 changePKPWParser.addArgument(changePKPWCurrentPassword); 3485 3486 final FileArgument changePKPWCurrentPasswordFile = new FileArgument(null, 3487 "current-private-key-password-file", false, 1, null, 3488 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_CURRENT_PW_FILE_DESC.get(), true, 3489 true, true, false); 3490 changePKPWCurrentPasswordFile.addLongIdentifier( 3491 "currentPrivateKeyPasswordFile", true); 3492 changePKPWCurrentPasswordFile.addLongIdentifier( 3493 "current-private-key-passphrase-file", true); 3494 changePKPWCurrentPasswordFile.addLongIdentifier( 3495 "currentPrivateKeyPassphraseFile", true); 3496 changePKPWCurrentPasswordFile.addLongIdentifier( 3497 "current-private-key-pin-file", true); 3498 changePKPWCurrentPasswordFile.addLongIdentifier("currentPrivateKeyPINFile", 3499 true); 3500 changePKPWParser.addArgument(changePKPWCurrentPasswordFile); 3501 3502 final BooleanArgument changePKPWPromptForCurrentPassword = 3503 new BooleanArgument(null, "prompt-for-current-private-key-password", 3504 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_CURRENT_PW_DESC.get()); 3505 changePKPWPromptForCurrentPassword.addLongIdentifier( 3506 "promptForCurrentPrivateKeyPassword", true); 3507 changePKPWPromptForCurrentPassword.addLongIdentifier( 3508 "prompt-for-current-private-key-passphrase", true); 3509 changePKPWPromptForCurrentPassword.addLongIdentifier( 3510 "promptForCurrentPrivateKeyPassphrase", true); 3511 changePKPWPromptForCurrentPassword.addLongIdentifier( 3512 "prompt-for-current-private-key-pin", true); 3513 changePKPWPromptForCurrentPassword.addLongIdentifier( 3514 "promptForCurrentPrivateKeyPIN", true); 3515 changePKPWParser.addArgument(changePKPWPromptForCurrentPassword); 3516 3517 final StringArgument changePKPWNewPassword = new StringArgument(null, 3518 "new-private-key-password", false, 1, 3519 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3520 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_NEW_PW_DESC.get()); 3521 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPassword", 3522 true); 3523 changePKPWNewPassword.addLongIdentifier("new-private-key-passphrase", true); 3524 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPassphrase", true); 3525 changePKPWNewPassword.addLongIdentifier("new-private-key-pin", true); 3526 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPIN", true); 3527 changePKPWNewPassword.addLongIdentifier("new", true); 3528 changePKPWNewPassword.setSensitive(true); 3529 changePKPWParser.addArgument(changePKPWNewPassword); 3530 3531 final FileArgument changePKPWNewPasswordFile = new FileArgument(null, 3532 "new-private-key-password-file", false, 1, null, 3533 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_NEW_PW_FILE_DESC.get(), true, 3534 true, true, false); 3535 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPasswordFile", 3536 true); 3537 changePKPWNewPasswordFile.addLongIdentifier( 3538 "new-private-key-passphrase-file", true); 3539 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPassphraseFile", 3540 true); 3541 changePKPWNewPasswordFile.addLongIdentifier("new-private-key-pin-file", 3542 true); 3543 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPINFile", true); 3544 changePKPWParser.addArgument(changePKPWNewPasswordFile); 3545 3546 final BooleanArgument changePKPWPromptForNewPassword = 3547 new BooleanArgument(null, "prompt-for-new-private-key-password", 3548 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_NEW_PW_DESC.get()); 3549 changePKPWPromptForNewPassword.addLongIdentifier( 3550 "promptForNewPrivateKeyPassword", true); 3551 changePKPWPromptForNewPassword.addLongIdentifier( 3552 "prompt-for-new-private-key-passphrase", true); 3553 changePKPWPromptForNewPassword.addLongIdentifier( 3554 "promptForNewPrivateKeyPassphrase", true); 3555 changePKPWPromptForNewPassword.addLongIdentifier( 3556 "prompt-for-new-private-key-pin", true); 3557 changePKPWPromptForNewPassword.addLongIdentifier( 3558 "promptForNewPrivateKeyPIN", true); 3559 changePKPWParser.addArgument(changePKPWPromptForNewPassword); 3560 3561 final BooleanArgument changePKPWDisplayCommand = new BooleanArgument(null, 3562 "display-keytool-command", 1, 3563 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_DISPLAY_COMMAND_DESC.get()); 3564 changePKPWDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3565 changePKPWDisplayCommand.addLongIdentifier("show-keytool-command", true); 3566 changePKPWDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3567 changePKPWParser.addArgument(changePKPWDisplayCommand); 3568 3569 changePKPWParser.addRequiredArgumentSet(changePKPWKeystorePassword, 3570 changePKPWKeystorePasswordFile, changePKPWPromptForKeystorePassword); 3571 changePKPWParser.addExclusiveArgumentSet(changePKPWKeystorePassword, 3572 changePKPWKeystorePasswordFile, changePKPWPromptForKeystorePassword); 3573 changePKPWParser.addRequiredArgumentSet(changePKPWCurrentPassword, 3574 changePKPWCurrentPasswordFile, changePKPWPromptForCurrentPassword); 3575 changePKPWParser.addExclusiveArgumentSet(changePKPWCurrentPassword, 3576 changePKPWCurrentPasswordFile, changePKPWPromptForCurrentPassword); 3577 changePKPWParser.addRequiredArgumentSet(changePKPWNewPassword, 3578 changePKPWNewPasswordFile, changePKPWPromptForNewPassword); 3579 changePKPWParser.addExclusiveArgumentSet(changePKPWNewPassword, 3580 changePKPWNewPasswordFile, changePKPWPromptForNewPassword); 3581 3582 final LinkedHashMap<String[],String> changePKPWExamples = 3583 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3584 changePKPWExamples.put( 3585 new String[] 3586 { 3587 "change-private-key-password", 3588 "--keystore", getPlatformSpecificPath("config", "keystore"), 3589 "--keystore-password-file", 3590 getPlatformSpecificPath("config", "keystore.pin"), 3591 "--alias", "server-cert", 3592 "--current-private-key-password-file", 3593 getPlatformSpecificPath("config", "current.pin"), 3594 "--new-private-key-password-file", 3595 getPlatformSpecificPath("config", "new.pin"), 3596 "--display-keytool-command" 3597 }, 3598 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_EXAMPLE_1.get( 3599 getPlatformSpecificPath("config", "keystore"), 3600 getPlatformSpecificPath("config", "current.pin"), 3601 getPlatformSpecificPath("config", "new.pin"))); 3602 3603 final SubCommand changePKPWSubCommand = new SubCommand( 3604 "change-private-key-password", 3605 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_DESC.get(), changePKPWParser, 3606 changePKPWExamples); 3607 changePKPWSubCommand.addName("changePrivateKeyPassword", true); 3608 changePKPWSubCommand.addName("change-private-key-passphrase", true); 3609 changePKPWSubCommand.addName("changePrivateKeyPassphrase", true); 3610 changePKPWSubCommand.addName("change-private-key-pin", true); 3611 changePKPWSubCommand.addName("changePrivateKeyPIN", true); 3612 changePKPWSubCommand.addName("change-key-password", true); 3613 changePKPWSubCommand.addName("changeKeyPassword", true); 3614 changePKPWSubCommand.addName("change-key-passphrase", true); 3615 changePKPWSubCommand.addName("changeKeyPassphrase", true); 3616 changePKPWSubCommand.addName("change-key-pin", true); 3617 changePKPWSubCommand.addName("changeKeyPIN", true); 3618 changePKPWSubCommand.addName("keypasswd", true); 3619 3620 parser.addSubCommand(changePKPWSubCommand); 3621 3622 3623 // Define the "copy-keystore" subcommand and all of its arguments. 3624 final ArgumentParser copyKSParser = new ArgumentParser("copy-keystore", 3625 INFO_MANAGE_CERTS_SC_COPY_KS_DESC.get()); 3626 3627 final FileArgument copyKSSourceKeystore = new FileArgument(null, 3628 "source-keystore", true, 1, null, 3629 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_DESC.get(), true, true, true, 3630 false); 3631 copyKSSourceKeystore.addLongIdentifier("sourceKeystore", true); 3632 copyKSSourceKeystore.addLongIdentifier("source-keystore-path", true); 3633 copyKSSourceKeystore.addLongIdentifier("sourceKeystorePath", true); 3634 copyKSSourceKeystore.addLongIdentifier("source-keystore-file", true); 3635 copyKSSourceKeystore.addLongIdentifier("sourceKeystoreFile", true); 3636 copyKSParser.addArgument(copyKSSourceKeystore); 3637 3638 final StringArgument copyKSSourceKeystorePassword = new StringArgument(null, 3639 "source-keystore-password", false, 1, 3640 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3641 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_PW_DESC.get()); 3642 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePassword", 3643 true); 3644 copyKSSourceKeystorePassword.addLongIdentifier("source-keystore-passphrase", 3645 true); 3646 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePassphrase", 3647 true); 3648 copyKSSourceKeystorePassword.addLongIdentifier("source-keystore-pin", true); 3649 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePIN", true); 3650 copyKSParser.addArgument(copyKSSourceKeystorePassword); 3651 3652 final FileArgument copyKSSourceKeystorePasswordFile = new FileArgument(null, 3653 "source-keystore-password-file", false, 1, null, 3654 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_PW_FILE_DESC.get(), true, true, 3655 true, false); 3656 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3657 "sourceKeystorePasswordFile", true); 3658 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3659 "source-keystore-passphrase-file", true); 3660 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3661 "sourceKeystorePassphraseFile", true); 3662 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3663 "source-keystore-pin-file", true); 3664 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3665 "sourceKeystorePINFile", true); 3666 copyKSParser.addArgument(copyKSSourceKeystorePasswordFile); 3667 3668 final BooleanArgument copyKSPromptForSourceKeystorePassword = 3669 new BooleanArgument(null, "prompt-for-source-keystore-password", 1, 3670 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_SRC_KS_PW.get()); 3671 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3672 "promptForSourceKeystorePassword", true); 3673 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3674 "prompt-for-source-keystore-passphrase", true); 3675 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3676 "promptForSourceKeystorePassphrase", true); 3677 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3678 "prompt-for-source-keystore-pin", true); 3679 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3680 "promptForSourceKeystorePIN", true); 3681 copyKSParser.addArgument(copyKSPromptForSourceKeystorePassword); 3682 3683 final StringArgument copyKSSourcePKPassword = new StringArgument(null, 3684 "source-private-key-password", false, 1, 3685 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3686 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_PK_PW_DESC.get()); 3687 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPassword", true); 3688 copyKSSourcePKPassword.addLongIdentifier("source-private-key-passphrase", 3689 true); 3690 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPassphrase", 3691 true); 3692 copyKSSourcePKPassword.addLongIdentifier("source-private-key-pin", true); 3693 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPIN", true); 3694 copyKSParser.addArgument(copyKSSourcePKPassword); 3695 3696 final FileArgument copyKSSourcePKPasswordFile = new FileArgument(null, 3697 "source-private-key-password-file", false, 1, null, 3698 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_PK_PW_FILE_DESC.get(), true, true, 3699 true, false); 3700 copyKSSourcePKPasswordFile.addLongIdentifier( 3701 "sourcePrivateKeyPasswordFile", true); 3702 copyKSSourcePKPasswordFile.addLongIdentifier( 3703 "source-private-key-passphrase-file", true); 3704 copyKSSourcePKPasswordFile.addLongIdentifier( 3705 "sourcePrivateKeyPassphraseFile", true); 3706 copyKSSourcePKPasswordFile.addLongIdentifier( 3707 "source-private-key-pin-file", true); 3708 copyKSSourcePKPasswordFile.addLongIdentifier( 3709 "sourcePrivateKeyPINFile", true); 3710 copyKSParser.addArgument(copyKSSourcePKPasswordFile); 3711 3712 final BooleanArgument copyKSPromptForSourcePKPassword = 3713 new BooleanArgument(null, "prompt-for-source-private-key-password", 1, 3714 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_SRC_PK_PW.get()); 3715 copyKSPromptForSourcePKPassword.addLongIdentifier( 3716 "promptForSourcePrivateKeyPassword", true); 3717 copyKSPromptForSourcePKPassword.addLongIdentifier( 3718 "prompt-for-source-private-key-passphrase", true); 3719 copyKSPromptForSourcePKPassword.addLongIdentifier( 3720 "promptForSourcePrivateKeyPassphrase", true); 3721 copyKSPromptForSourcePKPassword.addLongIdentifier( 3722 "prompt-for-source-private-key-pin", true); 3723 copyKSPromptForSourcePKPassword.addLongIdentifier( 3724 "promptForSourcePrivateKeyPIN", true); 3725 copyKSParser.addArgument(copyKSPromptForSourcePKPassword); 3726 3727 final StringArgument copyKSSourceKeystoreType = new StringArgument(null, 3728 "source-keystore-type", false, 1, 3729 INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3730 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_TYPE.get(), 3731 ALLOWED_KEYSTORE_TYPE_VALUES); 3732 copyKSSourceKeystoreType.addLongIdentifier("source-key-store-type", true); 3733 copyKSSourceKeystoreType.addLongIdentifier("sourceKeystoreType", true); 3734 copyKSSourceKeystoreType.addLongIdentifier("source-keystore-format", true); 3735 copyKSSourceKeystoreType.addLongIdentifier("source-key-store-format", true); 3736 copyKSSourceKeystoreType.addLongIdentifier("sourceKeystoreFormat", true); 3737 copyKSParser.addArgument(copyKSSourceKeystoreType); 3738 3739 final FileArgument copyKSDestKeystore = new FileArgument(null, 3740 "destination-keystore", true, 1, null, 3741 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_DESC.get(), false, true, true, 3742 false); 3743 copyKSDestKeystore.addLongIdentifier("destinationKeystore", true); 3744 copyKSDestKeystore.addLongIdentifier("destination-keystore-path", true); 3745 copyKSDestKeystore.addLongIdentifier("destinationKeystorePath", true); 3746 copyKSDestKeystore.addLongIdentifier("destination-keystore-file", true); 3747 copyKSDestKeystore.addLongIdentifier("destinationKeystoreFile", true); 3748 copyKSDestKeystore.addLongIdentifier("target-keystore", true); 3749 copyKSDestKeystore.addLongIdentifier("targetKeystore", true); 3750 copyKSDestKeystore.addLongIdentifier("target-keystore-path", true); 3751 copyKSDestKeystore.addLongIdentifier("targetKeystorePath", true); 3752 copyKSDestKeystore.addLongIdentifier("target-keystore-file", true); 3753 copyKSDestKeystore.addLongIdentifier("targetKeystoreFile", true); 3754 copyKSParser.addArgument(copyKSDestKeystore); 3755 3756 final StringArgument copyKSDestKeystorePassword = new StringArgument(null, 3757 "destination-keystore-password", false, 1, 3758 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3759 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_PW_DESC.get()); 3760 copyKSDestKeystorePassword.addLongIdentifier("destinationKeystorePassword", 3761 true); 3762 copyKSDestKeystorePassword.addLongIdentifier( 3763 "destination-keystore-passphrase", true); 3764 copyKSDestKeystorePassword.addLongIdentifier( 3765 "destinationKeystorePassphrase", true); 3766 copyKSDestKeystorePassword.addLongIdentifier("destination-keystore-pin", 3767 true); 3768 copyKSDestKeystorePassword.addLongIdentifier("destinationKeystorePIN", 3769 true); 3770 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-password", 3771 true); 3772 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePassword", 3773 true); 3774 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-passphrase", 3775 true); 3776 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePassphrase", 3777 true); 3778 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-pin", true); 3779 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePIN", true); 3780 copyKSParser.addArgument(copyKSDestKeystorePassword); 3781 3782 final FileArgument copyKSDestKeystorePasswordFile = new FileArgument(null, 3783 "destination-keystore-password-file", false, 1, null, 3784 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_PW_FILE_DESC.get(), true, true, 3785 true, false); 3786 copyKSDestKeystorePasswordFile.addLongIdentifier( 3787 "destinationKeystorePasswordFile", true); 3788 copyKSDestKeystorePasswordFile.addLongIdentifier( 3789 "destination-keystore-passphrase-file", true); 3790 copyKSDestKeystorePasswordFile.addLongIdentifier( 3791 "destinationKeystorePassphraseFile", true); 3792 copyKSDestKeystorePasswordFile.addLongIdentifier( 3793 "destination-keystore-pin-file", true); 3794 copyKSDestKeystorePasswordFile.addLongIdentifier( 3795 "destinationKeystorePINFile", true); 3796 copyKSDestKeystorePasswordFile.addLongIdentifier( 3797 "target-keystore-password-file", true); 3798 copyKSDestKeystorePasswordFile.addLongIdentifier( 3799 "targetKeystorePasswordFile", true); 3800 copyKSDestKeystorePasswordFile.addLongIdentifier( 3801 "target-keystore-passphrase-file", true); 3802 copyKSDestKeystorePasswordFile.addLongIdentifier( 3803 "targetKeystorePassphraseFile", true); 3804 copyKSDestKeystorePasswordFile.addLongIdentifier("target-keystore-pin-file", 3805 true); 3806 copyKSDestKeystorePasswordFile.addLongIdentifier("targetKeystorePINFile", 3807 true); 3808 copyKSParser.addArgument(copyKSDestKeystorePasswordFile); 3809 3810 final BooleanArgument copyKSPromptForDestKeystorePassword = 3811 new BooleanArgument(null, "prompt-for-destination-keystore-password", 3812 1, INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_DST_KS_PW.get()); 3813 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3814 "promptForDestinationKeystorePassword", true); 3815 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3816 "prompt-for-Destination-keystore-passphrase", true); 3817 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3818 "promptForDestinationKeystorePassphrase", true); 3819 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3820 "prompt-for-Destination-keystore-pin", true); 3821 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3822 "promptForDestinationKeystorePIN", true); 3823 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3824 "prompt-for-target-keystore-password", true); 3825 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3826 "promptForTargetKeystorePassword", true); 3827 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3828 "prompt-for-Target-keystore-passphrase", true); 3829 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3830 "promptForTargetKeystorePassphrase", true); 3831 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3832 "prompt-for-Target-keystore-pin", true); 3833 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3834 "promptForTargetKeystorePIN", true); 3835 copyKSParser.addArgument(copyKSPromptForDestKeystorePassword); 3836 3837 final StringArgument copyKSDestPKPassword = new StringArgument(null, 3838 "destination-private-key-password", false, 1, 3839 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3840 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_PK_PW_DESC.get()); 3841 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPassword", 3842 true); 3843 copyKSDestPKPassword.addLongIdentifier("destination-private-key-passphrase", 3844 true); 3845 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPassphrase", 3846 true); 3847 copyKSDestPKPassword.addLongIdentifier("destination-private-key-pin", true); 3848 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPIN", true); 3849 copyKSDestPKPassword.addLongIdentifier("target-private-key-password", 3850 true); 3851 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPassword", 3852 true); 3853 copyKSDestPKPassword.addLongIdentifier("target-private-key-passphrase", 3854 true); 3855 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPassphrase", 3856 true); 3857 copyKSDestPKPassword.addLongIdentifier("target-private-key-pin", true); 3858 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPIN", true); 3859 copyKSParser.addArgument(copyKSDestPKPassword); 3860 3861 final FileArgument copyKSDestPKPasswordFile = new FileArgument(null, 3862 "destination-private-key-password-file", false, 1, null, 3863 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_PK_PW_FILE_DESC.get(), true, true, 3864 true, false); 3865 copyKSDestPKPasswordFile.addLongIdentifier( 3866 "destinationPrivateKeyPasswordFile", true); 3867 copyKSDestPKPasswordFile.addLongIdentifier( 3868 "destination-private-key-passphrase-file", true); 3869 copyKSDestPKPasswordFile.addLongIdentifier( 3870 "destinationPrivateKeyPassphraseFile", true); 3871 copyKSDestPKPasswordFile.addLongIdentifier( 3872 "destination-private-key-pin-file", true); 3873 copyKSDestPKPasswordFile.addLongIdentifier( 3874 "destinationPrivateKeyPINFile", true); 3875 copyKSDestPKPasswordFile.addLongIdentifier( 3876 "target-private-key-password-file", true); 3877 copyKSDestPKPasswordFile.addLongIdentifier( 3878 "targetPrivateKeyPasswordFile", true); 3879 copyKSDestPKPasswordFile.addLongIdentifier( 3880 "target-private-key-passphrase-file", true); 3881 copyKSDestPKPasswordFile.addLongIdentifier( 3882 "targetPrivateKeyPassphraseFile", true); 3883 copyKSDestPKPasswordFile.addLongIdentifier( 3884 "target-private-key-pin-file", true); 3885 copyKSDestPKPasswordFile.addLongIdentifier( 3886 "targetPrivateKeyPINFile", true); 3887 copyKSParser.addArgument(copyKSDestPKPasswordFile); 3888 3889 final BooleanArgument copyKSPromptForDestPKPassword = 3890 new BooleanArgument(null, 3891 "prompt-for-destination-private-key-password", 1, 3892 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_DST_PK_PW.get()); 3893 copyKSPromptForDestPKPassword.addLongIdentifier( 3894 "promptForDestinationPrivateKeyPassword", true); 3895 copyKSPromptForDestPKPassword.addLongIdentifier( 3896 "prompt-for-Destination-private-key-passphrase", true); 3897 copyKSPromptForDestPKPassword.addLongIdentifier( 3898 "promptForDestinationPrivateKeyPassphrase", true); 3899 copyKSPromptForDestPKPassword.addLongIdentifier( 3900 "prompt-for-Destination-private-key-pin", true); 3901 copyKSPromptForDestPKPassword.addLongIdentifier( 3902 "promptForDestinationPrivateKeyPIN", true); 3903 copyKSPromptForDestPKPassword.addLongIdentifier( 3904 "prompt-for-target-private-key-password", true); 3905 copyKSPromptForDestPKPassword.addLongIdentifier( 3906 "promptForTargetPrivateKeyPassword", true); 3907 copyKSPromptForDestPKPassword.addLongIdentifier( 3908 "prompt-for-Target-private-key-passphrase", true); 3909 copyKSPromptForDestPKPassword.addLongIdentifier( 3910 "promptForTargetPrivateKeyPassphrase", true); 3911 copyKSPromptForDestPKPassword.addLongIdentifier( 3912 "prompt-for-Target-private-key-pin", true); 3913 copyKSPromptForDestPKPassword.addLongIdentifier( 3914 "promptForTargetPrivateKeyPIN", true); 3915 copyKSParser.addArgument(copyKSPromptForDestPKPassword); 3916 3917 final StringArgument copyKSDestKeystoreType = new StringArgument(null, 3918 "destination-keystore-type", false, 1, 3919 INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3920 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_TYPE.get(), 3921 ALLOWED_KEYSTORE_TYPE_VALUES); 3922 copyKSDestKeystoreType.addLongIdentifier("destination-key-store-type", 3923 true); 3924 copyKSDestKeystoreType.addLongIdentifier("destinationKeystoreType", true); 3925 copyKSDestKeystoreType.addLongIdentifier("destination-keystore-format", 3926 true); 3927 copyKSDestKeystoreType.addLongIdentifier("destination-key-store-format", 3928 true); 3929 copyKSDestKeystoreType.addLongIdentifier("destinationKeystoreFormat", true); 3930 copyKSDestKeystoreType.addLongIdentifier("target-key-store-type", true); 3931 copyKSDestKeystoreType.addLongIdentifier("targetKeystoreType", true); 3932 copyKSDestKeystoreType.addLongIdentifier("target-keystore-format", true); 3933 copyKSDestKeystoreType.addLongIdentifier("target-key-store-format", true); 3934 copyKSDestKeystoreType.addLongIdentifier("targetKeystoreFormat", true); 3935 copyKSParser.addArgument(copyKSDestKeystoreType); 3936 3937 final StringArgument copyKSAlias = new StringArgument(null, "alias", false, 3938 0, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3939 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_ALIAS.get()); 3940 copyKSAlias.addLongIdentifier("nickname", true); 3941 copyKSParser.addArgument(copyKSAlias); 3942 3943 copyKSParser.addRequiredArgumentSet(copyKSSourceKeystorePassword, 3944 copyKSSourceKeystorePasswordFile, 3945 copyKSPromptForSourceKeystorePassword); 3946 copyKSParser.addExclusiveArgumentSet(copyKSSourceKeystorePassword, 3947 copyKSSourceKeystorePasswordFile, 3948 copyKSPromptForSourceKeystorePassword); 3949 copyKSParser.addExclusiveArgumentSet(copyKSSourcePKPassword, 3950 copyKSSourcePKPasswordFile, copyKSPromptForDestPKPassword); 3951 copyKSParser.addExclusiveArgumentSet(copyKSDestKeystorePassword, 3952 copyKSDestKeystorePasswordFile, copyKSPromptForDestKeystorePassword); 3953 copyKSParser.addExclusiveArgumentSet(copyKSDestPKPassword, 3954 copyKSDestPKPasswordFile, copyKSPromptForDestPKPassword); 3955 3956 final LinkedHashMap<String[],String> copyKeyStoreExamples = 3957 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3958 copyKeyStoreExamples.put( 3959 new String[] 3960 { 3961 "copy-keystore", 3962 "--source-keystore", 3963 getPlatformSpecificPath("config", "keystore.jks"), 3964 "--source-keystore-password-file", 3965 getPlatformSpecificPath("config", "keystore.pin"), 3966 "--source-keystore-type", "JKS", 3967 "--destination-keystore", 3968 getPlatformSpecificPath("config", "keystore.p12"), 3969 "--destination-keystore-password-file", 3970 getPlatformSpecificPath("config", "keystore.pin"), 3971 "--destination-keystore-type", "PKCS12" 3972 }, 3973 INFO_MANAGE_CERTS_SC_COPY_KS_EXAMPLE_1.get("keystore.jks", 3974 "keystore.p12")); 3975 3976 final SubCommand copyKeyStoreSubCommand = new SubCommand("copy-keystore", 3977 INFO_MANAGE_CERTS_SC_COPY_KS_DESC.get(), copyKSParser, 3978 copyKeyStoreExamples); 3979 copyKeyStoreSubCommand.addName("copy-key-store", true); 3980 copyKeyStoreSubCommand.addName("copyKeyStore", true); 3981 copyKeyStoreSubCommand.addName("import-keystore", true); 3982 copyKeyStoreSubCommand.addName("import-key-store", true); 3983 copyKeyStoreSubCommand.addName("importKeyStore", true); 3984 copyKeyStoreSubCommand.addName("convert-keystore", true); 3985 copyKeyStoreSubCommand.addName("convert-key-store", true); 3986 copyKeyStoreSubCommand.addName("convertKeyStore", true); 3987 3988 parser.addSubCommand(copyKeyStoreSubCommand); 3989 3990 // Define the "retrieve-server-certificate" subcommand and all of its 3991 // arguments. 3992 final ArgumentParser retrieveCertParser = new ArgumentParser( 3993 "retrieve-server-certificate", 3994 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_DESC.get()); 3995 3996 final StringArgument retrieveCertHostname = new StringArgument('h', 3997 "hostname", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_HOST.get(), 3998 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_HOSTNAME_DESC.get()); 3999 retrieveCertHostname.addLongIdentifier("server-address", true); 4000 retrieveCertHostname.addLongIdentifier("serverAddress", true); 4001 retrieveCertHostname.addLongIdentifier("address", true); 4002 retrieveCertParser.addArgument(retrieveCertHostname); 4003 4004 final IntegerArgument retrieveCertPort = new IntegerArgument('p', 4005 "port", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_PORT.get(), 4006 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_PORT_DESC.get(), 1, 65_535); 4007 retrieveCertPort.addLongIdentifier("server-port", true); 4008 retrieveCertPort.addLongIdentifier("serverPort", true); 4009 retrieveCertParser.addArgument(retrieveCertPort); 4010 4011 final BooleanArgument retrieveCertUseStartTLS = new BooleanArgument('q', 4012 "use-ldap-start-tls", 1, 4013 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_USE_START_TLS_DESC.get()); 4014 retrieveCertUseStartTLS.addLongIdentifier("use-ldap-starttls", true); 4015 retrieveCertUseStartTLS.addLongIdentifier("useLDAPStartTLS", true); 4016 retrieveCertUseStartTLS.addLongIdentifier("use-start-tls", true); 4017 retrieveCertUseStartTLS.addLongIdentifier("use-starttls", true); 4018 retrieveCertUseStartTLS.addLongIdentifier("useStartTLS", true); 4019 retrieveCertParser.addArgument(retrieveCertUseStartTLS); 4020 4021 final FileArgument retrieveCertOutputFile = new FileArgument(null, 4022 "output-file", false, 1, null, 4023 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_FILE_DESC.get(), false, true, 4024 true, false); 4025 retrieveCertOutputFile.addLongIdentifier("outputFile", true); 4026 retrieveCertOutputFile.addLongIdentifier("export-file", true); 4027 retrieveCertOutputFile.addLongIdentifier("exportFile", true); 4028 retrieveCertOutputFile.addLongIdentifier("certificate-file", true); 4029 retrieveCertOutputFile.addLongIdentifier("certificateFile", true); 4030 retrieveCertOutputFile.addLongIdentifier("file", true); 4031 retrieveCertOutputFile.addLongIdentifier("filename", true); 4032 retrieveCertParser.addArgument(retrieveCertOutputFile); 4033 4034 final Set<String> retrieveCertOutputFormatAllowedValues = StaticUtils.setOf( 4035 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 4036 final StringArgument retrieveCertOutputFormat = new StringArgument(null, 4037 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 4038 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_FORMAT_DESC.get(), 4039 retrieveCertOutputFormatAllowedValues, "PEM"); 4040 retrieveCertOutputFormat.addLongIdentifier("outputFormat", true); 4041 retrieveCertParser.addArgument(retrieveCertOutputFormat); 4042 4043 final BooleanArgument retrieveCertOnlyPeer = new BooleanArgument(null, 4044 "only-peer-certificate", 1, 4045 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_ONLY_PEER_DESC.get()); 4046 retrieveCertOnlyPeer.addLongIdentifier("onlyPeerCertificate", true); 4047 retrieveCertOnlyPeer.addLongIdentifier("only-peer", true); 4048 retrieveCertOnlyPeer.addLongIdentifier("onlyPeer", true); 4049 retrieveCertOnlyPeer.addLongIdentifier("peer-certificate-only", true); 4050 retrieveCertOnlyPeer.addLongIdentifier("peerCertificateOnly", true); 4051 retrieveCertOnlyPeer.addLongIdentifier("peer-only", true); 4052 retrieveCertOnlyPeer.addLongIdentifier("peerOnly", true); 4053 retrieveCertParser.addArgument(retrieveCertOnlyPeer); 4054 4055 final BooleanArgument retrieveCertEnableSSLDebugging = new BooleanArgument( 4056 null, "enableSSLDebugging", 1, 4057 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_ENABLE_SSL_DEBUGGING_DESC. 4058 get()); 4059 retrieveCertEnableSSLDebugging.addLongIdentifier("enableTLSDebugging", 4060 true); 4061 retrieveCertEnableSSLDebugging.addLongIdentifier("enableStartTLSDebugging", 4062 true); 4063 retrieveCertEnableSSLDebugging.addLongIdentifier("enable-ssl-debugging", 4064 true); 4065 retrieveCertEnableSSLDebugging.addLongIdentifier("enable-tls-debugging", 4066 true); 4067 retrieveCertEnableSSLDebugging.addLongIdentifier( 4068 "enable-starttls-debugging", true); 4069 retrieveCertEnableSSLDebugging.addLongIdentifier( 4070 "enable-start-tls-debugging", true); 4071 retrieveCertParser.addArgument(retrieveCertEnableSSLDebugging); 4072 addEnableSSLDebuggingArgument(retrieveCertEnableSSLDebugging); 4073 4074 final BooleanArgument retrieveCertVerbose = new BooleanArgument(null, 4075 "verbose", 1, 4076 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_VERBOSE_DESC.get()); 4077 retrieveCertParser.addArgument(retrieveCertVerbose); 4078 4079 retrieveCertParser.addDependentArgumentSet(retrieveCertOutputFormat, 4080 retrieveCertOutputFile); 4081 4082 final LinkedHashMap<String[],String> retrieveCertExamples = 4083 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4084 retrieveCertExamples.put( 4085 new String[] 4086 { 4087 "retrieve-server-certificate", 4088 "--hostname", "ds.example.com", 4089 "--port", "636" 4090 }, 4091 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_1.get( 4092 getPlatformSpecificPath("config", "truststore"))); 4093 retrieveCertExamples.put( 4094 new String[] 4095 { 4096 "retrieve-server-certificate", 4097 "--hostname", "ds.example.com", 4098 "--port", "389", 4099 "--use-ldap-start-tls", 4100 "--only-peer-certificate", 4101 "--output-file", "ds-cert.pem", 4102 "--output-format", "PEM", 4103 "--verbose" 4104 }, 4105 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_2.get( 4106 getPlatformSpecificPath("config", "truststore"))); 4107 4108 final SubCommand retrieveCertSubCommand = new SubCommand( 4109 "retrieve-server-certificate", 4110 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_DESC.get(), retrieveCertParser, 4111 retrieveCertExamples); 4112 retrieveCertSubCommand.addName("retrieveServerCertificate", true); 4113 retrieveCertSubCommand.addName("retrieve-certificate", true); 4114 retrieveCertSubCommand.addName("retrieveCertificate", true); 4115 retrieveCertSubCommand.addName("get-server-certificate", true); 4116 retrieveCertSubCommand.addName("getServerCertificate", true); 4117 retrieveCertSubCommand.addName("get-certificate", true); 4118 retrieveCertSubCommand.addName("getCertificate", true); 4119 retrieveCertSubCommand.addName("display-server-certificate", true); 4120 retrieveCertSubCommand.addName("displayServerCertificate", true); 4121 4122 parser.addSubCommand(retrieveCertSubCommand); 4123 4124 4125 // Define the "trust-server-certificate" subcommand and all of its 4126 // arguments. 4127 final ArgumentParser trustServerParser = new ArgumentParser( 4128 "trust-server-certificate", 4129 INFO_MANAGE_CERTS_SC_TRUST_SERVER_DESC.get()); 4130 4131 final StringArgument trustServerHostname = new StringArgument('h', 4132 "hostname", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_HOST.get(), 4133 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_HOSTNAME_DESC.get()); 4134 trustServerHostname.addLongIdentifier("server-address", true); 4135 trustServerHostname.addLongIdentifier("serverAddress", true); 4136 trustServerHostname.addLongIdentifier("address", true); 4137 trustServerParser.addArgument(trustServerHostname); 4138 4139 final IntegerArgument trustServerPort = new IntegerArgument('p', 4140 "port", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_PORT.get(), 4141 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_PORT_DESC.get(), 1, 65_535); 4142 trustServerPort.addLongIdentifier("server-port", true); 4143 trustServerPort.addLongIdentifier("serverPort", true); 4144 trustServerParser.addArgument(trustServerPort); 4145 4146 final BooleanArgument trustServerUseStartTLS = new BooleanArgument('q', 4147 "use-ldap-start-tls", 1, 4148 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_USE_START_TLS_DESC.get()); 4149 trustServerUseStartTLS.addLongIdentifier("use-ldap-starttls", true); 4150 trustServerUseStartTLS.addLongIdentifier("useLDAPStartTLS", true); 4151 trustServerUseStartTLS.addLongIdentifier("use-start-tls", true); 4152 trustServerUseStartTLS.addLongIdentifier("use-starttls", true); 4153 trustServerUseStartTLS.addLongIdentifier("useStartTLS", true); 4154 trustServerParser.addArgument(trustServerUseStartTLS); 4155 4156 final FileArgument trustServerKeystore = new FileArgument(null, "keystore", 4157 true, 1, null, INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_DESC.get(), 4158 false, true, true, false); 4159 trustServerKeystore.addLongIdentifier("keystore-path", true); 4160 trustServerKeystore.addLongIdentifier("keystorePath", true); 4161 trustServerKeystore.addLongIdentifier("keystore-file", true); 4162 trustServerKeystore.addLongIdentifier("keystoreFile", true); 4163 trustServerParser.addArgument(trustServerKeystore); 4164 4165 final StringArgument trustServerKeystorePassword = new StringArgument(null, 4166 "keystore-password", false, 1, 4167 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 4168 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_PW_DESC.get()); 4169 trustServerKeystorePassword.addLongIdentifier("keystorePassword", true); 4170 trustServerKeystorePassword.addLongIdentifier("keystore-passphrase", true); 4171 trustServerKeystorePassword.addLongIdentifier("keystorePassphrase", true); 4172 trustServerKeystorePassword.addLongIdentifier("keystore-pin", true); 4173 trustServerKeystorePassword.addLongIdentifier("keystorePIN", true); 4174 trustServerKeystorePassword.addLongIdentifier("storepass", true); 4175 trustServerKeystorePassword.setSensitive(true); 4176 trustServerParser.addArgument(trustServerKeystorePassword); 4177 4178 final FileArgument trustServerKeystorePasswordFile = new FileArgument(null, 4179 "keystore-password-file", false, 1, null, 4180 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_PW_FILE_DESC.get(), true, 4181 true, true, false); 4182 trustServerKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 4183 true); 4184 trustServerKeystorePasswordFile.addLongIdentifier( 4185 "keystore-passphrase-file", true); 4186 trustServerKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 4187 true); 4188 trustServerKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 4189 true); 4190 trustServerKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 4191 trustServerParser.addArgument(trustServerKeystorePasswordFile); 4192 4193 final BooleanArgument trustServerPromptForKeystorePassword = 4194 new BooleanArgument(null, "prompt-for-keystore-password", 4195 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_PROMPT_FOR_KS_PW_DESC.get()); 4196 trustServerPromptForKeystorePassword.addLongIdentifier( 4197 "promptForKeystorePassword", true); 4198 trustServerPromptForKeystorePassword.addLongIdentifier( 4199 "prompt-for-keystore-passphrase", true); 4200 trustServerPromptForKeystorePassword.addLongIdentifier( 4201 "promptForKeystorePassphrase", true); 4202 trustServerPromptForKeystorePassword.addLongIdentifier( 4203 "prompt-for-keystore-pin", true); 4204 trustServerPromptForKeystorePassword.addLongIdentifier( 4205 "promptForKeystorePIN", true); 4206 trustServerParser.addArgument(trustServerPromptForKeystorePassword); 4207 4208 final StringArgument trustServerKeystoreType = new StringArgument(null, 4209 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 4210 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_TYPE_DESC.get(), 4211 ALLOWED_KEYSTORE_TYPE_VALUES); 4212 trustServerKeystoreType.addLongIdentifier("key-store-type", true); 4213 trustServerKeystoreType.addLongIdentifier("keystoreType", true); 4214 trustServerKeystoreType.addLongIdentifier("keystore-format", true); 4215 trustServerKeystoreType.addLongIdentifier("key-store-format", true); 4216 trustServerKeystoreType.addLongIdentifier("keystoreFormat", true); 4217 trustServerKeystoreType.addLongIdentifier("storetype", true); 4218 trustServerParser.addArgument(trustServerKeystoreType); 4219 4220 final StringArgument trustServerAlias = new StringArgument(null, 4221 "alias", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 4222 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ALIAS_DESC.get()); 4223 trustServerAlias.addLongIdentifier("nickname", true); 4224 trustServerParser.addArgument(trustServerAlias); 4225 4226 final BooleanArgument trustServerIssuersOnly = new BooleanArgument(null, 4227 "issuers-only", 1, 4228 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ISSUERS_ONLY_DESC.get()); 4229 trustServerIssuersOnly.addLongIdentifier("issuersOnly", true); 4230 trustServerIssuersOnly.addLongIdentifier("issuer-certificates-only", true); 4231 trustServerIssuersOnly.addLongIdentifier("issuerCertificatesOnly", true); 4232 trustServerIssuersOnly.addLongIdentifier("only-issuers", true); 4233 trustServerIssuersOnly.addLongIdentifier("onlyIssuers", true); 4234 trustServerIssuersOnly.addLongIdentifier("only-issuer-certificates", true); 4235 trustServerIssuersOnly.addLongIdentifier("onlyIssuerCertificates", true); 4236 trustServerParser.addArgument(trustServerIssuersOnly); 4237 4238 final BooleanArgument trustServerEnableSSLDebugging = new BooleanArgument( 4239 null, "enableSSLDebugging", 1, 4240 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ENABLE_SSL_DEBUGGING_DESC.get()); 4241 trustServerEnableSSLDebugging.addLongIdentifier("enableTLSDebugging", true); 4242 trustServerEnableSSLDebugging.addLongIdentifier("enableStartTLSDebugging", 4243 true); 4244 trustServerEnableSSLDebugging.addLongIdentifier("enable-ssl-debugging", 4245 true); 4246 trustServerEnableSSLDebugging.addLongIdentifier("enable-tls-debugging", 4247 true); 4248 trustServerEnableSSLDebugging.addLongIdentifier("enable-starttls-debugging", 4249 true); 4250 trustServerEnableSSLDebugging.addLongIdentifier( 4251 "enable-start-tls-debugging", true); 4252 trustServerParser.addArgument(trustServerEnableSSLDebugging); 4253 addEnableSSLDebuggingArgument(trustServerEnableSSLDebugging); 4254 4255 final BooleanArgument trustServerVerbose = new BooleanArgument(null, 4256 "verbose", 1, 4257 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_VERBOSE_DESC.get()); 4258 trustServerParser.addArgument(trustServerVerbose); 4259 4260 final BooleanArgument trustServerNoPrompt = new BooleanArgument(null, 4261 "no-prompt", 1, 4262 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_NO_PROMPT_DESC.get()); 4263 trustServerNoPrompt.addLongIdentifier("noPrompt", true); 4264 trustServerParser.addArgument(trustServerNoPrompt); 4265 4266 trustServerParser.addRequiredArgumentSet(trustServerKeystorePassword, 4267 trustServerKeystorePasswordFile, trustServerPromptForKeystorePassword); 4268 trustServerParser.addExclusiveArgumentSet(trustServerKeystorePassword, 4269 trustServerKeystorePasswordFile, trustServerPromptForKeystorePassword); 4270 4271 final LinkedHashMap<String[],String> trustServerExamples = 4272 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4273 trustServerExamples.put( 4274 new String[] 4275 { 4276 "trust-server-certificate", 4277 "--hostname", "ds.example.com", 4278 "--port", "636", 4279 "--keystore", getPlatformSpecificPath("config", "truststore"), 4280 "--keystore-password-file", 4281 getPlatformSpecificPath("config", "truststore.pin"), 4282 "--verbose" 4283 }, 4284 INFO_MANAGE_CERTS_SC_TRUST_SERVER_EXAMPLE_1.get( 4285 getPlatformSpecificPath("config", "truststore"))); 4286 trustServerExamples.put( 4287 new String[] 4288 { 4289 "trust-server-certificate", 4290 "--hostname", "ds.example.com", 4291 "--port", "389", 4292 "--use-ldap-start-tls", 4293 "--keystore", getPlatformSpecificPath("config", "truststore"), 4294 "--keystore-password-file", 4295 getPlatformSpecificPath("config", "truststore.pin"), 4296 "--issuers-only", 4297 "--alias", "ds-start-tls-cert", 4298 "--no-prompt" 4299 }, 4300 INFO_MANAGE_CERTS_SC_TRUST_SERVER_EXAMPLE_2.get( 4301 getPlatformSpecificPath("config", "truststore"))); 4302 4303 final SubCommand trustServerSubCommand = new SubCommand( 4304 "trust-server-certificate", 4305 INFO_MANAGE_CERTS_SC_TRUST_SERVER_DESC.get(), trustServerParser, 4306 trustServerExamples); 4307 trustServerSubCommand.addName("trustServerCertificate", true); 4308 trustServerSubCommand.addName("trust-server", true); 4309 trustServerSubCommand.addName("trustServer", true); 4310 4311 parser.addSubCommand(trustServerSubCommand); 4312 4313 4314 // Define the "check-certificate-usability" subcommand and all of its 4315 // arguments. 4316 final ArgumentParser checkUsabilityParser = new ArgumentParser( 4317 "check-certificate-usability", 4318 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_DESC.get()); 4319 4320 final FileArgument checkUsabilityKeystore = new FileArgument(null, 4321 "keystore", true, 1, null, 4322 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_DESC.get(), 4323 true, true, true, false); 4324 checkUsabilityKeystore.addLongIdentifier("keystore-path", true); 4325 checkUsabilityKeystore.addLongIdentifier("keystorePath", true); 4326 checkUsabilityKeystore.addLongIdentifier("keystore-file", true); 4327 checkUsabilityKeystore.addLongIdentifier("keystoreFile", true); 4328 checkUsabilityParser.addArgument(checkUsabilityKeystore); 4329 4330 final StringArgument checkUsabilityKeystorePassword = new StringArgument( 4331 null, "keystore-password", false, 1, 4332 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 4333 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_PW_DESC.get()); 4334 checkUsabilityKeystorePassword.addLongIdentifier("keystorePassword", true); 4335 checkUsabilityKeystorePassword.addLongIdentifier("keystore-passphrase", 4336 true); 4337 checkUsabilityKeystorePassword.addLongIdentifier("keystorePassphrase", 4338 true); 4339 checkUsabilityKeystorePassword.addLongIdentifier("keystore-pin", true); 4340 checkUsabilityKeystorePassword.addLongIdentifier("keystorePIN", true); 4341 checkUsabilityKeystorePassword.addLongIdentifier("storepass", true); 4342 checkUsabilityKeystorePassword.setSensitive(true); 4343 checkUsabilityParser.addArgument(checkUsabilityKeystorePassword); 4344 4345 final FileArgument checkUsabilityKeystorePasswordFile = new FileArgument( 4346 null, "keystore-password-file", false, 1, null, 4347 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_PW_FILE_DESC.get(), true, 4348 true, true, false); 4349 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 4350 true); 4351 checkUsabilityKeystorePasswordFile.addLongIdentifier( 4352 "keystore-passphrase-file", true); 4353 checkUsabilityKeystorePasswordFile.addLongIdentifier( 4354 "keystorePassphraseFile", true); 4355 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 4356 true); 4357 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystorePINFile", 4358 true); 4359 checkUsabilityParser.addArgument(checkUsabilityKeystorePasswordFile); 4360 4361 final BooleanArgument checkUsabilityPromptForKeystorePassword = 4362 new BooleanArgument(null, "prompt-for-keystore-password", 4363 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_PROMPT_FOR_KS_PW_DESC.get()); 4364 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4365 "promptForKeystorePassword", true); 4366 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4367 "prompt-for-keystore-passphrase", true); 4368 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4369 "promptForKeystorePassphrase", true); 4370 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4371 "prompt-for-keystore-pin", true); 4372 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4373 "promptForKeystorePIN", true); 4374 checkUsabilityParser.addArgument(checkUsabilityPromptForKeystorePassword); 4375 4376 final StringArgument checkUsabilityKeystoreType = new StringArgument(null, 4377 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 4378 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_TYPE_DESC.get(), 4379 ALLOWED_KEYSTORE_TYPE_VALUES); 4380 checkUsabilityKeystoreType.addLongIdentifier("key-store-type", true); 4381 checkUsabilityKeystoreType.addLongIdentifier("keystoreType", true); 4382 checkUsabilityKeystoreType.addLongIdentifier("keystore-format", true); 4383 checkUsabilityKeystoreType.addLongIdentifier("key-store-format", true); 4384 checkUsabilityKeystoreType.addLongIdentifier("keystoreFormat", true); 4385 checkUsabilityKeystoreType.addLongIdentifier("storetype", true); 4386 checkUsabilityParser.addArgument(checkUsabilityKeystoreType); 4387 4388 final StringArgument checkUsabilityAlias = new StringArgument(null, "alias", 4389 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 4390 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_ALIAS_DESC.get()); 4391 checkUsabilityAlias.addLongIdentifier("nickname", true); 4392 checkUsabilityParser.addArgument(checkUsabilityAlias); 4393 4394 final BooleanArgument checkUsabilityIgnoreSHA1Signature = 4395 new BooleanArgument(null, 4396 "allow-sha-1-signature-for-issuer-certificates", 1, 4397 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_IGNORE_SHA1_WARNING_DESC. 4398 get()); 4399 checkUsabilityIgnoreSHA1Signature.addLongIdentifier( 4400 "allow-sha1-signature-for-issuer-certificates", true); 4401 checkUsabilityIgnoreSHA1Signature.addLongIdentifier( 4402 "allowSHA1SignatureForIssuerCertificates", true); 4403 checkUsabilityParser.addArgument(checkUsabilityIgnoreSHA1Signature); 4404 4405 checkUsabilityParser.addRequiredArgumentSet(checkUsabilityKeystorePassword, 4406 checkUsabilityKeystorePasswordFile, 4407 checkUsabilityPromptForKeystorePassword); 4408 checkUsabilityParser.addExclusiveArgumentSet(checkUsabilityKeystorePassword, 4409 checkUsabilityKeystorePasswordFile, 4410 checkUsabilityPromptForKeystorePassword); 4411 4412 final LinkedHashMap<String[],String> checkUsabilityExamples = 4413 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4414 checkUsabilityExamples.put( 4415 new String[] 4416 { 4417 "check-certificate-usability", 4418 "--keystore", getPlatformSpecificPath("config", "keystore"), 4419 "--keystore-password-file", 4420 getPlatformSpecificPath("config", "keystore.pin"), 4421 "--alias", "server-cert" 4422 }, 4423 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_EXAMPLE_1.get( 4424 getPlatformSpecificPath("config", "keystore"))); 4425 4426 final SubCommand checkUsabilitySubCommand = new SubCommand( 4427 "check-certificate-usability", 4428 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_DESC.get(), checkUsabilityParser, 4429 checkUsabilityExamples); 4430 checkUsabilitySubCommand.addName("checkCertificateUsability", true); 4431 checkUsabilitySubCommand.addName("check-usability", true); 4432 checkUsabilitySubCommand.addName("checkUsability", true); 4433 4434 parser.addSubCommand(checkUsabilitySubCommand); 4435 4436 4437 // Define the "display-certificate-file" subcommand and all of its 4438 // arguments. 4439 final ArgumentParser displayCertParser = new ArgumentParser( 4440 "display-certificate-file", 4441 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_DESC.get()); 4442 4443 final FileArgument displayCertFile = new FileArgument(null, 4444 "certificate-file", true, 1, null, 4445 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_FILE_DESC.get(), true, true, 4446 true, false); 4447 displayCertFile.addLongIdentifier("certificateFile", true); 4448 displayCertFile.addLongIdentifier("input-file", true); 4449 displayCertFile.addLongIdentifier("inputFile", true); 4450 displayCertFile.addLongIdentifier("file", true); 4451 displayCertFile.addLongIdentifier("filename", true); 4452 displayCertParser.addArgument(displayCertFile); 4453 4454 final BooleanArgument displayCertVerbose = new BooleanArgument(null, 4455 "verbose", 1, 4456 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_VERBOSE_DESC.get()); 4457 displayCertParser.addArgument(displayCertVerbose); 4458 4459 final BooleanArgument displayCertDisplayCommand = new BooleanArgument(null, 4460 "display-keytool-command", 1, 4461 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 4462 displayCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 4463 displayCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 4464 displayCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 4465 displayCertParser.addArgument(displayCertDisplayCommand); 4466 4467 final LinkedHashMap<String[],String> displayCertExamples = 4468 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4469 displayCertExamples.put( 4470 new String[] 4471 { 4472 "display-certificate-file", 4473 "--certificate-file", "certificate.pem", 4474 }, 4475 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_EXAMPLE_1.get("certificate.pem")); 4476 displayCertExamples.put( 4477 new String[] 4478 { 4479 "display-certificate-file", 4480 "--certificate-file", "certificate.pem", 4481 "--verbose", 4482 "--display-keytool-command" 4483 }, 4484 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_EXAMPLE_2.get("certificate.pem")); 4485 4486 final SubCommand displayCertSubCommand = new SubCommand( 4487 "display-certificate-file", 4488 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_DESC.get(), displayCertParser, 4489 displayCertExamples); 4490 displayCertSubCommand.addName("displayCertificateFile", true); 4491 displayCertSubCommand.addName("display-certificate", true); 4492 displayCertSubCommand.addName("displayCertificate", true); 4493 displayCertSubCommand.addName("display-certificates", true); 4494 displayCertSubCommand.addName("displayCertificates", true); 4495 displayCertSubCommand.addName("show-certificate", true); 4496 displayCertSubCommand.addName("showCertificate", true); 4497 displayCertSubCommand.addName("show-certificate-file", true); 4498 displayCertSubCommand.addName("showCertificateFile", true); 4499 displayCertSubCommand.addName("show-certificates", true); 4500 displayCertSubCommand.addName("showCertificates", true); 4501 displayCertSubCommand.addName("print-certificate-file", true); 4502 displayCertSubCommand.addName("printCertificateFile", true); 4503 displayCertSubCommand.addName("print-certificate", true); 4504 displayCertSubCommand.addName("printCertificate", true); 4505 displayCertSubCommand.addName("print-certificates", true); 4506 displayCertSubCommand.addName("printCertificates", true); 4507 displayCertSubCommand.addName("printcert", true); 4508 4509 parser.addSubCommand(displayCertSubCommand); 4510 4511 4512 // Define the "display-certificate-signing-request-file" subcommand and all 4513 // of its arguments. 4514 final ArgumentParser displayCSRParser = new ArgumentParser( 4515 "display-certificate-signing-request-file", 4516 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_DESC.get()); 4517 4518 final FileArgument displayCSRFile = new FileArgument(null, 4519 "certificate-signing-request-file", true, 1, null, 4520 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_FILE_DESC.get(), true, true, 4521 true, false); 4522 displayCSRFile.addLongIdentifier("certificateSigningRequestFile", true); 4523 displayCSRFile.addLongIdentifier("request-file", true); 4524 displayCSRFile.addLongIdentifier("requestFile", true); 4525 displayCSRFile.addLongIdentifier("input-file", true); 4526 displayCSRFile.addLongIdentifier("inputFile", true); 4527 displayCSRFile.addLongIdentifier("file", true); 4528 displayCSRFile.addLongIdentifier("filename", true); 4529 displayCSRParser.addArgument(displayCSRFile); 4530 4531 final BooleanArgument displayCSRVerbose = new BooleanArgument(null, 4532 "verbose", 1, 4533 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_VERBOSE_DESC.get()); 4534 displayCSRParser.addArgument(displayCSRVerbose); 4535 4536 final BooleanArgument displayCSRDisplayCommand = new BooleanArgument(null, 4537 "display-keytool-command", 1, 4538 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 4539 displayCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 4540 displayCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 4541 displayCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 4542 displayCSRParser.addArgument(displayCSRDisplayCommand); 4543 4544 final LinkedHashMap<String[],String> displayCSRExamples = 4545 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 4546 displayCSRExamples.put( 4547 new String[] 4548 { 4549 "display-certificate-signing-request-file", 4550 "--certificate-signing-request-file", "server-cert.csr", 4551 "--display-keytool-command" 4552 }, 4553 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_EXAMPLE_1.get("server-cert.csr")); 4554 4555 final SubCommand displayCSRSubCommand = new SubCommand( 4556 "display-certificate-signing-request-file", 4557 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_DESC.get(), displayCSRParser, 4558 displayCSRExamples); 4559 displayCSRSubCommand.addName("displayCertificateSigningRequestFile", true); 4560 displayCSRSubCommand.addName("display-certificate-signing-request", true); 4561 displayCSRSubCommand.addName("displayCertificateSigningRequest", true); 4562 displayCSRSubCommand.addName("display-certificate-request-file", true); 4563 displayCSRSubCommand.addName("displayCertificateRequestFile", true); 4564 displayCSRSubCommand.addName("display-certificate-request", true); 4565 displayCSRSubCommand.addName("displayCertificateRequest", true); 4566 displayCSRSubCommand.addName("display-csr-file", true); 4567 displayCSRSubCommand.addName("displayCSRFile", true); 4568 displayCSRSubCommand.addName("display-csr", true); 4569 displayCSRSubCommand.addName("displayCSR", true); 4570 displayCSRSubCommand.addName("show-certificate-signing-request-file", true); 4571 displayCSRSubCommand.addName("showCertificateSigningRequestFile", true); 4572 displayCSRSubCommand.addName("show-certificate-signing-request", true); 4573 displayCSRSubCommand.addName("showCertificateSigningRequest", true); 4574 displayCSRSubCommand.addName("show-certificate-request-file", true); 4575 displayCSRSubCommand.addName("showCertificateRequestFile", true); 4576 displayCSRSubCommand.addName("show-certificate-request", true); 4577 displayCSRSubCommand.addName("showCertificateRequest", true); 4578 displayCSRSubCommand.addName("show-csr-file", true); 4579 displayCSRSubCommand.addName("showCSRFile", true); 4580 displayCSRSubCommand.addName("show-csr", true); 4581 displayCSRSubCommand.addName("showCSR", true); 4582 displayCSRSubCommand.addName("print-certificate-signing-request-file", 4583 true); 4584 displayCSRSubCommand.addName("printCertificateSigningRequestFile", true); 4585 displayCSRSubCommand.addName("print-certificate-signing-request", true); 4586 displayCSRSubCommand.addName("printCertificateSigningRequest", true); 4587 displayCSRSubCommand.addName("print-certificate-request-file", true); 4588 displayCSRSubCommand.addName("printCertificateRequestFile", true); 4589 displayCSRSubCommand.addName("print-certificate-request", true); 4590 displayCSRSubCommand.addName("printCertificateRequest", true); 4591 displayCSRSubCommand.addName("print-csr-file", true); 4592 displayCSRSubCommand.addName("printCSRFile", true); 4593 displayCSRSubCommand.addName("print-csr", true); 4594 displayCSRSubCommand.addName("printCSR", true); 4595 displayCSRSubCommand.addName("printcertreq", true); 4596 4597 parser.addSubCommand(displayCSRSubCommand); 4598 } 4599 4600 4601 4602 /** 4603 * Constructs a platform-specific relative path from the provided elements. 4604 * 4605 * @param pathElements The elements of the path to construct. It must not 4606 * be {@code null} or empty. 4607 * 4608 * @return The constructed path. 4609 */ 4610 @NotNull() 4611 private static String getPlatformSpecificPath( 4612 @NotNull final String... pathElements) 4613 { 4614 final StringBuilder buffer = new StringBuilder(); 4615 for (int i=0; i < pathElements.length; i++) 4616 { 4617 if (i > 0) 4618 { 4619 buffer.append(File.separatorChar); 4620 } 4621 4622 buffer.append(pathElements[i]); 4623 } 4624 4625 return buffer.toString(); 4626 } 4627 4628 4629 4630 /** 4631 * Performs the core set of processing for this tool. 4632 * 4633 * @return A result code that indicates whether the processing completed 4634 * successfully. 4635 */ 4636 @Override() 4637 @NotNull() 4638 public ResultCode doToolProcessing() 4639 { 4640 final SubCommand selectedSubCommand = globalParser.getSelectedSubCommand(); 4641 if (selectedSubCommand == null) 4642 { 4643 // This should never happen. 4644 wrapErr(0, WRAP_COLUMN, ERR_MANAGE_CERTS_NO_SUBCOMMAND.get()); 4645 return ResultCode.PARAM_ERROR; 4646 } 4647 4648 subCommandParser = selectedSubCommand.getArgumentParser(); 4649 4650 if (selectedSubCommand.hasName("list-certificates")) 4651 { 4652 return doListCertificates(); 4653 } 4654 else if (selectedSubCommand.hasName("export-certificate")) 4655 { 4656 return doExportCertificate(); 4657 } 4658 else if (selectedSubCommand.hasName("export-private-key")) 4659 { 4660 return doExportPrivateKey(); 4661 } 4662 else if (selectedSubCommand.hasName("import-certificate")) 4663 { 4664 return doImportCertificate(); 4665 } 4666 else if (selectedSubCommand.hasName("delete-certificate")) 4667 { 4668 return doDeleteCertificate(); 4669 } 4670 else if (selectedSubCommand.hasName("generate-self-signed-certificate")) 4671 { 4672 return doGenerateOrSignCertificateOrCSR(); 4673 } 4674 else if (selectedSubCommand.hasName("generate-certificate-signing-request")) 4675 { 4676 return doGenerateOrSignCertificateOrCSR(); 4677 } 4678 else if (selectedSubCommand.hasName("sign-certificate-signing-request")) 4679 { 4680 return doGenerateOrSignCertificateOrCSR(); 4681 } 4682 else if (selectedSubCommand.hasName("change-certificate-alias")) 4683 { 4684 return doChangeCertificateAlias(); 4685 } 4686 else if (selectedSubCommand.hasName("change-keystore-password")) 4687 { 4688 return doChangeKeystorePassword(); 4689 } 4690 else if (selectedSubCommand.hasName("change-private-key-password")) 4691 { 4692 return doChangePrivateKeyPassword(); 4693 } 4694 else if (selectedSubCommand.hasName("copy-keystore")) 4695 { 4696 return doCopyKeystore(); 4697 } 4698 else if (selectedSubCommand.hasName("retrieve-server-certificate")) 4699 { 4700 return doRetrieveServerCertificate(); 4701 } 4702 else if (selectedSubCommand.hasName("trust-server-certificate")) 4703 { 4704 return doTrustServerCertificate(); 4705 } 4706 else if (selectedSubCommand.hasName("check-certificate-usability")) 4707 { 4708 return doCheckCertificateUsability(); 4709 } 4710 else if (selectedSubCommand.hasName("display-certificate-file")) 4711 { 4712 return doDisplayCertificateFile(); 4713 } 4714 else if (selectedSubCommand.hasName( 4715 "display-certificate-signing-request-file")) 4716 { 4717 return doDisplayCertificateSigningRequestFile(); 4718 } 4719 else 4720 { 4721 // This should never happen. 4722 wrapErr(0, WRAP_COLUMN, 4723 ERR_MANAGE_CERTS_UNKNOWN_SUBCOMMAND.get( 4724 selectedSubCommand.getPrimaryName())); 4725 return ResultCode.PARAM_ERROR; 4726 } 4727 } 4728 4729 4730 4731 /** 4732 * Performs the necessary processing for the list-certificates subcommand. 4733 * 4734 * @return A result code that indicates whether the processing completed 4735 * successfully. 4736 */ 4737 @NotNull() 4738 private ResultCode doListCertificates() 4739 { 4740 // Get the values of a number of configured arguments. 4741 final BooleanArgument displayPEMArgument = 4742 subCommandParser.getBooleanArgument("display-pem-certificate"); 4743 final boolean displayPEM = 4744 ((displayPEMArgument != null) && displayPEMArgument.isPresent()); 4745 4746 final BooleanArgument verboseArgument = 4747 subCommandParser.getBooleanArgument("verbose"); 4748 final boolean verbose = 4749 ((verboseArgument != null) && verboseArgument.isPresent()); 4750 4751 final Map<String,String> missingAliases; 4752 final Set<String> aliases; 4753 final StringArgument aliasArgument = 4754 subCommandParser.getStringArgument("alias"); 4755 if ((aliasArgument == null) || (! aliasArgument.isPresent())) 4756 { 4757 aliases = Collections.emptySet(); 4758 missingAliases = Collections.emptyMap(); 4759 } 4760 else 4761 { 4762 final List<String> values = aliasArgument.getValues(); 4763 aliases = new LinkedHashSet<>(StaticUtils.computeMapCapacity( 4764 values.size())); 4765 missingAliases = 4766 new LinkedHashMap<>(StaticUtils.computeMapCapacity(values.size())); 4767 for (final String alias : values) 4768 { 4769 final String lowerAlias = StaticUtils.toLowerCase(alias); 4770 aliases.add(StaticUtils.toLowerCase(lowerAlias)); 4771 missingAliases.put(lowerAlias, alias); 4772 } 4773 } 4774 4775 final String keystoreType; 4776 final File keystorePath = getKeystorePath(); 4777 try 4778 { 4779 keystoreType = inferKeystoreType(keystorePath); 4780 } 4781 catch (final LDAPException le) 4782 { 4783 Debug.debugException(le); 4784 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4785 return le.getResultCode(); 4786 } 4787 4788 final char[] keystorePassword; 4789 try 4790 { 4791 keystorePassword = getKeystorePassword(keystorePath); 4792 } 4793 catch (final LDAPException le) 4794 { 4795 Debug.debugException(le); 4796 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4797 return le.getResultCode(); 4798 } 4799 4800 final BooleanArgument displayKeytoolCommandArgument = 4801 subCommandParser.getBooleanArgument("display-keytool-command"); 4802 if ((displayKeytoolCommandArgument != null) && 4803 displayKeytoolCommandArgument.isPresent()) 4804 { 4805 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 4806 keytoolArgs.add("-list"); 4807 4808 keytoolArgs.add("-keystore"); 4809 keytoolArgs.add(keystorePath.getAbsolutePath()); 4810 keytoolArgs.add("-storetype"); 4811 keytoolArgs.add(keystoreType); 4812 4813 if (keystorePassword != null) 4814 { 4815 keytoolArgs.add("-storepass"); 4816 keytoolArgs.add("*****REDACTED*****"); 4817 } 4818 4819 for (final String alias : missingAliases.values()) 4820 { 4821 keytoolArgs.add("-alias"); 4822 keytoolArgs.add(alias); 4823 } 4824 4825 if (displayPEM) 4826 { 4827 keytoolArgs.add("-rfc"); 4828 } 4829 4830 if (verbose) 4831 { 4832 keytoolArgs.add("-v"); 4833 } 4834 4835 displayKeytoolCommand(keytoolArgs); 4836 } 4837 4838 4839 // Get the keystore. 4840 final KeyStore keystore; 4841 try 4842 { 4843 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 4844 } 4845 catch (final LDAPException le) 4846 { 4847 Debug.debugException(le); 4848 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4849 return le.getResultCode(); 4850 } 4851 4852 4853 // Display a message with the keystore type. 4854 wrapOut(0, WRAP_COLUMN, 4855 INFO_MANAGE_CERTS_LIST_KEYSTORE_TYPE.get(keystoreType)); 4856 4857 4858 // Iterate through the keystore and display the appropriate certificates. 4859 final Enumeration<String> aliasEnumeration; 4860 try 4861 { 4862 aliasEnumeration = keystore.aliases(); 4863 } 4864 catch (final Exception e) 4865 { 4866 Debug.debugException(e); 4867 err(); 4868 wrapErr(0, WRAP_COLUMN, 4869 ERR_MANAGE_CERTS_LIST_CERTS_CANNOT_GET_ALIASES.get( 4870 keystorePath.getAbsolutePath())); 4871 e.printStackTrace(getErr()); 4872 return ResultCode.LOCAL_ERROR; 4873 } 4874 4875 int listedCount = 0; 4876 ResultCode resultCode = ResultCode.SUCCESS; 4877 while (aliasEnumeration.hasMoreElements()) 4878 { 4879 final String alias = aliasEnumeration.nextElement(); 4880 final String lowerAlias = StaticUtils.toLowerCase(alias); 4881 if ((!aliases.isEmpty()) && (missingAliases.remove(lowerAlias) == null)) 4882 { 4883 // We don't care about this alias. 4884 continue; 4885 } 4886 4887 final X509Certificate[] certificateChain; 4888 try 4889 { 4890 // NOTE: Keystore entries that have private keys may have a certificate 4891 // chain associated with them (the end certificate plus all of the 4892 // issuer certificates). In that case all of those certificates in the 4893 // chain will be stored under the same alias, and the only way we can 4894 // access them is to call the getCertificateChain method. However, if 4895 // the keystore only has a certificate for the alias but no private key, 4896 // then the entry will not have a chain, and the call to 4897 // getCertificateChain will return null for that alias. We want to be 4898 // able to handle both of these cases, so we will first try 4899 // getCertificateChain to see if we can get a complete chain, but if 4900 // that returns null, then use getCertificate to see if we can get a 4901 // single certificate. That call to getCertificate can also return null 4902 // because the entry with this alias might be some other type of entry, 4903 // like a secret key entry. 4904 Certificate[] chain = keystore.getCertificateChain(alias); 4905 if ((chain == null) || (chain.length == 0)) 4906 { 4907 final Certificate cert = keystore.getCertificate(alias); 4908 if (cert == null) 4909 { 4910 continue; 4911 } 4912 else 4913 { 4914 chain = new Certificate[] { cert }; 4915 } 4916 } 4917 4918 certificateChain = new X509Certificate[chain.length]; 4919 for (int i = 0; i < chain.length; i++) 4920 { 4921 certificateChain[i] = new X509Certificate(chain[i].getEncoded()); 4922 } 4923 } 4924 catch (final Exception e) 4925 { 4926 Debug.debugException(e); 4927 err(); 4928 wrapErr(0, WRAP_COLUMN, 4929 ERR_MANAGE_CERTS_LIST_CERTS_ERROR_GETTING_CERT.get(alias, 4930 StaticUtils.getExceptionMessage(e))); 4931 resultCode = ResultCode.LOCAL_ERROR; 4932 continue; 4933 } 4934 4935 listedCount++; 4936 for (int i = 0; i < certificateChain.length; i++) 4937 { 4938 out(); 4939 if (certificateChain.length == 1) 4940 { 4941 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_ALIAS_WITHOUT_CHAIN.get( 4942 alias)); 4943 } 4944 else 4945 { 4946 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_ALIAS_WITH_CHAIN.get(alias, 4947 (i + 1), certificateChain.length)); 4948 } 4949 4950 printCertificate(certificateChain[i], "", verbose); 4951 4952 if (i == 0) 4953 { 4954 if (hasKeyAlias(keystore, alias)) 4955 { 4956 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_HAS_PK_YES.get()); 4957 } 4958 else 4959 { 4960 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_HAS_PK_NO.get()); 4961 } 4962 } 4963 4964 CertException signatureVerificationException = null; 4965 if (certificateChain[i].isSelfSigned()) 4966 { 4967 try 4968 { 4969 certificateChain[i].verifySignature(null); 4970 } 4971 catch (final CertException ce) 4972 { 4973 Debug.debugException(ce); 4974 signatureVerificationException = ce; 4975 } 4976 } 4977 else 4978 { 4979 X509Certificate issuerCertificate = null; 4980 try 4981 { 4982 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 4983 new AtomicReference<>(); 4984 final AtomicReference<DN> missingIssuerRef = 4985 new AtomicReference<>(); 4986 issuerCertificate = getIssuerCertificate(certificateChain[i], 4987 keystore, jvmDefaultTrustStoreRef, missingIssuerRef); 4988 } 4989 catch (final Exception e) 4990 { 4991 Debug.debugException(e); 4992 } 4993 4994 if (issuerCertificate == null) 4995 { 4996 signatureVerificationException = new CertException( 4997 ERR_MANAGE_CERTS_LIST_CERTS_VERIFY_SIGNATURE_NO_ISSUER.get( 4998 certificateChain[i].getIssuerDN())); 4999 } 5000 else 5001 { 5002 try 5003 { 5004 certificateChain[i].verifySignature(issuerCertificate); 5005 } 5006 catch (final CertException ce) 5007 { 5008 Debug.debugException(ce); 5009 signatureVerificationException = ce; 5010 } 5011 } 5012 } 5013 5014 if (signatureVerificationException == null) 5015 { 5016 wrapOut(0, WRAP_COLUMN, 5017 INFO_MANAGE_CERTS_LIST_CERTS_SIGNATURE_VALID.get()); 5018 } 5019 else 5020 { 5021 wrapErr(0, WRAP_COLUMN, 5022 signatureVerificationException.getMessage()); 5023 } 5024 5025 if (displayPEM) 5026 { 5027 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_PEM.get()); 5028 writePEMCertificate(getOut(), 5029 certificateChain[i].getX509CertificateBytes()); 5030 } 5031 } 5032 } 5033 5034 if (! missingAliases.isEmpty()) 5035 { 5036 err(); 5037 for (final String missingAlias : missingAliases.values()) 5038 { 5039 wrapErr(0, WRAP_COLUMN, 5040 WARN_MANAGE_CERTS_LIST_CERTS_ALIAS_NOT_IN_KS.get(missingAlias, 5041 keystorePath.getAbsolutePath())); 5042 resultCode = ResultCode.PARAM_ERROR; 5043 } 5044 } 5045 else if (listedCount == 0) 5046 { 5047 out(); 5048 if (keystorePassword == null) 5049 { 5050 wrapOut(0, WRAP_COLUMN, 5051 INFO_MANAGE_CERTS_LIST_CERTS_NO_CERTS_OR_KEYS_WITHOUT_PW.get()); 5052 } 5053 else 5054 { 5055 wrapOut(0, WRAP_COLUMN, 5056 INFO_MANAGE_CERTS_LIST_CERTS_NO_CERTS_OR_KEYS_WITH_PW.get()); 5057 } 5058 } 5059 5060 return resultCode; 5061 } 5062 5063 5064 5065 /** 5066 * Performs the necessary processing for the export-certificate subcommand. 5067 * 5068 * @return A result code that indicates whether the processing completed 5069 * successfully. 5070 */ 5071 @NotNull() 5072 private ResultCode doExportCertificate() 5073 { 5074 // Get the values of a number of configured arguments. 5075 final StringArgument aliasArgument = 5076 subCommandParser.getStringArgument("alias"); 5077 final String alias = aliasArgument.getValue(); 5078 5079 final BooleanArgument exportChainArgument = 5080 subCommandParser.getBooleanArgument("export-certificate-chain"); 5081 final boolean exportChain = 5082 ((exportChainArgument != null) && exportChainArgument.isPresent()); 5083 5084 final BooleanArgument separateFilePerCertificateArgument = 5085 subCommandParser.getBooleanArgument("separate-file-per-certificate"); 5086 final boolean separateFilePerCertificate = 5087 ((separateFilePerCertificateArgument != null) && 5088 separateFilePerCertificateArgument.isPresent()); 5089 5090 boolean exportPEM = true; 5091 final StringArgument outputFormatArgument = 5092 subCommandParser.getStringArgument("output-format"); 5093 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 5094 { 5095 final String format = outputFormatArgument.getValue().toLowerCase(); 5096 if (format.equals("der") || format.equals("binary") || 5097 format.equals("bin")) 5098 { 5099 exportPEM = false; 5100 } 5101 } 5102 5103 File outputFile = null; 5104 final FileArgument outputFileArgument = 5105 subCommandParser.getFileArgument("output-file"); 5106 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 5107 { 5108 outputFile = outputFileArgument.getValue(); 5109 } 5110 5111 if ((outputFile == null) && (! exportPEM)) 5112 { 5113 wrapErr(0, WRAP_COLUMN, 5114 ERR_MANAGE_CERTS_EXPORT_CERT_NO_FILE_WITH_DER.get()); 5115 return ResultCode.PARAM_ERROR; 5116 } 5117 5118 final String keystoreType; 5119 final File keystorePath = getKeystorePath(); 5120 try 5121 { 5122 keystoreType = inferKeystoreType(keystorePath); 5123 } 5124 catch (final LDAPException le) 5125 { 5126 Debug.debugException(le); 5127 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5128 return le.getResultCode(); 5129 } 5130 5131 final char[] keystorePassword; 5132 try 5133 { 5134 keystorePassword = getKeystorePassword(keystorePath); 5135 } 5136 catch (final LDAPException le) 5137 { 5138 Debug.debugException(le); 5139 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5140 return le.getResultCode(); 5141 } 5142 5143 final BooleanArgument displayKeytoolCommandArgument = 5144 subCommandParser.getBooleanArgument("display-keytool-command"); 5145 if ((displayKeytoolCommandArgument != null) && 5146 displayKeytoolCommandArgument.isPresent()) 5147 { 5148 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 5149 keytoolArgs.add("-list"); 5150 5151 keytoolArgs.add("-keystore"); 5152 keytoolArgs.add(keystorePath.getAbsolutePath()); 5153 keytoolArgs.add("-storetype"); 5154 keytoolArgs.add(keystoreType); 5155 5156 if (keystorePassword != null) 5157 { 5158 keytoolArgs.add("-storepass"); 5159 keytoolArgs.add("*****REDACTED*****"); 5160 } 5161 5162 keytoolArgs.add("-alias"); 5163 keytoolArgs.add(alias); 5164 5165 if (exportPEM) 5166 { 5167 keytoolArgs.add("-rfc"); 5168 } 5169 5170 if (outputFile != null) 5171 { 5172 keytoolArgs.add("-file"); 5173 keytoolArgs.add(outputFile.getAbsolutePath()); 5174 } 5175 5176 displayKeytoolCommand(keytoolArgs); 5177 } 5178 5179 5180 // Get the keystore. 5181 final KeyStore keystore; 5182 try 5183 { 5184 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5185 } 5186 catch (final LDAPException le) 5187 { 5188 Debug.debugException(le); 5189 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5190 return le.getResultCode(); 5191 } 5192 5193 5194 // Get the certificates to export. If the --export-certificate-chain 5195 // argument was provided, this can be multiple certificates. Otherwise, it 5196 // there will only be one. 5197 DN missingIssuerDN = null; 5198 final X509Certificate[] certificatesToExport; 5199 if (exportChain) 5200 { 5201 try 5202 { 5203 final AtomicReference<DN> missingIssuerRef = new AtomicReference<>(); 5204 certificatesToExport = 5205 getCertificateChain(alias, keystore, missingIssuerRef); 5206 missingIssuerDN = missingIssuerRef.get(); 5207 } 5208 catch (final LDAPException le) 5209 { 5210 Debug.debugException(le); 5211 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5212 return le.getResultCode(); 5213 } 5214 } 5215 else 5216 { 5217 try 5218 { 5219 final Certificate cert = keystore.getCertificate(alias); 5220 if (cert == null) 5221 { 5222 certificatesToExport = new X509Certificate[0]; 5223 } 5224 else 5225 { 5226 certificatesToExport = new X509Certificate[] 5227 { 5228 new X509Certificate(cert.getEncoded()) 5229 }; 5230 } 5231 } 5232 catch (final Exception e) 5233 { 5234 Debug.debugException(e); 5235 wrapErr(0, WRAP_COLUMN, 5236 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_GETTING_CERT.get(alias, 5237 keystorePath.getAbsolutePath())); 5238 e.printStackTrace(getErr()); 5239 return ResultCode.LOCAL_ERROR; 5240 } 5241 } 5242 5243 if (certificatesToExport.length == 0) 5244 { 5245 wrapErr(0, WRAP_COLUMN, 5246 ERR_MANAGE_CERTS_EXPORT_CERT_NO_CERT_WITH_ALIAS.get(alias, 5247 keystorePath.getAbsolutePath())); 5248 return ResultCode.PARAM_ERROR; 5249 } 5250 5251 5252 // Get a PrintStream to use for the output. 5253 int fileCounter = 1; 5254 String filename = null; 5255 PrintStream printStream; 5256 if (outputFile == null) 5257 { 5258 printStream = getOut(); 5259 } 5260 else 5261 { 5262 try 5263 { 5264 if ((certificatesToExport.length > 1) && separateFilePerCertificate) 5265 { 5266 filename = outputFile.getAbsolutePath() + '.' + fileCounter; 5267 } 5268 else 5269 { 5270 filename = outputFile.getAbsolutePath(); 5271 } 5272 printStream = new PrintStream(filename); 5273 } 5274 catch (final Exception e) 5275 { 5276 Debug.debugException(e); 5277 wrapErr(0, WRAP_COLUMN, 5278 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_OPENING_OUTPUT.get( 5279 outputFile.getAbsolutePath())); 5280 e.printStackTrace(getErr()); 5281 return ResultCode.LOCAL_ERROR; 5282 } 5283 } 5284 5285 try 5286 { 5287 for (final X509Certificate certificate : certificatesToExport) 5288 { 5289 try 5290 { 5291 if (separateFilePerCertificate && (certificatesToExport.length > 1)) 5292 { 5293 if (fileCounter > 1) 5294 { 5295 printStream.close(); 5296 filename = outputFile.getAbsolutePath() + '.' + fileCounter; 5297 printStream = new PrintStream(filename); 5298 } 5299 5300 fileCounter++; 5301 } 5302 5303 if (exportPEM) 5304 { 5305 writePEMCertificate(printStream, 5306 certificate.getX509CertificateBytes()); 5307 } 5308 else 5309 { 5310 printStream.write(certificate.getX509CertificateBytes()); 5311 } 5312 } 5313 catch (final Exception e) 5314 { 5315 Debug.debugException(e); 5316 wrapErr(0, WRAP_COLUMN, 5317 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_WRITING_CERT.get(alias, 5318 certificate.getSubjectDN())); 5319 e.printStackTrace(getErr()); 5320 return ResultCode.LOCAL_ERROR; 5321 } 5322 5323 if (outputFile != null) 5324 { 5325 out(); 5326 wrapOut(0, WRAP_COLUMN, 5327 INFO_MANAGE_CERTS_EXPORT_CERT_EXPORT_SUCCESSFUL.get(filename)); 5328 printCertificate(certificate, "", false); 5329 } 5330 } 5331 } 5332 finally 5333 { 5334 printStream.flush(); 5335 if (outputFile != null) 5336 { 5337 printStream.close(); 5338 } 5339 } 5340 5341 if (missingIssuerDN != null) 5342 { 5343 err(); 5344 wrapErr(0, WRAP_COLUMN, 5345 WARN_MANAGE_CERTS_EXPORT_CERT_MISSING_CERT_IN_CHAIN.get( 5346 missingIssuerDN, keystorePath.getAbsolutePath())); 5347 return ResultCode.NO_SUCH_OBJECT; 5348 } 5349 5350 return ResultCode.SUCCESS; 5351 } 5352 5353 5354 5355 /** 5356 * Performs the necessary processing for the export-private-key subcommand. 5357 * 5358 * @return A result code that indicates whether the processing completed 5359 * successfully. 5360 */ 5361 @NotNull() 5362 private ResultCode doExportPrivateKey() 5363 { 5364 // Get the values of a number of configured arguments. 5365 final StringArgument aliasArgument = 5366 subCommandParser.getStringArgument("alias"); 5367 final String alias = aliasArgument.getValue(); 5368 5369 boolean exportPEM = true; 5370 final StringArgument outputFormatArgument = 5371 subCommandParser.getStringArgument("output-format"); 5372 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 5373 { 5374 final String format = outputFormatArgument.getValue().toLowerCase(); 5375 if (format.equals("der") || format.equals("binary") || 5376 format.equals("bin")) 5377 { 5378 exportPEM = false; 5379 } 5380 } 5381 5382 File outputFile = null; 5383 final FileArgument outputFileArgument = 5384 subCommandParser.getFileArgument("output-file"); 5385 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 5386 { 5387 outputFile = outputFileArgument.getValue(); 5388 } 5389 5390 if ((outputFile == null) && (! exportPEM)) 5391 { 5392 wrapErr(0, WRAP_COLUMN, 5393 ERR_MANAGE_CERTS_EXPORT_KEY_NO_FILE_WITH_DER.get()); 5394 return ResultCode.PARAM_ERROR; 5395 } 5396 5397 final String keystoreType; 5398 final File keystorePath = getKeystorePath(); 5399 try 5400 { 5401 keystoreType = inferKeystoreType(keystorePath); 5402 } 5403 catch (final LDAPException le) 5404 { 5405 Debug.debugException(le); 5406 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5407 return le.getResultCode(); 5408 } 5409 5410 final char[] keystorePassword; 5411 try 5412 { 5413 keystorePassword = getKeystorePassword(keystorePath); 5414 } 5415 catch (final LDAPException le) 5416 { 5417 Debug.debugException(le); 5418 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5419 return le.getResultCode(); 5420 } 5421 5422 5423 // Get the keystore. 5424 final KeyStore keystore; 5425 try 5426 { 5427 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5428 } 5429 catch (final LDAPException le) 5430 { 5431 Debug.debugException(le); 5432 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5433 return le.getResultCode(); 5434 } 5435 5436 5437 // See if we need to use a private key password that is different from the 5438 // keystore password. 5439 final char[] privateKeyPassword; 5440 try 5441 { 5442 privateKeyPassword = 5443 getPrivateKeyPassword(keystore, alias, keystorePassword); 5444 } 5445 catch (final LDAPException le) 5446 { 5447 Debug.debugException(le); 5448 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5449 return le.getResultCode(); 5450 } 5451 5452 5453 // Get the password to use to encrypt the private key when it is exported. 5454 final char[] encryptionPassword; 5455 try 5456 { 5457 encryptionPassword = getPrivateKeyEncryptionPassword(false); 5458 } 5459 catch (final LDAPException le) 5460 { 5461 Debug.debugException(le); 5462 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5463 return le.getResultCode(); 5464 } 5465 5466 5467 // Get the private key to export. 5468 final PrivateKey privateKey; 5469 try 5470 { 5471 final Key key = keystore.getKey(alias, privateKeyPassword); 5472 if (key == null) 5473 { 5474 wrapErr(0, WRAP_COLUMN, 5475 ERR_MANAGE_CERTS_EXPORT_KEY_NO_KEY_WITH_ALIAS.get(alias, 5476 keystorePath.getAbsolutePath())); 5477 return ResultCode.PARAM_ERROR; 5478 } 5479 5480 privateKey = (PrivateKey) key; 5481 } 5482 catch (final UnrecoverableKeyException e) 5483 { 5484 Debug.debugException(e); 5485 wrapErr(0, WRAP_COLUMN, 5486 ERR_MANAGE_CERTS_EXPORT_KEY_WRONG_KEY_PW.get(alias, 5487 keystorePath.getAbsolutePath())); 5488 return ResultCode.PARAM_ERROR; 5489 } 5490 catch (final Exception e) 5491 { 5492 Debug.debugException(e); 5493 wrapErr(0, WRAP_COLUMN, 5494 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_GETTING_KEY.get(alias, 5495 keystorePath.getAbsolutePath())); 5496 e.printStackTrace(getErr()); 5497 return ResultCode.LOCAL_ERROR; 5498 } 5499 5500 5501 // Get a PrintStream to use for the output. 5502 final PrintStream printStream; 5503 if (outputFile == null) 5504 { 5505 printStream = getOut(); 5506 } 5507 else 5508 { 5509 try 5510 { 5511 printStream = new PrintStream(outputFile); 5512 } 5513 catch (final Exception e) 5514 { 5515 Debug.debugException(e); 5516 wrapErr(0, WRAP_COLUMN, 5517 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_OPENING_OUTPUT.get( 5518 outputFile.getAbsolutePath())); 5519 e.printStackTrace(getErr()); 5520 return ResultCode.LOCAL_ERROR; 5521 } 5522 } 5523 5524 try 5525 { 5526 try 5527 { 5528 if (exportPEM) 5529 { 5530 writePEMPrivateKey(printStream, privateKey.getEncoded(), 5531 encryptionPassword); 5532 } 5533 else 5534 { 5535 if (encryptionPassword == null) 5536 { 5537 printStream.write(privateKey.getEncoded()); 5538 } 5539 else 5540 { 5541 final byte[] encryptedPrivateKey = 5542 PKCS8EncryptionHandler.encryptPrivateKey( 5543 privateKey.getEncoded(), encryptionPassword, 5544 new PKCS8EncryptionProperties()); 5545 printStream.write(encryptedPrivateKey); 5546 } 5547 } 5548 } 5549 catch (final Exception e) 5550 { 5551 Debug.debugException(e); 5552 wrapErr(0, WRAP_COLUMN, 5553 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_WRITING_KEY.get(alias)); 5554 e.printStackTrace(getErr()); 5555 return ResultCode.LOCAL_ERROR; 5556 } 5557 5558 if (outputFile != null) 5559 { 5560 out(); 5561 wrapOut(0, WRAP_COLUMN, 5562 INFO_MANAGE_CERTS_EXPORT_KEY_EXPORT_SUCCESSFUL.get()); 5563 } 5564 } 5565 finally 5566 { 5567 printStream.flush(); 5568 if (outputFile != null) 5569 { 5570 printStream.close(); 5571 } 5572 } 5573 5574 return ResultCode.SUCCESS; 5575 } 5576 5577 5578 5579 /** 5580 * Performs the necessary processing for the import-certificate subcommand. 5581 * 5582 * @return A result code that indicates whether the processing completed 5583 * successfully. 5584 */ 5585 @NotNull() 5586 private ResultCode doImportCertificate() 5587 { 5588 // Get the values of a number of configured arguments. 5589 final StringArgument aliasArgument = 5590 subCommandParser.getStringArgument("alias"); 5591 final String alias = aliasArgument.getValue(); 5592 5593 final FileArgument certificateFileArgument = 5594 subCommandParser.getFileArgument("certificate-file"); 5595 final List<File> certFiles = certificateFileArgument.getValues(); 5596 5597 final File privateKeyFile; 5598 final FileArgument privateKeyFileArgument = 5599 subCommandParser.getFileArgument("private-key-file"); 5600 if ((privateKeyFileArgument != null) && privateKeyFileArgument.isPresent()) 5601 { 5602 privateKeyFile = privateKeyFileArgument.getValue(); 5603 } 5604 else 5605 { 5606 privateKeyFile = null; 5607 } 5608 5609 final BooleanArgument noPromptArgument = 5610 subCommandParser.getBooleanArgument("no-prompt"); 5611 final boolean noPrompt = 5612 ((noPromptArgument != null) && noPromptArgument.isPresent()); 5613 5614 final String keystoreType; 5615 final File keystorePath = getKeystorePath(); 5616 final boolean isNewKeystore = (! keystorePath.exists()); 5617 try 5618 { 5619 keystoreType = inferKeystoreType(keystorePath); 5620 } 5621 catch (final LDAPException le) 5622 { 5623 Debug.debugException(le); 5624 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5625 return le.getResultCode(); 5626 } 5627 5628 5629 final char[] keystorePassword; 5630 try 5631 { 5632 keystorePassword = getKeystorePassword(keystorePath); 5633 } 5634 catch (final LDAPException le) 5635 { 5636 Debug.debugException(le); 5637 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5638 return le.getResultCode(); 5639 } 5640 5641 5642 // Read the contents of the certificate files. 5643 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 5644 for (final File certFile : certFiles) 5645 { 5646 try 5647 { 5648 final List<X509Certificate> certs = readCertificatesFromFile(certFile); 5649 if (certs.isEmpty()) 5650 { 5651 wrapErr(0, WRAP_COLUMN, 5652 ERR_MANAGE_CERTS_IMPORT_CERT_NO_CERTS_IN_FILE.get( 5653 certFile.getAbsolutePath())); 5654 return ResultCode.PARAM_ERROR; 5655 } 5656 5657 certList.addAll(certs); 5658 } 5659 catch (final LDAPException le) 5660 { 5661 Debug.debugException(le); 5662 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5663 return le.getResultCode(); 5664 } 5665 } 5666 5667 5668 // See if there is a password to use to decrypt the private key that is 5669 // being imported. 5670 final char[] encryptionPassword; 5671 try 5672 { 5673 encryptionPassword = getPrivateKeyEncryptionPassword(true); 5674 } 5675 catch (final LDAPException le) 5676 { 5677 Debug.debugException(le); 5678 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5679 return le.getResultCode(); 5680 } 5681 5682 5683 // If a private key file was specified, then read the private key. 5684 final PKCS8PrivateKey privateKey; 5685 if (privateKeyFile == null) 5686 { 5687 privateKey = null; 5688 } 5689 else 5690 { 5691 try 5692 { 5693 privateKey = readPrivateKeyFromFile(privateKeyFile, encryptionPassword); 5694 } 5695 catch (final LDAPException le) 5696 { 5697 Debug.debugException(le); 5698 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5699 return le.getResultCode(); 5700 } 5701 } 5702 5703 5704 // Get the keystore. 5705 final KeyStore keystore; 5706 try 5707 { 5708 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5709 } 5710 catch (final LDAPException le) 5711 { 5712 Debug.debugException(le); 5713 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5714 return le.getResultCode(); 5715 } 5716 5717 5718 // If there is a private key, then see if we need to use a private key 5719 // password that is different from the keystore password. 5720 final char[] privateKeyPassword; 5721 try 5722 { 5723 privateKeyPassword = 5724 getPrivateKeyPassword(keystore, alias, keystorePassword); 5725 } 5726 catch (final LDAPException le) 5727 { 5728 Debug.debugException(le); 5729 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5730 return le.getResultCode(); 5731 } 5732 5733 5734 // If we should display an equivalent keytool command, then do that now. 5735 final BooleanArgument displayKeytoolCommandArgument = 5736 subCommandParser.getBooleanArgument("display-keytool-command"); 5737 if ((displayKeytoolCommandArgument != null) && 5738 displayKeytoolCommandArgument.isPresent()) 5739 { 5740 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 5741 keytoolArgs.add("-import"); 5742 5743 keytoolArgs.add("-keystore"); 5744 keytoolArgs.add(keystorePath.getAbsolutePath()); 5745 keytoolArgs.add("-storetype"); 5746 keytoolArgs.add(keystoreType); 5747 keytoolArgs.add("-storepass"); 5748 keytoolArgs.add("*****REDACTED*****"); 5749 keytoolArgs.add("-keypass"); 5750 keytoolArgs.add("*****REDACTED*****"); 5751 keytoolArgs.add("-alias"); 5752 keytoolArgs.add(alias); 5753 keytoolArgs.add("-file"); 5754 keytoolArgs.add(certFiles.get(0).getAbsolutePath()); 5755 keytoolArgs.add("-trustcacerts"); 5756 5757 displayKeytoolCommand(keytoolArgs); 5758 } 5759 5760 5761 // Look at all the certificates to be imported. Make sure that every 5762 // subsequent certificate in the chain is the issuer for the previous. 5763 final Iterator<X509Certificate> certIterator = certList.iterator(); 5764 X509Certificate subjectCert = certIterator.next(); 5765 while (true) 5766 { 5767 if (subjectCert.isSelfSigned()) 5768 { 5769 if (certIterator.hasNext()) 5770 { 5771 wrapErr(0, WRAP_COLUMN, 5772 ERR_MANAGE_CERTS_IMPORT_CERT_SELF_SIGNED_NOT_LAST.get( 5773 subjectCert.getSubjectDN())); 5774 return ResultCode.PARAM_ERROR; 5775 } 5776 } 5777 5778 if (! certIterator.hasNext()) 5779 { 5780 break; 5781 } 5782 5783 final X509Certificate issuerCert = certIterator.next(); 5784 final StringBuilder notIssuerReason = new StringBuilder(); 5785 if (! issuerCert.isIssuerFor(subjectCert, notIssuerReason)) 5786 { 5787 // In some cases, the process of signing a certificate can put two 5788 // certificates in the output file (both the signed certificate and its 5789 // issuer. If the same certificate is in the chain twice, then we'll 5790 // silently ignore it. 5791 if (Arrays.equals(issuerCert.getX509CertificateBytes(), 5792 subjectCert.getX509CertificateBytes())) 5793 { 5794 certIterator.remove(); 5795 } 5796 else 5797 { 5798 wrapErr(0, WRAP_COLUMN, 5799 ERR_MANAGE_CERTS_IMPORT_CERT_NEXT_NOT_ISSUER_OF_PREV.get( 5800 notIssuerReason.toString())); 5801 return ResultCode.PARAM_ERROR; 5802 } 5803 } 5804 5805 subjectCert = issuerCert; 5806 } 5807 5808 5809 // If the last certificate in the chain is not self-signed, then make sure 5810 // that we can complete the chain using other certificates in the keystore 5811 // or in the JVM's set of default trusted issuers. If we can't complete 5812 // the chain, then that's an error, although we'll go ahead and proceed 5813 // anyway with the import if we're not also importing a private key. 5814 final ArrayList<X509Certificate> chain; 5815 if (certList.get(certList.size() - 1).isSelfSigned()) 5816 { 5817 chain = certList; 5818 } 5819 else 5820 { 5821 chain = new ArrayList<>(certList.size() + 5); 5822 chain.addAll(certList); 5823 5824 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 5825 new AtomicReference<>(); 5826 final AtomicReference<DN> missingIssuerRef = new AtomicReference<>(); 5827 5828 X509Certificate c = certList.get(certList.size() - 1); 5829 while (! c.isSelfSigned()) 5830 { 5831 final X509Certificate issuer; 5832 try 5833 { 5834 issuer = getIssuerCertificate(c, keystore, jvmDefaultTrustStoreRef, 5835 missingIssuerRef); 5836 } 5837 catch (final Exception e) 5838 { 5839 Debug.debugException(e); 5840 wrapErr(0, WRAP_COLUMN, 5841 ERR_MANAGE_CERTS_IMPORT_CERT_CANNOT_GET_ISSUER.get( 5842 c.getIssuerDN())); 5843 e.printStackTrace(getErr()); 5844 return ResultCode.LOCAL_ERROR; 5845 } 5846 5847 if (issuer == null) 5848 { 5849 final byte[] authorityKeyIdentifier = getAuthorityKeyIdentifier(c); 5850 5851 // We couldn't find the issuer certificate. If we're importing a 5852 // private key, or if the keystore already has a key entry with the 5853 // same alias that we're going to use, then this is definitely an 5854 // error because we can only write a key entry if we have a complete 5855 // certificate chain. 5856 // 5857 // If we weren't explicitly provided with a private key, then it's 5858 // still an undesirable thing to import a certificate without having 5859 // the complete set of issuers, but we'll go ahead and let it slide 5860 // with just a warning. 5861 if ((privateKey != null) || hasKeyAlias(keystore, alias)) 5862 { 5863 if (authorityKeyIdentifier == null) 5864 { 5865 err(); 5866 wrapErr(0, WRAP_COLUMN, 5867 ERR_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_NO_AKI.get( 5868 c.getIssuerDN())); 5869 } 5870 else 5871 { 5872 err(); 5873 wrapErr(0, WRAP_COLUMN, 5874 ERR_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_WITH_AKI.get( 5875 c.getIssuerDN(), 5876 toColonDelimitedHex(authorityKeyIdentifier))); 5877 } 5878 5879 return ResultCode.PARAM_ERROR; 5880 } 5881 else 5882 { 5883 if (authorityKeyIdentifier == null) 5884 { 5885 err(); 5886 wrapErr(0, WRAP_COLUMN, 5887 WARN_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_NO_AKI.get( 5888 c.getIssuerDN())); 5889 } 5890 else 5891 { 5892 err(); 5893 wrapErr(0, WRAP_COLUMN, 5894 WARN_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_WITH_AKI.get( 5895 c.getIssuerDN(), 5896 toColonDelimitedHex(authorityKeyIdentifier))); 5897 } 5898 5899 break; 5900 } 5901 } 5902 else 5903 { 5904 chain.add(issuer); 5905 c = issuer; 5906 } 5907 } 5908 } 5909 5910 5911 // If we're going to import a private key with a certificate chain, then 5912 // perform the necessary validation and do the import. 5913 if (privateKey != null) 5914 { 5915 // Make sure that the keystore doesn't already have a key or certificate 5916 // with the specified alias. 5917 if (hasKeyAlias(keystore, alias)) 5918 { 5919 wrapErr(0, WRAP_COLUMN, 5920 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_PK_KEY_ALIAS_CONFLICT.get( 5921 alias)); 5922 return ResultCode.PARAM_ERROR; 5923 } 5924 else if (hasCertificateAlias(keystore, alias)) 5925 { 5926 wrapErr(0, WRAP_COLUMN, 5927 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_PK_CERT_ALIAS_CONFLICT.get( 5928 alias)); 5929 return ResultCode.PARAM_ERROR; 5930 } 5931 5932 5933 // Make sure that the private key has a key algorithm of either RSA or EC, 5934 // and convert it into a Java PrivateKey object. 5935 final PrivateKey javaPrivateKey; 5936 try 5937 { 5938 javaPrivateKey = privateKey.toPrivateKey(); 5939 } 5940 catch (final Exception e) 5941 { 5942 Debug.debugException(e); 5943 wrapErr(0, WRAP_COLUMN, 5944 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_KEY.get( 5945 privateKeyFile.getAbsolutePath())); 5946 e.printStackTrace(getErr()); 5947 return ResultCode.LOCAL_ERROR; 5948 } 5949 5950 5951 // Convert the certificate chain into a Java Certificate[]. 5952 final Certificate[] javaCertificateChain = new Certificate[chain.size()]; 5953 for (int i=0; i < javaCertificateChain.length; i++) 5954 { 5955 final X509Certificate c = chain.get(i); 5956 try 5957 { 5958 javaCertificateChain[i] = c.toCertificate(); 5959 } 5960 catch (final Exception e) 5961 { 5962 Debug.debugException(e); 5963 wrapErr(0, WRAP_COLUMN, 5964 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 5965 c.getSubjectDN())); 5966 e.printStackTrace(getErr()); 5967 return ResultCode.LOCAL_ERROR; 5968 } 5969 } 5970 5971 5972 // Prompt the user to confirm the import, if appropriate. 5973 if (! noPrompt) 5974 { 5975 out(); 5976 wrapOut(0, WRAP_COLUMN, 5977 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_NEW_KEY.get( 5978 alias)); 5979 5980 for (final X509Certificate c : chain) 5981 { 5982 out(); 5983 printCertificate(c, "", false); 5984 } 5985 5986 out(); 5987 5988 try 5989 { 5990 if (! promptForYesNo( 5991 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 5992 { 5993 wrapErr(0, WRAP_COLUMN, 5994 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 5995 return ResultCode.USER_CANCELED; 5996 } 5997 } 5998 catch (final LDAPException le) 5999 { 6000 Debug.debugException(le); 6001 err(); 6002 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6003 return le.getResultCode(); 6004 } 6005 } 6006 6007 6008 // Set the private key entry in the keystore. 6009 try 6010 { 6011 keystore.setKeyEntry(alias, javaPrivateKey, privateKeyPassword, 6012 javaCertificateChain); 6013 } 6014 catch (final Exception e) 6015 { 6016 Debug.debugException(e); 6017 wrapErr(0, WRAP_COLUMN, 6018 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CHAIN.get( 6019 alias)); 6020 e.printStackTrace(getErr()); 6021 return ResultCode.LOCAL_ERROR; 6022 } 6023 6024 6025 // Write the updated keystore to disk. 6026 try 6027 { 6028 writeKeystore(keystore, keystorePath, keystorePassword); 6029 } 6030 catch (final LDAPException le) 6031 { 6032 Debug.debugException(le); 6033 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6034 return le.getResultCode(); 6035 } 6036 6037 if (isNewKeystore) 6038 { 6039 out(); 6040 wrapOut(0, WRAP_COLUMN, 6041 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6042 getUserFriendlyKeystoreType(keystoreType))); 6043 } 6044 6045 out(); 6046 wrapOut(0, WRAP_COLUMN, 6047 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITH_PK.get()); 6048 return ResultCode.SUCCESS; 6049 } 6050 6051 6052 // If we've gotten here, then we were given one or more certificates but no 6053 // private key. See if the keystore already has a certificate entry with 6054 // the specified alias. If so, then that's always an error. 6055 if (hasCertificateAlias(keystore, alias)) 6056 { 6057 wrapErr(0, WRAP_COLUMN, 6058 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_CONFLICTING_CERT_ALIAS.get(alias)); 6059 return ResultCode.PARAM_ERROR; 6060 } 6061 6062 6063 // See if the keystore already has a key entry with the specified alias. 6064 // If so, then it may or may not be an error. This can happen if we 6065 // generated a certificate signing request from an existing key pair, and 6066 // now want to import the signed certificate. If that is the case, then we 6067 // will replace the existing key entry with a new one that contains the full 6068 // new certificate chain and the existing private key, but only if the 6069 // new certificate uses the same public key as the certificate at the head 6070 // of the existing chain in that alias. 6071 if (hasKeyAlias(keystore, alias)) 6072 { 6073 // Make sure that the existing key pair uses the same public key as the 6074 // new certificate we are importing. 6075 final PrivateKey existingPrivateKey; 6076 final Certificate[] existingChain; 6077 final X509Certificate existingEndCertificate; 6078 try 6079 { 6080 existingPrivateKey = 6081 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 6082 existingChain = keystore.getCertificateChain(alias); 6083 existingEndCertificate = 6084 new X509Certificate(existingChain[0].getEncoded()); 6085 } 6086 catch (final Exception e) 6087 { 6088 Debug.debugException(e); 6089 wrapErr(0, WRAP_COLUMN, 6090 ERR_MANAGE_CERTS_IMPORT_CERT_INTO_KEY_ALIAS_CANNOT_GET_KEY.get( 6091 alias)); 6092 e.printStackTrace(getErr()); 6093 return ResultCode.LOCAL_ERROR; 6094 } 6095 6096 final boolean[] existingPublicKeyBits = 6097 existingEndCertificate.getEncodedPublicKey().getBits(); 6098 final boolean[] newPublicKeyBits = 6099 chain.get(0).getEncodedPublicKey().getBits(); 6100 if (! Arrays.equals(existingPublicKeyBits, newPublicKeyBits)) 6101 { 6102 wrapErr(0, WRAP_COLUMN, 6103 ERR_MANAGE_CERTS_IMPORT_CERT_INTO_KEY_ALIAS_KEY_MISMATCH.get( 6104 alias)); 6105 return ResultCode.PARAM_ERROR; 6106 } 6107 6108 6109 // Prepare the new certificate chain to store in the alias. 6110 final Certificate[] newChain = new Certificate[chain.size()]; 6111 for (int i=0; i < chain.size(); i++) 6112 { 6113 final X509Certificate c = chain.get(i); 6114 try 6115 { 6116 newChain[i] = c.toCertificate(); 6117 } 6118 catch (final Exception e) 6119 { 6120 Debug.debugException(e); 6121 wrapErr(0, WRAP_COLUMN, 6122 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 6123 c.getSubjectDN())); 6124 e.printStackTrace(getErr()); 6125 return ResultCode.LOCAL_ERROR; 6126 } 6127 } 6128 6129 6130 // Prompt the user to confirm the import, if appropriate. 6131 if (! noPrompt) 6132 { 6133 out(); 6134 wrapOut(0, WRAP_COLUMN, 6135 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_EXISTING_KEY. 6136 get(alias)); 6137 6138 for (final X509Certificate c : chain) 6139 { 6140 out(); 6141 printCertificate(c, "", false); 6142 } 6143 6144 out(); 6145 6146 try 6147 { 6148 if (! promptForYesNo( 6149 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 6150 { 6151 wrapErr(0, WRAP_COLUMN, 6152 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 6153 return ResultCode.USER_CANCELED; 6154 } 6155 } 6156 catch (final LDAPException le) 6157 { 6158 Debug.debugException(le); 6159 err(); 6160 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6161 return le.getResultCode(); 6162 } 6163 } 6164 6165 6166 // Set the private key entry in the keystore. 6167 try 6168 { 6169 keystore.setKeyEntry(alias, existingPrivateKey, privateKeyPassword, 6170 newChain); 6171 } 6172 catch (final Exception e) 6173 { 6174 Debug.debugException(e); 6175 wrapErr(0, WRAP_COLUMN, 6176 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CHAIN.get( 6177 alias)); 6178 e.printStackTrace(getErr()); 6179 return ResultCode.LOCAL_ERROR; 6180 } 6181 6182 6183 // Write the updated keystore to disk. 6184 try 6185 { 6186 writeKeystore(keystore, keystorePath, keystorePassword); 6187 } 6188 catch (final LDAPException le) 6189 { 6190 Debug.debugException(le); 6191 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6192 return le.getResultCode(); 6193 } 6194 6195 out(); 6196 6197 if (isNewKeystore) 6198 { 6199 wrapOut(0, WRAP_COLUMN, 6200 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6201 getUserFriendlyKeystoreType(keystoreType))); 6202 } 6203 6204 wrapOut(0, WRAP_COLUMN, 6205 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITHOUT_PK.get()); 6206 return ResultCode.SUCCESS; 6207 } 6208 6209 6210 // If we've gotten here, then we know that we're just going to add 6211 // certificate entries to the keystore. Iterate through the certificates 6212 // and add them to the keystore under the appropriate aliases, first making 6213 // sure that the alias isn't already in use. 6214 final LinkedHashMap<String,X509Certificate> certMap = 6215 new LinkedHashMap<>(StaticUtils.computeMapCapacity(certList.size())); 6216 for (int i=0; i < certList.size(); i++) 6217 { 6218 final X509Certificate x509Certificate = certList.get(i); 6219 final Certificate javaCertificate; 6220 try 6221 { 6222 javaCertificate = x509Certificate.toCertificate(); 6223 } 6224 catch (final Exception e) 6225 { 6226 Debug.debugException(e); 6227 wrapErr(0, WRAP_COLUMN, 6228 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 6229 x509Certificate.getSubjectDN())); 6230 e.printStackTrace(getErr()); 6231 return ResultCode.LOCAL_ERROR; 6232 } 6233 6234 final String certAlias; 6235 if (i == 0) 6236 { 6237 certAlias = alias; 6238 } 6239 else if (certList.size() > 2) 6240 { 6241 certAlias = alias + "-issuer-" + i; 6242 } 6243 else 6244 { 6245 certAlias = alias + "-issuer"; 6246 } 6247 6248 certMap.put(certAlias, x509Certificate); 6249 6250 if (hasKeyAlias(keystore, certAlias) || 6251 hasCertificateAlias(keystore, certAlias)) 6252 { 6253 wrapErr(0, WRAP_COLUMN, 6254 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_CONFLICTING_ISSUER_ALIAS.get( 6255 x509Certificate.getSubjectDN(), certAlias)); 6256 return ResultCode.PARAM_ERROR; 6257 } 6258 6259 try 6260 { 6261 keystore.setCertificateEntry(certAlias, javaCertificate); 6262 } 6263 catch (final Exception e) 6264 { 6265 Debug.debugException(e); 6266 wrapErr(0, WRAP_COLUMN, 6267 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CERT.get( 6268 x509Certificate.getSubjectDN(), alias)); 6269 e.printStackTrace(getErr()); 6270 return ResultCode.LOCAL_ERROR; 6271 } 6272 } 6273 6274 6275 // Prompt about whether to perform the import, if appropriate. 6276 if (! noPrompt) 6277 { 6278 out(); 6279 wrapOut(0, WRAP_COLUMN, 6280 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_NO_KEY. 6281 get(alias)); 6282 6283 for (final Map.Entry<String,X509Certificate> e : certMap.entrySet()) 6284 { 6285 out(); 6286 wrapOut(0, WRAP_COLUMN, 6287 INFO_MANAGE_CERTS_IMPORT_CERT_LABEL_ALIAS.get(e.getKey())); 6288 printCertificate(e.getValue(), "", false); 6289 } 6290 6291 out(); 6292 6293 try 6294 { 6295 if (! promptForYesNo( 6296 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 6297 { 6298 wrapErr(0, WRAP_COLUMN, 6299 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 6300 return ResultCode.USER_CANCELED; 6301 } 6302 } 6303 catch (final LDAPException le) 6304 { 6305 Debug.debugException(le); 6306 err(); 6307 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6308 return le.getResultCode(); 6309 } 6310 } 6311 6312 6313 // Write the updated keystore to disk. 6314 try 6315 { 6316 writeKeystore(keystore, keystorePath, keystorePassword); 6317 } 6318 catch (final LDAPException le) 6319 { 6320 Debug.debugException(le); 6321 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6322 return le.getResultCode(); 6323 } 6324 6325 out(); 6326 6327 if (isNewKeystore) 6328 { 6329 wrapOut(0, WRAP_COLUMN, 6330 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6331 getUserFriendlyKeystoreType(keystoreType))); 6332 } 6333 6334 wrapOut(0, WRAP_COLUMN, 6335 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITHOUT_PK.get()); 6336 return ResultCode.SUCCESS; 6337 } 6338 6339 6340 6341 /** 6342 * Performs the necessary processing for the delete-certificate subcommand. 6343 * 6344 * @return A result code that indicates whether the processing completed 6345 * successfully. 6346 */ 6347 @NotNull() 6348 private ResultCode doDeleteCertificate() 6349 { 6350 // Get the values of a number of configured arguments. 6351 final StringArgument aliasArgument = 6352 subCommandParser.getStringArgument("alias"); 6353 final String alias = aliasArgument.getValue(); 6354 6355 final BooleanArgument noPromptArgument = 6356 subCommandParser.getBooleanArgument("no-prompt"); 6357 final boolean noPrompt = 6358 ((noPromptArgument != null) && noPromptArgument.isPresent()); 6359 6360 final String keystoreType; 6361 final File keystorePath = getKeystorePath(); 6362 try 6363 { 6364 keystoreType = inferKeystoreType(keystorePath); 6365 } 6366 catch (final LDAPException le) 6367 { 6368 Debug.debugException(le); 6369 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6370 return le.getResultCode(); 6371 } 6372 6373 final char[] keystorePassword; 6374 try 6375 { 6376 keystorePassword = getKeystorePassword(keystorePath); 6377 } 6378 catch (final LDAPException le) 6379 { 6380 Debug.debugException(le); 6381 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6382 return le.getResultCode(); 6383 } 6384 6385 final BooleanArgument displayKeytoolCommandArgument = 6386 subCommandParser.getBooleanArgument("display-keytool-command"); 6387 if ((displayKeytoolCommandArgument != null) && 6388 displayKeytoolCommandArgument.isPresent()) 6389 { 6390 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 6391 keytoolArgs.add("-delete"); 6392 6393 keytoolArgs.add("-keystore"); 6394 keytoolArgs.add(keystorePath.getAbsolutePath()); 6395 keytoolArgs.add("-storetype"); 6396 keytoolArgs.add(keystoreType); 6397 keytoolArgs.add("-storepass"); 6398 keytoolArgs.add("*****REDACTED*****"); 6399 keytoolArgs.add("-alias"); 6400 keytoolArgs.add(alias); 6401 6402 displayKeytoolCommand(keytoolArgs); 6403 } 6404 6405 6406 // Get the keystore. 6407 final KeyStore keystore; 6408 try 6409 { 6410 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 6411 } 6412 catch (final LDAPException le) 6413 { 6414 Debug.debugException(le); 6415 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6416 return le.getResultCode(); 6417 } 6418 6419 6420 // Get the entry for the specified alias. 6421 final boolean hasPrivateKey; 6422 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 6423 if (hasCertificateAlias(keystore, alias)) 6424 { 6425 try 6426 { 6427 hasPrivateKey = false; 6428 certList.add( 6429 new X509Certificate(keystore.getCertificate(alias).getEncoded())); 6430 } 6431 catch (final Exception e) 6432 { 6433 Debug.debugException(e); 6434 wrapErr(0, WRAP_COLUMN, 6435 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_GETTING_CERT.get(alias)); 6436 e.printStackTrace(getErr()); 6437 return ResultCode.LOCAL_ERROR; 6438 } 6439 } 6440 else if (hasKeyAlias(keystore, alias)) 6441 { 6442 try 6443 { 6444 hasPrivateKey = true; 6445 for (final Certificate c : keystore.getCertificateChain(alias)) 6446 { 6447 certList.add(new X509Certificate(c.getEncoded())); 6448 } 6449 } 6450 catch (final Exception e) 6451 { 6452 Debug.debugException(e); 6453 wrapErr(0, WRAP_COLUMN, 6454 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_GETTING_CHAIN.get(alias)); 6455 e.printStackTrace(getErr()); 6456 return ResultCode.LOCAL_ERROR; 6457 } 6458 } 6459 else 6460 { 6461 wrapErr(0, WRAP_COLUMN, 6462 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_ALIAS_NOT_CERT_OR_KEY.get(alias)); 6463 return ResultCode.PARAM_ERROR; 6464 } 6465 6466 6467 // Prompt about whether to perform the delete, if appropriate. 6468 if (! noPrompt) 6469 { 6470 out(); 6471 if (! hasPrivateKey) 6472 { 6473 wrapOut(0, WRAP_COLUMN, 6474 INFO_MANAGE_CERTS_DELETE_CERT_CONFIRM_DELETE_CERT.get()); 6475 } 6476 else 6477 { 6478 wrapOut(0, WRAP_COLUMN, 6479 INFO_MANAGE_CERTS_DELETE_CERT_CONFIRM_DELETE_CHAIN.get()); 6480 } 6481 6482 for (final X509Certificate c : certList) 6483 { 6484 out(); 6485 printCertificate(c, "", false); 6486 } 6487 6488 out(); 6489 6490 try 6491 { 6492 if (! promptForYesNo( 6493 INFO_MANAGE_CERTS_DELETE_CERT_PROMPT_DELETE.get())) 6494 { 6495 wrapErr(0, WRAP_COLUMN, 6496 ERR_MANAGE_CERTS_DELETE_CERT_CANCELED.get()); 6497 return ResultCode.USER_CANCELED; 6498 } 6499 } 6500 catch (final LDAPException le) 6501 { 6502 Debug.debugException(le); 6503 err(); 6504 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6505 return le.getResultCode(); 6506 } 6507 } 6508 6509 6510 // Delete the entry from the keystore. 6511 try 6512 { 6513 keystore.deleteEntry(alias); 6514 } 6515 catch (final Exception e) 6516 { 6517 Debug.debugException(e); 6518 wrapErr(0, WRAP_COLUMN, 6519 ERR_MANAGE_CERTS_DELETE_CERT_DELETE_ERROR.get(alias)); 6520 e.printStackTrace(getErr()); 6521 return ResultCode.LOCAL_ERROR; 6522 } 6523 6524 6525 // Write the updated keystore to disk. 6526 try 6527 { 6528 writeKeystore(keystore, keystorePath, keystorePassword); 6529 } 6530 catch (final LDAPException le) 6531 { 6532 Debug.debugException(le); 6533 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6534 return le.getResultCode(); 6535 } 6536 6537 if (certList.size() == 1) 6538 { 6539 out(); 6540 wrapOut(0, WRAP_COLUMN, 6541 INFO_MANAGE_CERTS_DELETE_CERT_DELETED_CERT.get()); 6542 } 6543 else 6544 { 6545 out(); 6546 wrapOut(0, WRAP_COLUMN, 6547 INFO_MANAGE_CERTS_DELETE_CERT_DELETED_CHAIN.get()); 6548 } 6549 6550 return ResultCode.SUCCESS; 6551 } 6552 6553 6554 6555 /** 6556 * Performs the necessary processing for the generate-self-signed-certificate, 6557 * generate-certificate-signing-request, and sign-certificate-signing-request 6558 * subcommands. 6559 * 6560 * @return A result code that indicates whether the processing completed 6561 * successfully. 6562 */ 6563 @NotNull() 6564 private ResultCode doGenerateOrSignCertificateOrCSR() 6565 { 6566 // Figure out which subcommand we're processing. 6567 final boolean isGenerateCertificate; 6568 final boolean isGenerateCSR; 6569 final boolean isSignCSR; 6570 final SubCommand selectedSubCommand = globalParser.getSelectedSubCommand(); 6571 if (selectedSubCommand.hasName("generate-self-signed-certificate")) 6572 { 6573 isGenerateCertificate = true; 6574 isGenerateCSR = false; 6575 isSignCSR = false; 6576 } 6577 else if (selectedSubCommand.hasName("generate-certificate-signing-request")) 6578 { 6579 isGenerateCertificate = false; 6580 isGenerateCSR = true; 6581 isSignCSR = false; 6582 } 6583 else 6584 { 6585 Validator.ensureTrue( 6586 selectedSubCommand.hasName("sign-certificate-signing-request")); 6587 isGenerateCertificate = false; 6588 isGenerateCSR = false; 6589 isSignCSR = true; 6590 } 6591 6592 6593 // Get the values of a number of configured arguments. 6594 final StringArgument aliasArgument = 6595 subCommandParser.getStringArgument("alias"); 6596 final String alias = aliasArgument.getValue(); 6597 6598 final File keystorePath = getKeystorePath(); 6599 final boolean isNewKeystore = (! keystorePath.exists()); 6600 6601 DN subjectDN = null; 6602 final DNArgument subjectDNArgument = 6603 subCommandParser.getDNArgument("subject-dn"); 6604 if ((subjectDNArgument != null) && subjectDNArgument.isPresent()) 6605 { 6606 subjectDN = subjectDNArgument.getValue(); 6607 } 6608 6609 File inputFile = null; 6610 final FileArgument inputFileArgument = 6611 subCommandParser.getFileArgument("input-file"); 6612 if ((inputFileArgument != null) && inputFileArgument.isPresent()) 6613 { 6614 inputFile = inputFileArgument.getValue(); 6615 } 6616 6617 File outputFile = null; 6618 final FileArgument outputFileArgument = 6619 subCommandParser.getFileArgument("output-file"); 6620 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 6621 { 6622 outputFile = outputFileArgument.getValue(); 6623 } 6624 6625 boolean outputPEM = true; 6626 final StringArgument outputFormatArgument = 6627 subCommandParser.getStringArgument("output-format"); 6628 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 6629 { 6630 final String format = outputFormatArgument.getValue().toLowerCase(); 6631 if (format.equals("der") || format.equals("binary") || 6632 format.equals("bin")) 6633 { 6634 outputPEM = false; 6635 } 6636 } 6637 6638 if ((! outputPEM) && (outputFile == null)) 6639 { 6640 wrapErr(0, WRAP_COLUMN, 6641 ERR_MANAGE_CERTS_GEN_CERT_NO_FILE_WITH_DER.get()); 6642 return ResultCode.PARAM_ERROR; 6643 } 6644 6645 final BooleanArgument useExistingKeyPairArgument = 6646 subCommandParser.getBooleanArgument("use-existing-key-pair"); 6647 final boolean useExistingKeyPair = 6648 ((useExistingKeyPairArgument != null) && 6649 useExistingKeyPairArgument.isPresent()); 6650 if (useExistingKeyPair && (! keystorePath.exists())) 6651 { 6652 wrapErr(0, WRAP_COLUMN, 6653 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_WITHOUT_KS.get()); 6654 return ResultCode.PARAM_ERROR; 6655 } 6656 6657 final BooleanArgument inheritExtensionsArgument = 6658 subCommandParser.getBooleanArgument("inherit-extensions"); 6659 final boolean inheritExtensions = 6660 ((inheritExtensionsArgument != null) && 6661 inheritExtensionsArgument.isPresent()); 6662 6663 final BooleanArgument includeRequestedExtensionsArgument = 6664 subCommandParser.getBooleanArgument("include-requested-extensions"); 6665 final boolean includeRequestedExtensions = 6666 ((includeRequestedExtensionsArgument != null) && 6667 includeRequestedExtensionsArgument.isPresent()); 6668 6669 final BooleanArgument noPromptArgument = 6670 subCommandParser.getBooleanArgument("no-prompt"); 6671 final boolean noPrompt = 6672 ((noPromptArgument != null) && noPromptArgument.isPresent()); 6673 6674 final BooleanArgument displayKeytoolCommandArgument = 6675 subCommandParser.getBooleanArgument("display-keytool-command"); 6676 final boolean displayKeytoolCommand = 6677 ((displayKeytoolCommandArgument != null) && 6678 displayKeytoolCommandArgument.isPresent()); 6679 6680 int daysValid = 365; 6681 final IntegerArgument daysValidArgument = 6682 subCommandParser.getIntegerArgument("days-valid"); 6683 if ((daysValidArgument != null) && daysValidArgument.isPresent()) 6684 { 6685 daysValid = daysValidArgument.getValue(); 6686 } 6687 6688 Date validityStartTime = null; 6689 final TimestampArgument validityStartTimeArgument = 6690 subCommandParser.getTimestampArgument("validity-start-time"); 6691 if ((validityStartTimeArgument != null) && 6692 validityStartTimeArgument.isPresent()) 6693 { 6694 validityStartTime = validityStartTimeArgument.getValue(); 6695 } 6696 6697 PublicKeyAlgorithmIdentifier keyAlgorithmIdentifier = null; 6698 String keyAlgorithmName = null; 6699 final StringArgument keyAlgorithmArgument = 6700 subCommandParser.getStringArgument("key-algorithm"); 6701 if ((keyAlgorithmArgument != null) && keyAlgorithmArgument.isPresent()) 6702 { 6703 final String name = keyAlgorithmArgument.getValue(); 6704 keyAlgorithmIdentifier = PublicKeyAlgorithmIdentifier.forName(name); 6705 if (keyAlgorithmIdentifier == null) 6706 { 6707 wrapErr(0, WRAP_COLUMN, 6708 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_KEY_ALG.get(name)); 6709 return ResultCode.PARAM_ERROR; 6710 } 6711 else 6712 { 6713 keyAlgorithmName = keyAlgorithmIdentifier.getName(); 6714 } 6715 } 6716 6717 Integer keySizeBits = null; 6718 final IntegerArgument keySizeBitsArgument = 6719 subCommandParser.getIntegerArgument("key-size-bits"); 6720 if ((keySizeBitsArgument != null) && keySizeBitsArgument.isPresent()) 6721 { 6722 keySizeBits = keySizeBitsArgument.getValue(); 6723 } 6724 6725 if ((keyAlgorithmIdentifier != null) && 6726 (keyAlgorithmIdentifier != PublicKeyAlgorithmIdentifier.RSA) && 6727 (keySizeBits == null)) 6728 { 6729 wrapErr(0, WRAP_COLUMN, 6730 ERR_MANAGE_CERTS_GEN_CERT_NO_KEY_SIZE_FOR_NON_RSA_KEY.get()); 6731 return ResultCode.PARAM_ERROR; 6732 } 6733 6734 String signatureAlgorithmName = null; 6735 SignatureAlgorithmIdentifier signatureAlgorithmIdentifier = null; 6736 final StringArgument signatureAlgorithmArgument = 6737 subCommandParser.getStringArgument("signature-algorithm"); 6738 if ((signatureAlgorithmArgument != null) && 6739 signatureAlgorithmArgument.isPresent()) 6740 { 6741 final String name = signatureAlgorithmArgument.getValue(); 6742 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forName(name); 6743 if (signatureAlgorithmIdentifier == null) 6744 { 6745 wrapErr(0, WRAP_COLUMN, 6746 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG.get(name)); 6747 return ResultCode.PARAM_ERROR; 6748 } 6749 else 6750 { 6751 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 6752 } 6753 } 6754 6755 if ((keyAlgorithmIdentifier != null) && 6756 (keyAlgorithmIdentifier != PublicKeyAlgorithmIdentifier.RSA) && 6757 (signatureAlgorithmIdentifier == null)) 6758 { 6759 wrapErr(0, WRAP_COLUMN, 6760 ERR_MANAGE_CERTS_GEN_CERT_NO_SIG_ALG_FOR_NON_RSA_KEY.get()); 6761 return ResultCode.PARAM_ERROR; 6762 } 6763 6764 6765 // Build a subject alternative name extension, if appropriate. 6766 final ArrayList<X509CertificateExtension> extensionList = 6767 new ArrayList<>(10); 6768 final GeneralNamesBuilder sanBuilder = new GeneralNamesBuilder(); 6769 final LinkedHashSet<String> sanValues = 6770 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 6771 final StringArgument sanDNSArgument = 6772 subCommandParser.getStringArgument("subject-alternative-name-dns"); 6773 if ((sanDNSArgument != null) && sanDNSArgument.isPresent()) 6774 { 6775 for (final String value : sanDNSArgument.getValues()) 6776 { 6777 sanBuilder.addDNSName(value); 6778 sanValues.add("DNS:" + value); 6779 } 6780 } 6781 6782 final StringArgument sanIPArgument = subCommandParser.getStringArgument( 6783 "subject-alternative-name-ip-address"); 6784 if ((sanIPArgument != null) && sanIPArgument.isPresent()) 6785 { 6786 for (final String value : sanIPArgument.getValues()) 6787 { 6788 try 6789 { 6790 sanBuilder.addIPAddress(LDAPConnectionOptions.DEFAULT_NAME_RESOLVER. 6791 getByName(value)); 6792 sanValues.add("IP:" + value); 6793 } 6794 catch (final Exception e) 6795 { 6796 // This should never happen. 6797 Debug.debugException(e); 6798 throw new RuntimeException(e); 6799 } 6800 } 6801 } 6802 6803 final StringArgument sanEmailArgument = subCommandParser.getStringArgument( 6804 "subject-alternative-name-email-address"); 6805 if ((sanEmailArgument != null) && sanEmailArgument.isPresent()) 6806 { 6807 for (final String value : sanEmailArgument.getValues()) 6808 { 6809 sanBuilder.addRFC822Name(value); 6810 sanValues.add("EMAIL:" + value); 6811 } 6812 } 6813 6814 final StringArgument sanURIArgument = 6815 subCommandParser.getStringArgument("subject-alternative-name-uri"); 6816 if ((sanURIArgument != null) && sanURIArgument.isPresent()) 6817 { 6818 for (final String value : sanURIArgument.getValues()) 6819 { 6820 sanBuilder.addUniformResourceIdentifier(value); 6821 sanValues.add("URI:" + value); 6822 } 6823 } 6824 6825 final StringArgument sanOIDArgument = 6826 subCommandParser.getStringArgument("subject-alternative-name-oid"); 6827 if ((sanOIDArgument != null) && sanOIDArgument.isPresent()) 6828 { 6829 for (final String value : sanOIDArgument.getValues()) 6830 { 6831 sanBuilder.addRegisteredID(new OID(value)); 6832 sanValues.add("OID:" + value); 6833 } 6834 } 6835 6836 if (! sanValues.isEmpty()) 6837 { 6838 try 6839 { 6840 extensionList.add( 6841 new SubjectAlternativeNameExtension(false, sanBuilder.build())); 6842 } 6843 catch (final Exception e) 6844 { 6845 // This should never happen. 6846 Debug.debugException(e); 6847 throw new RuntimeException(e); 6848 } 6849 } 6850 6851 // Build a set of issuer alternative name extension values. 6852 final GeneralNamesBuilder ianBuilder = new GeneralNamesBuilder(); 6853 final LinkedHashSet<String> ianValues = 6854 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 6855 final StringArgument ianDNSArgument = 6856 subCommandParser.getStringArgument("issuer-alternative-name-dns"); 6857 if ((ianDNSArgument != null) && ianDNSArgument.isPresent()) 6858 { 6859 for (final String value : ianDNSArgument.getValues()) 6860 { 6861 ianBuilder.addDNSName(value); 6862 ianValues.add("DNS:" + value); 6863 } 6864 } 6865 6866 final StringArgument ianIPArgument = subCommandParser.getStringArgument( 6867 "issuer-alternative-name-ip-address"); 6868 if ((ianIPArgument != null) && ianIPArgument.isPresent()) 6869 { 6870 for (final String value : ianIPArgument.getValues()) 6871 { 6872 try 6873 { 6874 ianBuilder.addIPAddress(LDAPConnectionOptions.DEFAULT_NAME_RESOLVER. 6875 getByName(value)); 6876 ianValues.add("IP:" + value); 6877 } 6878 catch (final Exception e) 6879 { 6880 // This should never happen. 6881 Debug.debugException(e); 6882 throw new RuntimeException(e); 6883 } 6884 } 6885 } 6886 6887 final StringArgument ianEmailArgument = subCommandParser.getStringArgument( 6888 "issuer-alternative-name-email-address"); 6889 if ((ianEmailArgument != null) && ianEmailArgument.isPresent()) 6890 { 6891 for (final String value : ianEmailArgument.getValues()) 6892 { 6893 ianBuilder.addRFC822Name(value); 6894 ianValues.add("EMAIL:" + value); 6895 } 6896 } 6897 6898 final StringArgument ianURIArgument = 6899 subCommandParser.getStringArgument("issuer-alternative-name-uri"); 6900 if ((ianURIArgument != null) && ianURIArgument.isPresent()) 6901 { 6902 for (final String value : ianURIArgument.getValues()) 6903 { 6904 ianBuilder.addUniformResourceIdentifier(value); 6905 ianValues.add("URI:" + value); 6906 } 6907 } 6908 6909 final StringArgument ianOIDArgument = 6910 subCommandParser.getStringArgument("issuer-alternative-name-oid"); 6911 if ((ianOIDArgument != null) && ianOIDArgument.isPresent()) 6912 { 6913 for (final String value : ianOIDArgument.getValues()) 6914 { 6915 ianBuilder.addRegisteredID(new OID(value)); 6916 ianValues.add("OID:" + value); 6917 } 6918 } 6919 6920 if (! ianValues.isEmpty()) 6921 { 6922 try 6923 { 6924 extensionList.add( 6925 new IssuerAlternativeNameExtension(false, ianBuilder.build())); 6926 } 6927 catch (final Exception e) 6928 { 6929 // This should never happen. 6930 Debug.debugException(e); 6931 throw new RuntimeException(e); 6932 } 6933 } 6934 6935 6936 // Build a basic constraints extension, if appropriate. 6937 BasicConstraintsExtension basicConstraints = null; 6938 final BooleanValueArgument basicConstraintsIsCAArgument = 6939 subCommandParser.getBooleanValueArgument("basic-constraints-is-ca"); 6940 if ((basicConstraintsIsCAArgument != null) && 6941 basicConstraintsIsCAArgument.isPresent()) 6942 { 6943 final boolean isCA = basicConstraintsIsCAArgument.getValue(); 6944 6945 Integer pathLength = null; 6946 final IntegerArgument pathLengthArgument = 6947 subCommandParser.getIntegerArgument( 6948 "basic-constraints-maximum-path-length"); 6949 if ((pathLengthArgument != null) && pathLengthArgument.isPresent()) 6950 { 6951 if (isCA) 6952 { 6953 pathLength = pathLengthArgument.getValue(); 6954 } 6955 else 6956 { 6957 wrapErr(0, WRAP_COLUMN, 6958 ERR_MANAGE_CERTS_GEN_CERT_BC_PATH_LENGTH_WITHOUT_CA.get()); 6959 return ResultCode.PARAM_ERROR; 6960 } 6961 } 6962 6963 basicConstraints = new BasicConstraintsExtension(false, isCA, pathLength); 6964 extensionList.add(basicConstraints); 6965 } 6966 6967 6968 // Build a key usage extension, if appropriate. 6969 KeyUsageExtension keyUsage = null; 6970 final StringArgument keyUsageArgument = 6971 subCommandParser.getStringArgument("key-usage"); 6972 if ((keyUsageArgument != null) && keyUsageArgument.isPresent()) 6973 { 6974 boolean digitalSignature = false; 6975 boolean nonRepudiation = false; 6976 boolean keyEncipherment = false; 6977 boolean dataEncipherment = false; 6978 boolean keyAgreement = false; 6979 boolean keyCertSign = false; 6980 boolean crlSign = false; 6981 boolean encipherOnly = false; 6982 boolean decipherOnly = false; 6983 6984 for (final String value : keyUsageArgument.getValues()) 6985 { 6986 if (value.equalsIgnoreCase("digital-signature") || 6987 value.equalsIgnoreCase("digitalSignature")) 6988 { 6989 digitalSignature = true; 6990 } 6991 else if (value.equalsIgnoreCase("non-repudiation") || 6992 value.equalsIgnoreCase("nonRepudiation") || 6993 value.equalsIgnoreCase("content-commitment") || 6994 value.equalsIgnoreCase("contentCommitment")) 6995 { 6996 nonRepudiation = true; 6997 } 6998 else if (value.equalsIgnoreCase("key-encipherment") || 6999 value.equalsIgnoreCase("keyEncipherment")) 7000 { 7001 keyEncipherment = true; 7002 } 7003 else if (value.equalsIgnoreCase("data-encipherment") || 7004 value.equalsIgnoreCase("dataEncipherment")) 7005 { 7006 dataEncipherment = true; 7007 } 7008 else if (value.equalsIgnoreCase("key-agreement") || 7009 value.equalsIgnoreCase("keyAgreement")) 7010 { 7011 keyAgreement = true; 7012 } 7013 else if (value.equalsIgnoreCase("key-cert-sign") || 7014 value.equalsIgnoreCase("keyCertSign")) 7015 { 7016 keyCertSign = true; 7017 } 7018 else if (value.equalsIgnoreCase("crl-sign") || 7019 value.equalsIgnoreCase("crlSign")) 7020 { 7021 crlSign = true; 7022 } 7023 else if (value.equalsIgnoreCase("encipher-only") || 7024 value.equalsIgnoreCase("encipherOnly")) 7025 { 7026 encipherOnly = true; 7027 } 7028 else if (value.equalsIgnoreCase("decipher-only") || 7029 value.equalsIgnoreCase("decipherOnly")) 7030 { 7031 decipherOnly = true; 7032 } 7033 else 7034 { 7035 wrapErr(0, WRAP_COLUMN, 7036 ERR_MANAGE_CERTS_GEN_CERT_INVALID_KEY_USAGE.get(value)); 7037 return ResultCode.PARAM_ERROR; 7038 } 7039 } 7040 7041 keyUsage = new KeyUsageExtension(false, digitalSignature, nonRepudiation, 7042 keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, 7043 crlSign, encipherOnly, decipherOnly); 7044 extensionList.add(keyUsage); 7045 } 7046 7047 7048 // Build an extended key usage extension, if appropriate. 7049 ExtendedKeyUsageExtension extendedKeyUsage = null; 7050 final StringArgument extendedKeyUsageArgument = 7051 subCommandParser.getStringArgument("extended-key-usage"); 7052 if ((extendedKeyUsageArgument != null) && 7053 extendedKeyUsageArgument.isPresent()) 7054 { 7055 final List<String> values = extendedKeyUsageArgument.getValues(); 7056 final ArrayList<OID> keyPurposeIDs = new ArrayList<>(values.size()); 7057 for (final String value : values) 7058 { 7059 if (value.equalsIgnoreCase("server-auth") || 7060 value.equalsIgnoreCase("serverAuth") || 7061 value.equalsIgnoreCase("server-authentication") || 7062 value.equalsIgnoreCase("serverAuthentication") || 7063 value.equalsIgnoreCase("tls-server-authentication") || 7064 value.equalsIgnoreCase("tlsServerAuthentication")) 7065 { 7066 keyPurposeIDs.add( 7067 ExtendedKeyUsageID.TLS_SERVER_AUTHENTICATION.getOID()); 7068 } 7069 else if (value.equalsIgnoreCase("client-auth") || 7070 value.equalsIgnoreCase("clientAuth") || 7071 value.equalsIgnoreCase("client-authentication") || 7072 value.equalsIgnoreCase("clientAuthentication") || 7073 value.equalsIgnoreCase("tls-client-authentication") || 7074 value.equalsIgnoreCase("tlsClientAuthentication")) 7075 { 7076 keyPurposeIDs.add( 7077 ExtendedKeyUsageID.TLS_CLIENT_AUTHENTICATION.getOID()); 7078 } 7079 else if (value.equalsIgnoreCase("code-signing") || 7080 value.equalsIgnoreCase("codeSigning")) 7081 { 7082 keyPurposeIDs.add(ExtendedKeyUsageID.CODE_SIGNING.getOID()); 7083 } 7084 else if (value.equalsIgnoreCase("email-protection") || 7085 value.equalsIgnoreCase("emailProtection")) 7086 { 7087 keyPurposeIDs.add(ExtendedKeyUsageID.EMAIL_PROTECTION.getOID()); 7088 } 7089 else if (value.equalsIgnoreCase("time-stamping") || 7090 value.equalsIgnoreCase("timeStamping")) 7091 { 7092 keyPurposeIDs.add(ExtendedKeyUsageID.TIME_STAMPING.getOID()); 7093 } 7094 else if (value.equalsIgnoreCase("ocsp-signing") || 7095 value.equalsIgnoreCase("ocspSigning")) 7096 { 7097 keyPurposeIDs.add(ExtendedKeyUsageID.OCSP_SIGNING.getOID()); 7098 } 7099 else if (OID.isStrictlyValidNumericOID(value)) 7100 { 7101 keyPurposeIDs.add(new OID(value)); 7102 } 7103 else 7104 { 7105 wrapErr(0, WRAP_COLUMN, 7106 ERR_MANAGE_CERTS_GEN_CERT_INVALID_EXTENDED_KEY_USAGE.get(value)); 7107 return ResultCode.PARAM_ERROR; 7108 } 7109 } 7110 7111 try 7112 { 7113 extendedKeyUsage = new ExtendedKeyUsageExtension(false, keyPurposeIDs); 7114 } 7115 catch (final Exception e) 7116 { 7117 // This should never happen. 7118 Debug.debugException(e); 7119 wrapErr(0, WRAP_COLUMN, 7120 ERR_MANAGE_CERTS_GEN_CERT_EXTENDED_KEY_USAGE_ERROR.get()); 7121 e.printStackTrace(getErr()); 7122 return ResultCode.PARAM_ERROR; 7123 } 7124 7125 extensionList.add(extendedKeyUsage); 7126 } 7127 7128 7129 // Build a list of generic extensions. 7130 final ArrayList<X509CertificateExtension> genericExtensions = 7131 new ArrayList<>(5); 7132 final StringArgument extensionArgument = 7133 subCommandParser.getStringArgument("extension"); 7134 if ((extensionArgument != null) && extensionArgument.isPresent()) 7135 { 7136 for (final String value : extensionArgument.getValues()) 7137 { 7138 try 7139 { 7140 final int firstColonPos = value.indexOf(':'); 7141 final int secondColonPos = value.indexOf(':', firstColonPos + 1); 7142 final OID oid = new OID(value.substring(0, firstColonPos)); 7143 if (! oid.isStrictlyValidNumericOID()) 7144 { 7145 wrapErr(0, WRAP_COLUMN, 7146 ERR_MANAGE_CERTS_GEN_CERT_EXT_MALFORMED_OID.get(value, 7147 oid.toString())); 7148 return ResultCode.PARAM_ERROR; 7149 } 7150 7151 final boolean criticality; 7152 final String criticalityString = 7153 value.substring(firstColonPos + 1, secondColonPos); 7154 if (criticalityString.equalsIgnoreCase("true") || 7155 criticalityString.equalsIgnoreCase("t") || 7156 criticalityString.equalsIgnoreCase("yes") || 7157 criticalityString.equalsIgnoreCase("y") || 7158 criticalityString.equalsIgnoreCase("on") || 7159 criticalityString.equalsIgnoreCase("1")) 7160 { 7161 criticality = true; 7162 } 7163 else if (criticalityString.equalsIgnoreCase("false") || 7164 criticalityString.equalsIgnoreCase("f") || 7165 criticalityString.equalsIgnoreCase("no") || 7166 criticalityString.equalsIgnoreCase("n") || 7167 criticalityString.equalsIgnoreCase("off") || 7168 criticalityString.equalsIgnoreCase("0")) 7169 { 7170 criticality = false; 7171 } 7172 else 7173 { 7174 wrapErr(0, WRAP_COLUMN, 7175 ERR_MANAGE_CERTS_GEN_CERT_EXT_INVALID_CRITICALITY.get( 7176 value, criticalityString)); 7177 return ResultCode.PARAM_ERROR; 7178 } 7179 7180 final byte[] valueBytes; 7181 try 7182 { 7183 valueBytes = StaticUtils.fromHex(value.substring(secondColonPos+1)); 7184 } 7185 catch (final Exception e) 7186 { 7187 Debug.debugException(e); 7188 wrapErr(0, WRAP_COLUMN, 7189 ERR_MANAGE_CERTS_GEN_CERT_EXT_INVALID_VALUE.get(value)); 7190 return ResultCode.PARAM_ERROR; 7191 } 7192 7193 final X509CertificateExtension extension = 7194 new X509CertificateExtension(oid, criticality, valueBytes); 7195 genericExtensions.add(extension); 7196 extensionList.add(extension); 7197 } 7198 catch (final Exception e) 7199 { 7200 Debug.debugException(e); 7201 wrapErr(0, WRAP_COLUMN, 7202 ERR_MANAGE_CERTS_GEN_CERT_EXT_MALFORMED.get(value)); 7203 return ResultCode.PARAM_ERROR; 7204 } 7205 } 7206 } 7207 7208 7209 final String keystoreType; 7210 try 7211 { 7212 keystoreType = inferKeystoreType(keystorePath); 7213 } 7214 catch (final LDAPException le) 7215 { 7216 Debug.debugException(le); 7217 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7218 return le.getResultCode(); 7219 } 7220 7221 final char[] keystorePassword; 7222 try 7223 { 7224 keystorePassword = getKeystorePassword(keystorePath); 7225 } 7226 catch (final LDAPException le) 7227 { 7228 Debug.debugException(le); 7229 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7230 return le.getResultCode(); 7231 } 7232 7233 7234 // Get the keystore. 7235 final KeyStore keystore; 7236 try 7237 { 7238 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 7239 } 7240 catch (final LDAPException le) 7241 { 7242 Debug.debugException(le); 7243 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7244 return le.getResultCode(); 7245 } 7246 7247 7248 // If there is a private key, then see if we need to use a private key 7249 // password that is different from the keystore password. 7250 final char[] privateKeyPassword; 7251 try 7252 { 7253 privateKeyPassword = 7254 getPrivateKeyPassword(keystore, alias, keystorePassword); 7255 } 7256 catch (final LDAPException le) 7257 { 7258 Debug.debugException(le); 7259 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7260 return le.getResultCode(); 7261 } 7262 7263 7264 // If we're going to replace an existing certificate in the keystore, then 7265 // perform the appropriate processing for that. 7266 if (useExistingKeyPair) 7267 { 7268 // Make sure that the keystore already has a private key entry with the 7269 // specified alias. 7270 if (! hasKeyAlias(keystore, alias)) 7271 { 7272 if (hasCertificateAlias(keystore, alias)) 7273 { 7274 wrapErr(0, WRAP_COLUMN, 7275 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_ALIAS_IS_CERT.get( 7276 alias, keystorePath.getAbsolutePath())); 7277 return ResultCode.PARAM_ERROR; 7278 } 7279 else 7280 { 7281 wrapErr(0, WRAP_COLUMN, 7282 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_NO_SUCH_ALIAS.get( 7283 alias, keystorePath.getAbsolutePath())); 7284 return ResultCode.PARAM_ERROR; 7285 } 7286 } 7287 7288 7289 // Get the certificate to replace, along with its key pair. 7290 final X509Certificate certToReplace; 7291 final KeyPair keyPair; 7292 try 7293 { 7294 final Certificate[] chain = keystore.getCertificateChain(alias); 7295 certToReplace = new X509Certificate(chain[0].getEncoded()); 7296 7297 final PublicKey publicKey = chain[0].getPublicKey(); 7298 final PrivateKey privateKey = 7299 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 7300 keyPair = new KeyPair(publicKey, privateKey); 7301 } 7302 catch (final Exception e) 7303 { 7304 Debug.debugException(e); 7305 wrapErr(0, WRAP_COLUMN, 7306 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_COULD_NOT_GET_CERT.get( 7307 alias)); 7308 e.printStackTrace(getErr()); 7309 return ResultCode.LOCAL_ERROR; 7310 } 7311 7312 7313 // Assign the remaining values using information in the existing 7314 // certificate. 7315 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forOID( 7316 certToReplace.getSignatureAlgorithmOID()); 7317 if (signatureAlgorithmIdentifier == null) 7318 { 7319 wrapErr(0, WRAP_COLUMN, 7320 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG_IN_CERT.get( 7321 certToReplace.getSignatureAlgorithmOID())); 7322 return ResultCode.PARAM_ERROR; 7323 } 7324 else 7325 { 7326 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 7327 } 7328 7329 if (subjectDN == null) 7330 { 7331 subjectDN = certToReplace.getSubjectDN(); 7332 } 7333 7334 if (inheritExtensions) 7335 { 7336 for (final X509CertificateExtension extension : 7337 certToReplace.getExtensions()) 7338 { 7339 if ((extension instanceof AuthorityKeyIdentifierExtension) || 7340 (extension instanceof IssuerAlternativeNameExtension)) 7341 { 7342 // This extension applies to the issuer. We won't include this in 7343 // the set of inherited extensions. 7344 } 7345 else if (extension instanceof SubjectKeyIdentifierExtension) 7346 { 7347 // The generated certificate will automatically include a subject 7348 // key identifier extension, so we don't need to include it. 7349 } 7350 else if (extension instanceof BasicConstraintsExtension) 7351 { 7352 // Don't override a value already provided on the command line. 7353 if (basicConstraints == null) 7354 { 7355 basicConstraints = (BasicConstraintsExtension) extension; 7356 extensionList.add(basicConstraints); 7357 } 7358 } 7359 else if (extension instanceof ExtendedKeyUsageExtension) 7360 { 7361 // Don't override a value already provided on the command line. 7362 if (extendedKeyUsage == null) 7363 { 7364 extendedKeyUsage = (ExtendedKeyUsageExtension) extension; 7365 extensionList.add(extendedKeyUsage); 7366 } 7367 } 7368 else if (extension instanceof KeyUsageExtension) 7369 { 7370 // Don't override a value already provided on the command line. 7371 if (keyUsage == null) 7372 { 7373 keyUsage = (KeyUsageExtension) extension; 7374 extensionList.add(keyUsage); 7375 } 7376 } 7377 else if (extension instanceof SubjectAlternativeNameExtension) 7378 { 7379 // Although we could merge values, it's safer to not do that if any 7380 // subject alternative name values were provided on the command 7381 // line. 7382 if (sanValues.isEmpty()) 7383 { 7384 final SubjectAlternativeNameExtension e = 7385 (SubjectAlternativeNameExtension) extension; 7386 for (final String dnsName : e.getDNSNames()) 7387 { 7388 sanValues.add("DNS:" + dnsName); 7389 } 7390 7391 for (final InetAddress ipAddress : e.getIPAddresses()) 7392 { 7393 sanValues.add("IP:" + ipAddress.getHostAddress()); 7394 } 7395 7396 for (final String emailAddress : e.getRFC822Names()) 7397 { 7398 sanValues.add("EMAIL:" + emailAddress); 7399 } 7400 7401 for (final String uri : e.getUniformResourceIdentifiers()) 7402 { 7403 sanValues.add("URI:" + uri); 7404 } 7405 7406 for (final OID oid : e.getRegisteredIDs()) 7407 { 7408 sanValues.add("OID:" + oid.toString()); 7409 } 7410 7411 extensionList.add(extension); 7412 } 7413 } 7414 else 7415 { 7416 genericExtensions.add(extension); 7417 extensionList.add(extension); 7418 } 7419 } 7420 } 7421 7422 7423 // Create an array with the final set of extensions to include in the 7424 // certificate or certificate signing request. 7425 final X509CertificateExtension[] extensions = 7426 new X509CertificateExtension[extensionList.size()]; 7427 extensionList.toArray(extensions); 7428 7429 7430 // If we're generating a self-signed certificate or a certificate signing 7431 // request, then we should now have everything we need to do that. Build 7432 // a keytool command that we could use to accomplish it. 7433 if (isGenerateCertificate) 7434 { 7435 if (displayKeytoolCommand) 7436 { 7437 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7438 keytoolArguments.add("-selfcert"); 7439 keytoolArguments.add("-keystore"); 7440 keytoolArguments.add(keystorePath.getAbsolutePath()); 7441 keytoolArguments.add("-storetype"); 7442 keytoolArguments.add(keystoreType); 7443 keytoolArguments.add("-storepass"); 7444 keytoolArguments.add("*****REDACTED*****"); 7445 keytoolArguments.add("-keypass"); 7446 keytoolArguments.add("*****REDACTED*****"); 7447 keytoolArguments.add("-alias"); 7448 keytoolArguments.add(alias); 7449 keytoolArguments.add("-dname"); 7450 keytoolArguments.add(subjectDN.toString()); 7451 keytoolArguments.add("-sigalg"); 7452 keytoolArguments.add(signatureAlgorithmName); 7453 keytoolArguments.add("-validity"); 7454 keytoolArguments.add(String.valueOf(daysValid)); 7455 7456 if (validityStartTime != null) 7457 { 7458 keytoolArguments.add("-startdate"); 7459 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 7460 } 7461 7462 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7463 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7464 7465 displayKeytoolCommand(keytoolArguments); 7466 } 7467 7468 7469 // Generate the self-signed certificate. 7470 final long notBefore; 7471 if (validityStartTime == null) 7472 { 7473 notBefore = System.currentTimeMillis(); 7474 } 7475 else 7476 { 7477 notBefore = validityStartTime.getTime(); 7478 } 7479 7480 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 7481 7482 final X509Certificate certificate; 7483 final Certificate[] chain; 7484 try 7485 { 7486 certificate = X509Certificate.generateSelfSignedCertificate( 7487 signatureAlgorithmIdentifier, keyPair, subjectDN, notBefore, 7488 notAfter, extensions); 7489 chain = new Certificate[] { certificate.toCertificate() }; 7490 } 7491 catch (final Exception e) 7492 { 7493 Debug.debugException(e); 7494 wrapErr(0, WRAP_COLUMN, 7495 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CERT.get()); 7496 e.printStackTrace(getErr()); 7497 return ResultCode.LOCAL_ERROR; 7498 } 7499 7500 7501 // Update the keystore with the new certificate. 7502 try 7503 { 7504 keystore.setKeyEntry(alias, keyPair.getPrivate(), privateKeyPassword, 7505 chain); 7506 writeKeystore(keystore, keystorePath, keystorePassword); 7507 } 7508 catch (final Exception e) 7509 { 7510 Debug.debugException(e); 7511 wrapErr(0, WRAP_COLUMN, 7512 ERR_MANAGE_CERTS_GEN_CERT_ERROR_UPDATING_KEYSTORE.get()); 7513 e.printStackTrace(getErr()); 7514 return ResultCode.LOCAL_ERROR; 7515 } 7516 7517 7518 // Display the certificate we just generated to the end user. 7519 out(); 7520 wrapOut(0, WRAP_COLUMN, 7521 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_SELF_CERT. 7522 get()); 7523 printCertificate(certificate, "", false); 7524 7525 7526 // If we should write an output file, then do that now. 7527 if (outputFile != null) 7528 { 7529 try (PrintStream ps = new PrintStream(outputFile)) 7530 { 7531 final byte[] certBytes = certificate.getX509CertificateBytes(); 7532 if (outputPEM) 7533 { 7534 writePEMCertificate(ps, certBytes); 7535 } 7536 else 7537 { 7538 ps.write(certBytes); 7539 } 7540 7541 out(); 7542 wrapOut(0, WRAP_COLUMN, 7543 INFO_MANAGE_CERTS_GEN_CERT_WROTE_OUTPUT_FILE.get( 7544 outputFile.getAbsolutePath())); 7545 } 7546 catch (final Exception e) 7547 { 7548 Debug.debugException(e); 7549 err(); 7550 wrapErr(0, WRAP_COLUMN, 7551 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CERT.get( 7552 outputFile.getAbsolutePath())); 7553 e.printStackTrace(getErr()); 7554 return ResultCode.LOCAL_ERROR; 7555 } 7556 } 7557 7558 return ResultCode.SUCCESS; 7559 } 7560 else 7561 { 7562 // Build the keytool command used to generate the certificate signing 7563 // request. 7564 Validator.ensureTrue(isGenerateCSR); 7565 if (displayKeytoolCommand) 7566 { 7567 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7568 keytoolArguments.add("-certreq"); 7569 keytoolArguments.add("-keystore"); 7570 keytoolArguments.add(keystorePath.getAbsolutePath()); 7571 keytoolArguments.add("-storetype"); 7572 keytoolArguments.add(keystoreType); 7573 keytoolArguments.add("-storepass"); 7574 keytoolArguments.add("*****REDACTED*****"); 7575 keytoolArguments.add("-keypass"); 7576 keytoolArguments.add("*****REDACTED*****"); 7577 keytoolArguments.add("-alias"); 7578 keytoolArguments.add(alias); 7579 keytoolArguments.add("-dname"); 7580 keytoolArguments.add(subjectDN.toString()); 7581 keytoolArguments.add("-sigalg"); 7582 keytoolArguments.add(signatureAlgorithmName); 7583 7584 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7585 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7586 7587 if (outputFile != null) 7588 { 7589 keytoolArguments.add("-file"); 7590 keytoolArguments.add(outputFile.getAbsolutePath()); 7591 } 7592 7593 displayKeytoolCommand(keytoolArguments); 7594 } 7595 7596 7597 // Generate the certificate signing request. 7598 final PKCS10CertificateSigningRequest certificateSigningRequest; 7599 try 7600 { 7601 certificateSigningRequest = PKCS10CertificateSigningRequest. 7602 generateCertificateSigningRequest(signatureAlgorithmIdentifier, 7603 keyPair, subjectDN, extensions); 7604 } 7605 catch (final Exception e) 7606 { 7607 Debug.debugException(e); 7608 wrapErr(0, WRAP_COLUMN, 7609 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CSR.get()); 7610 e.printStackTrace(getErr()); 7611 return ResultCode.LOCAL_ERROR; 7612 } 7613 7614 7615 // Write the generated certificate signing request to the appropriate 7616 // location. 7617 try 7618 { 7619 final PrintStream ps; 7620 if (outputFile == null) 7621 { 7622 ps = getOut(); 7623 } 7624 else 7625 { 7626 ps = new PrintStream(outputFile); 7627 } 7628 7629 if (outputPEM) 7630 { 7631 writePEMCertificateSigningRequest(ps, 7632 certificateSigningRequest. 7633 getPKCS10CertificateSigningRequestBytes()); 7634 } 7635 else 7636 { 7637 ps.write(certificateSigningRequest. 7638 getPKCS10CertificateSigningRequestBytes()); 7639 } 7640 7641 if (outputFile != null) 7642 { 7643 ps.close(); 7644 } 7645 } 7646 catch (final Exception e) 7647 { 7648 Debug.debugException(e); 7649 wrapErr(0, WRAP_COLUMN, 7650 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CSR.get()); 7651 e.printStackTrace(getErr()); 7652 return ResultCode.LOCAL_ERROR; 7653 } 7654 7655 7656 // If the certificate signing request was written to an output file, 7657 // then let the user know that it was successful. If it was written to 7658 // standard output, then we don't need to tell them because they'll be 7659 // able to see it. 7660 if (outputFile != null) 7661 { 7662 out(); 7663 wrapOut(0, WRAP_COLUMN, 7664 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_CSR.get( 7665 outputFile.getAbsolutePath())); 7666 } 7667 7668 return ResultCode.SUCCESS; 7669 } 7670 } 7671 7672 7673 // If we've gotten here, then we know we're not replacing an existing 7674 // certificate. Perform any remaining argument assignment and validation. 7675 if ((subjectDN == null) && (! isSignCSR)) 7676 { 7677 wrapErr(0, WRAP_COLUMN, 7678 ERR_MANAGE_CERTS_GEN_CERT_NO_SUBJECT_DN_WITHOUT_USE_EXISTING_KP. 7679 get()); 7680 return ResultCode.PARAM_ERROR; 7681 } 7682 7683 if (keyAlgorithmIdentifier == null) 7684 { 7685 keyAlgorithmIdentifier = PublicKeyAlgorithmIdentifier.RSA; 7686 keyAlgorithmName = keyAlgorithmIdentifier.getName(); 7687 } 7688 7689 if (keySizeBits == null) 7690 { 7691 keySizeBits = 2048; 7692 } 7693 7694 if ((signatureAlgorithmIdentifier == null) && (! isSignCSR)) 7695 { 7696 signatureAlgorithmIdentifier = 7697 SignatureAlgorithmIdentifier.SHA_256_WITH_RSA; 7698 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 7699 } 7700 7701 7702 // If we're going to generate a self-signed certificate or a certificate 7703 // signing request, then we first need to generate a key pair. Put together 7704 // the appropriate set of keytool arguments and then generate a self-signed 7705 // certificate. 7706 if (isGenerateCertificate || isGenerateCSR) 7707 { 7708 // Make sure that the specified alias is not already in use in the 7709 // keystore. 7710 if (hasKeyAlias(keystore, alias) || hasCertificateAlias(keystore, alias)) 7711 { 7712 wrapErr(0, WRAP_COLUMN, 7713 ERR_MANAGE_CERTS_GEN_CERT_ALIAS_EXISTS_WITHOUT_USE_EXISTING_KP.get( 7714 alias)); 7715 return ResultCode.PARAM_ERROR; 7716 } 7717 7718 7719 if (displayKeytoolCommand) 7720 { 7721 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7722 keytoolArguments.add("-genkeypair"); 7723 keytoolArguments.add("-keystore"); 7724 keytoolArguments.add(keystorePath.getAbsolutePath()); 7725 keytoolArguments.add("-storetype"); 7726 keytoolArguments.add(keystoreType); 7727 keytoolArguments.add("-storepass"); 7728 keytoolArguments.add("*****REDACTED*****"); 7729 keytoolArguments.add("-keypass"); 7730 keytoolArguments.add("*****REDACTED*****"); 7731 keytoolArguments.add("-alias"); 7732 keytoolArguments.add(alias); 7733 keytoolArguments.add("-dname"); 7734 keytoolArguments.add(subjectDN.toString()); 7735 keytoolArguments.add("-keyalg"); 7736 keytoolArguments.add(keyAlgorithmName); 7737 keytoolArguments.add("-keysize"); 7738 keytoolArguments.add(String.valueOf(keySizeBits)); 7739 keytoolArguments.add("-sigalg"); 7740 keytoolArguments.add(signatureAlgorithmName); 7741 keytoolArguments.add("-validity"); 7742 keytoolArguments.add(String.valueOf(daysValid)); 7743 7744 if (validityStartTime != null) 7745 { 7746 keytoolArguments.add("-startdate"); 7747 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 7748 } 7749 7750 addExtensionArguments(keytoolArguments, basicConstraints, 7751 keyUsage, extendedKeyUsage, sanValues, ianValues, 7752 genericExtensions); 7753 7754 displayKeytoolCommand(keytoolArguments); 7755 } 7756 7757 7758 // Generate the self-signed certificate. 7759 final long notBefore; 7760 if (validityStartTime == null) 7761 { 7762 notBefore = System.currentTimeMillis(); 7763 } 7764 else 7765 { 7766 notBefore = validityStartTime.getTime(); 7767 } 7768 7769 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 7770 7771 final X509CertificateExtension[] extensions = 7772 new X509CertificateExtension[extensionList.size()]; 7773 extensionList.toArray(extensions); 7774 7775 final Certificate[] chain; 7776 final KeyPair keyPair; 7777 final X509Certificate certificate; 7778 try 7779 { 7780 final ObjectPair<X509Certificate,KeyPair> p = 7781 X509Certificate.generateSelfSignedCertificate( 7782 signatureAlgorithmIdentifier, keyAlgorithmIdentifier, 7783 keySizeBits, subjectDN, notBefore, notAfter, extensions); 7784 certificate = p.getFirst(); 7785 chain = new Certificate[] { certificate.toCertificate() }; 7786 keyPair = p.getSecond(); 7787 } 7788 catch (final Exception e) 7789 { 7790 Debug.debugException(e); 7791 wrapErr(0, WRAP_COLUMN, 7792 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CERT.get()); 7793 e.printStackTrace(getErr()); 7794 return ResultCode.LOCAL_ERROR; 7795 } 7796 7797 7798 // Update the keystore with the new certificate. 7799 try 7800 { 7801 keystore.setKeyEntry(alias, keyPair.getPrivate(), privateKeyPassword, 7802 chain); 7803 writeKeystore(keystore, keystorePath, keystorePassword); 7804 } 7805 catch (final Exception e) 7806 { 7807 Debug.debugException(e); 7808 wrapErr(0, WRAP_COLUMN, 7809 ERR_MANAGE_CERTS_GEN_CERT_ERROR_UPDATING_KEYSTORE.get()); 7810 e.printStackTrace(getErr()); 7811 return ResultCode.LOCAL_ERROR; 7812 } 7813 7814 if (isNewKeystore) 7815 { 7816 out(); 7817 wrapOut(0, WRAP_COLUMN, 7818 INFO_MANAGE_CERTS_GEN_CERT_CERT_CREATED_KEYSTORE.get( 7819 getUserFriendlyKeystoreType(keystoreType))); 7820 } 7821 7822 7823 // If we're just generating a self-signed certificate, then display the 7824 // certificate that we generated and potentially write it to an output 7825 // file. 7826 if (isGenerateCertificate) 7827 { 7828 out(); 7829 wrapOut(0, WRAP_COLUMN, 7830 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_SELF_CERT.get()); 7831 printCertificate(certificate, "", false); 7832 7833 7834 // If we should write an output file, then do that now. 7835 if (outputFile != null) 7836 { 7837 try (PrintStream ps = new PrintStream(outputFile)) 7838 { 7839 final byte[] certBytes = certificate.getX509CertificateBytes(); 7840 if (outputPEM) 7841 { 7842 writePEMCertificate(ps, certBytes); 7843 } 7844 else 7845 { 7846 ps.write(certBytes); 7847 } 7848 7849 out(); 7850 wrapOut(0, WRAP_COLUMN, 7851 INFO_MANAGE_CERTS_GEN_CERT_WROTE_OUTPUT_FILE.get( 7852 outputFile.getAbsolutePath())); 7853 } 7854 catch (final Exception e) 7855 { 7856 Debug.debugException(e); 7857 err(); 7858 wrapErr(0, WRAP_COLUMN, 7859 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CERT.get( 7860 outputFile.getAbsolutePath())); 7861 e.printStackTrace(getErr()); 7862 return ResultCode.LOCAL_ERROR; 7863 } 7864 } 7865 7866 return ResultCode.SUCCESS; 7867 } 7868 7869 7870 // If we're generating a certificate signing request, then put together 7871 // the appropriate set of arguments for that. 7872 Validator.ensureTrue(isGenerateCSR); 7873 out(); 7874 wrapOut(0, WRAP_COLUMN, 7875 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_KEYPAIR.get()); 7876 7877 if (displayKeytoolCommand) 7878 { 7879 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7880 keytoolArguments.add("-certreq"); 7881 keytoolArguments.add("-keystore"); 7882 keytoolArguments.add(keystorePath.getAbsolutePath()); 7883 keytoolArguments.add("-storetype"); 7884 keytoolArguments.add(keystoreType); 7885 keytoolArguments.add("-storepass"); 7886 keytoolArguments.add("*****REDACTED*****"); 7887 keytoolArguments.add("-keypass"); 7888 keytoolArguments.add("*****REDACTED*****"); 7889 keytoolArguments.add("-alias"); 7890 keytoolArguments.add(alias); 7891 keytoolArguments.add("-dname"); 7892 keytoolArguments.add(subjectDN.toString()); 7893 keytoolArguments.add("-sigalg"); 7894 keytoolArguments.add(signatureAlgorithmName); 7895 7896 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7897 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7898 7899 if (outputFile != null) 7900 { 7901 keytoolArguments.add("-file"); 7902 keytoolArguments.add(outputFile.getAbsolutePath()); 7903 } 7904 7905 displayKeytoolCommand(keytoolArguments); 7906 } 7907 7908 7909 // Generate the certificate signing request. 7910 final PKCS10CertificateSigningRequest certificateSigningRequest; 7911 try 7912 { 7913 certificateSigningRequest = PKCS10CertificateSigningRequest. 7914 generateCertificateSigningRequest(signatureAlgorithmIdentifier, 7915 keyPair, subjectDN, extensions); 7916 } 7917 catch (final Exception e) 7918 { 7919 Debug.debugException(e); 7920 wrapErr(0, WRAP_COLUMN, 7921 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CSR.get()); 7922 e.printStackTrace(getErr()); 7923 return ResultCode.LOCAL_ERROR; 7924 } 7925 7926 7927 // Write the generated certificate signing request to the appropriate 7928 // location. 7929 try 7930 { 7931 final PrintStream ps; 7932 if (outputFile == null) 7933 { 7934 ps = getOut(); 7935 } 7936 else 7937 { 7938 ps = new PrintStream(outputFile); 7939 } 7940 7941 if (outputPEM) 7942 { 7943 writePEMCertificateSigningRequest(ps, 7944 certificateSigningRequest. 7945 getPKCS10CertificateSigningRequestBytes()); 7946 } 7947 else 7948 { 7949 ps.write(certificateSigningRequest. 7950 getPKCS10CertificateSigningRequestBytes()); 7951 } 7952 7953 if (outputFile != null) 7954 { 7955 ps.close(); 7956 } 7957 } 7958 catch (final Exception e) 7959 { 7960 Debug.debugException(e); 7961 wrapErr(0, WRAP_COLUMN, 7962 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CSR.get()); 7963 e.printStackTrace(getErr()); 7964 return ResultCode.LOCAL_ERROR; 7965 } 7966 7967 7968 // If the certificate signing request was written to an output file, 7969 // then let the user know that it was successful. If it was written to 7970 // standard output, then we don't need to tell them because they'll be 7971 // able to see it. 7972 if (outputFile != null) 7973 { 7974 out(); 7975 wrapOut(0, WRAP_COLUMN, 7976 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_CSR.get( 7977 outputFile.getAbsolutePath())); 7978 } 7979 7980 return ResultCode.SUCCESS; 7981 } 7982 7983 7984 // If we've gotten here, then we should be signing a certificate signing 7985 // request. Make sure that the keystore already has a private key entry 7986 // with the specified alias. 7987 Validator.ensureTrue(isSignCSR); 7988 if (! hasKeyAlias(keystore, alias)) 7989 { 7990 if (hasCertificateAlias(keystore, alias)) 7991 { 7992 wrapErr(0, WRAP_COLUMN, 7993 ERR_MANAGE_CERTS_GEN_CERT_SIGN_ALIAS_IS_CERT.get(alias, 7994 keystorePath.getAbsolutePath())); 7995 return ResultCode.PARAM_ERROR; 7996 } 7997 else 7998 { 7999 wrapErr(0, WRAP_COLUMN, 8000 ERR_MANAGE_CERTS_GEN_CERT_SIGN_NO_SUCH_ALIAS.get(alias, 8001 keystorePath.getAbsolutePath())); 8002 return ResultCode.PARAM_ERROR; 8003 } 8004 } 8005 8006 8007 // Get the signing certificate and its key pair. 8008 final PrivateKey issuerPrivateKey; 8009 final X509Certificate issuerCertificate; 8010 try 8011 { 8012 final Certificate[] chain = keystore.getCertificateChain(alias); 8013 issuerCertificate = new X509Certificate(chain[0].getEncoded()); 8014 8015 issuerPrivateKey = 8016 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 8017 } 8018 catch (final Exception e) 8019 { 8020 Debug.debugException(e); 8021 wrapErr(0, WRAP_COLUMN, 8022 ERR_MANAGE_CERTS_GEN_CERT_SIGN_CANNOT_GET_SIGNING_CERT.get(alias)); 8023 e.printStackTrace(getErr()); 8024 return ResultCode.LOCAL_ERROR; 8025 } 8026 8027 8028 // Make sure that we can decode the certificate signing request. 8029 final PKCS10CertificateSigningRequest csr; 8030 try 8031 { 8032 csr = readCertificateSigningRequestFromFile(inputFile); 8033 } 8034 catch (final LDAPException le) 8035 { 8036 Debug.debugException(le); 8037 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8038 return le.getResultCode(); 8039 } 8040 8041 8042 // Make sure that we can verify the certificate signing request's signature. 8043 try 8044 { 8045 csr.verifySignature(); 8046 } 8047 catch (final CertException ce) 8048 { 8049 Debug.debugException(ce); 8050 wrapErr(0, WRAP_COLUMN, ce.getMessage()); 8051 return ResultCode.PARAM_ERROR; 8052 } 8053 8054 8055 // Prompt about whether to sign the request, if appropriate. 8056 if (! noPrompt) 8057 { 8058 out(); 8059 wrapOut(0, WRAP_COLUMN, 8060 INFO_MANAGE_CERTS_GEN_CERT_SIGN_CONFIRM.get()); 8061 out(); 8062 printCertificateSigningRequest(csr, false, ""); 8063 out(); 8064 8065 try 8066 { 8067 if (! promptForYesNo( 8068 INFO_MANAGE_CERTS_GEN_CERT_PROMPT_SIGN.get())) 8069 { 8070 wrapErr(0, WRAP_COLUMN, 8071 ERR_MANAGE_CERTS_GEN_CERT_SIGN_CANCELED.get()); 8072 return ResultCode.USER_CANCELED; 8073 } 8074 } 8075 catch (final LDAPException le) 8076 { 8077 Debug.debugException(le); 8078 err(); 8079 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8080 return le.getResultCode(); 8081 } 8082 } 8083 8084 8085 // Read the certificate signing request and see if we need to take values 8086 // from it. 8087 if ((subjectDN == null) || (signatureAlgorithmIdentifier == null) || 8088 includeRequestedExtensions) 8089 { 8090 if (subjectDN == null) 8091 { 8092 subjectDN = csr.getSubjectDN(); 8093 } 8094 8095 if (signatureAlgorithmIdentifier == null) 8096 { 8097 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forOID( 8098 csr.getSignatureAlgorithmOID()); 8099 if (signatureAlgorithmIdentifier == null) 8100 { 8101 wrapErr(0, WRAP_COLUMN, 8102 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG_IN_CSR.get( 8103 csr.getSignatureAlgorithmOID())); 8104 return ResultCode.PARAM_ERROR; 8105 } 8106 else 8107 { 8108 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 8109 } 8110 } 8111 8112 if (includeRequestedExtensions) 8113 { 8114 for (final X509CertificateExtension extension : csr.getExtensions()) 8115 { 8116 if ((extension instanceof AuthorityKeyIdentifierExtension) || 8117 (extension instanceof IssuerAlternativeNameExtension)) 8118 { 8119 // This extension applies to the issuer. We won't include this in 8120 // the set of inherited extensions. 8121 } 8122 else if (extension instanceof SubjectKeyIdentifierExtension) 8123 { 8124 // The generated certificate will automatically include a subject 8125 // key identifier extension, so we don't need to include it. 8126 } 8127 else if (extension instanceof BasicConstraintsExtension) 8128 { 8129 // Don't override a value already provided on the command line. 8130 if (basicConstraints == null) 8131 { 8132 basicConstraints = (BasicConstraintsExtension) extension; 8133 extensionList.add(basicConstraints); 8134 } 8135 } 8136 else if (extension instanceof ExtendedKeyUsageExtension) 8137 { 8138 // Don't override a value already provided on the command line. 8139 if (extendedKeyUsage == null) 8140 { 8141 extendedKeyUsage = (ExtendedKeyUsageExtension) extension; 8142 extensionList.add(extendedKeyUsage); 8143 } 8144 } 8145 else if (extension instanceof KeyUsageExtension) 8146 { 8147 // Don't override a value already provided on the command line. 8148 if (keyUsage == null) 8149 { 8150 keyUsage = (KeyUsageExtension) extension; 8151 extensionList.add(keyUsage); 8152 } 8153 } 8154 else if (extension instanceof SubjectAlternativeNameExtension) 8155 { 8156 // Although we could merge values, it's safer to not do that if any 8157 // subject alternative name values were provided on the command 8158 // line. 8159 if (sanValues.isEmpty()) 8160 { 8161 final SubjectAlternativeNameExtension e = 8162 (SubjectAlternativeNameExtension) extension; 8163 for (final String dnsName : e.getDNSNames()) 8164 { 8165 sanBuilder.addDNSName(dnsName); 8166 sanValues.add("DNS:" + dnsName); 8167 } 8168 8169 for (final InetAddress ipAddress : e.getIPAddresses()) 8170 { 8171 sanBuilder.addIPAddress(ipAddress); 8172 sanValues.add("IP:" + ipAddress.getHostAddress()); 8173 } 8174 8175 for (final String emailAddress : e.getRFC822Names()) 8176 { 8177 sanBuilder.addRFC822Name(emailAddress); 8178 sanValues.add("EMAIL:" + emailAddress); 8179 } 8180 8181 for (final String uri : e.getUniformResourceIdentifiers()) 8182 { 8183 sanBuilder.addUniformResourceIdentifier(uri); 8184 sanValues.add("URI:" + uri); 8185 } 8186 8187 for (final OID oid : e.getRegisteredIDs()) 8188 { 8189 sanBuilder.addRegisteredID(oid); 8190 sanValues.add("OID:" + oid.toString()); 8191 } 8192 8193 try 8194 { 8195 extensionList.add( 8196 new SubjectAlternativeNameExtension(false, 8197 sanBuilder.build())); 8198 } 8199 catch (final Exception ex) 8200 { 8201 // This should never happen. 8202 Debug.debugException(ex); 8203 throw new RuntimeException(ex); 8204 } 8205 } 8206 } 8207 else 8208 { 8209 genericExtensions.add(extension); 8210 extensionList.add(extension); 8211 } 8212 } 8213 } 8214 } 8215 8216 8217 // Generate the keytool arguments to use to sign the requested certificate. 8218 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8219 keytoolArguments.add("-gencert"); 8220 keytoolArguments.add("-keystore"); 8221 keytoolArguments.add(keystorePath.getAbsolutePath()); 8222 keytoolArguments.add("-storetype"); 8223 keytoolArguments.add(keystoreType); 8224 keytoolArguments.add("-storepass"); 8225 keytoolArguments.add("*****REDACTED*****"); 8226 keytoolArguments.add("-keypass"); 8227 keytoolArguments.add("*****REDACTED*****"); 8228 keytoolArguments.add("-alias"); 8229 keytoolArguments.add(alias); 8230 keytoolArguments.add("-dname"); 8231 keytoolArguments.add(subjectDN.toString()); 8232 keytoolArguments.add("-sigalg"); 8233 keytoolArguments.add(signatureAlgorithmName); 8234 keytoolArguments.add("-validity"); 8235 keytoolArguments.add(String.valueOf(daysValid)); 8236 8237 if (validityStartTime != null) 8238 { 8239 keytoolArguments.add("-startdate"); 8240 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 8241 } 8242 8243 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 8244 extendedKeyUsage, sanValues, ianValues, genericExtensions); 8245 8246 keytoolArguments.add("-infile"); 8247 keytoolArguments.add(inputFile.getAbsolutePath()); 8248 8249 if (outputFile != null) 8250 { 8251 keytoolArguments.add("-outfile"); 8252 keytoolArguments.add(outputFile.getAbsolutePath()); 8253 } 8254 8255 if (outputPEM) 8256 { 8257 keytoolArguments.add("-rfc"); 8258 } 8259 8260 if (displayKeytoolCommand) 8261 { 8262 displayKeytoolCommand(keytoolArguments); 8263 } 8264 8265 8266 // Generate the signed certificate. 8267 final long notBefore; 8268 if (validityStartTime == null) 8269 { 8270 notBefore = System.currentTimeMillis(); 8271 } 8272 else 8273 { 8274 notBefore = validityStartTime.getTime(); 8275 } 8276 8277 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 8278 8279 final X509CertificateExtension[] extensions = 8280 new X509CertificateExtension[extensionList.size()]; 8281 extensionList.toArray(extensions); 8282 8283 final X509Certificate signedCertificate; 8284 try 8285 { 8286 signedCertificate = X509Certificate.generateIssuerSignedCertificate( 8287 signatureAlgorithmIdentifier, issuerCertificate, issuerPrivateKey, 8288 csr.getPublicKeyAlgorithmOID(), 8289 csr.getPublicKeyAlgorithmParameters(), csr.getEncodedPublicKey(), 8290 csr.getDecodedPublicKey(), subjectDN, notBefore, notAfter, 8291 extensions); 8292 } 8293 catch (final Exception e) 8294 { 8295 Debug.debugException(e); 8296 wrapErr(0, WRAP_COLUMN, 8297 ERR_MANAGE_CERTS_GEN_CERT_ERROR_SIGNING_CERT.get()); 8298 e.printStackTrace(getErr()); 8299 return ResultCode.LOCAL_ERROR; 8300 } 8301 8302 8303 // Write the signed certificate signing request to the appropriate location. 8304 try 8305 { 8306 final PrintStream ps; 8307 if (outputFile == null) 8308 { 8309 ps = getOut(); 8310 } 8311 else 8312 { 8313 ps = new PrintStream(outputFile); 8314 } 8315 8316 if (outputPEM) 8317 { 8318 writePEMCertificate(ps, signedCertificate.getX509CertificateBytes()); 8319 } 8320 else 8321 { 8322 ps.write(signedCertificate.getX509CertificateBytes()); 8323 } 8324 8325 if (outputFile != null) 8326 { 8327 ps.close(); 8328 } 8329 } 8330 catch (final Exception e) 8331 { 8332 Debug.debugException(e); 8333 wrapErr(0, WRAP_COLUMN, 8334 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_SIGNED_CERT.get()); 8335 e.printStackTrace(getErr()); 8336 return ResultCode.LOCAL_ERROR; 8337 } 8338 8339 8340 // If the certificate signing request was written to an output file, 8341 // then let the user know that it was successful. If it was written to 8342 // standard output, then we don't need to tell them because they'll be 8343 // able to see it. 8344 if (outputFile != null) 8345 { 8346 out(); 8347 wrapOut(0, WRAP_COLUMN, 8348 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_SIGNED_CERT.get( 8349 outputFile.getAbsolutePath())); 8350 } 8351 8352 return ResultCode.SUCCESS; 8353 } 8354 8355 8356 8357 /** 8358 * Performs the necessary processing for the change-certificate-alias 8359 * subcommand. 8360 * 8361 * @return A result code that indicates whether the processing completed 8362 * successfully. 8363 */ 8364 @NotNull() 8365 private ResultCode doChangeCertificateAlias() 8366 { 8367 // Get the values of a number of configured arguments. 8368 final StringArgument currentAliasArgument = 8369 subCommandParser.getStringArgument("current-alias"); 8370 final String currentAlias = currentAliasArgument.getValue(); 8371 8372 final StringArgument newAliasArgument = 8373 subCommandParser.getStringArgument("new-alias"); 8374 final String newAlias = newAliasArgument.getValue(); 8375 8376 final String keystoreType; 8377 final File keystorePath = getKeystorePath(); 8378 try 8379 { 8380 keystoreType = inferKeystoreType(keystorePath); 8381 } 8382 catch (final LDAPException le) 8383 { 8384 Debug.debugException(le); 8385 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8386 return le.getResultCode(); 8387 } 8388 8389 final char[] keystorePassword; 8390 try 8391 { 8392 keystorePassword = getKeystorePassword(keystorePath); 8393 } 8394 catch (final LDAPException le) 8395 { 8396 Debug.debugException(le); 8397 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8398 return le.getResultCode(); 8399 } 8400 8401 8402 // Get the keystore. 8403 final KeyStore keystore; 8404 try 8405 { 8406 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 8407 } 8408 catch (final LDAPException le) 8409 { 8410 Debug.debugException(le); 8411 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8412 return le.getResultCode(); 8413 } 8414 8415 8416 // See if we need to use a private key password that is different from the 8417 // keystore password. 8418 final char[] privateKeyPassword; 8419 try 8420 { 8421 privateKeyPassword = 8422 getPrivateKeyPassword(keystore, currentAlias, keystorePassword); 8423 } 8424 catch (final LDAPException le) 8425 { 8426 Debug.debugException(le); 8427 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8428 return le.getResultCode(); 8429 } 8430 8431 8432 // Make sure that the keystore has an existing entry with the current alias. 8433 // It must be either a certificate entry or a private key entry. 8434 final Certificate existingCertificate; 8435 final Certificate[] existingCertificateChain; 8436 final PrivateKey existingPrivateKey; 8437 try 8438 { 8439 if (hasCertificateAlias(keystore, currentAlias)) 8440 { 8441 existingCertificate = keystore.getCertificate(currentAlias); 8442 existingCertificateChain = null; 8443 existingPrivateKey = null; 8444 } 8445 else if (hasKeyAlias(keystore, currentAlias)) 8446 { 8447 existingCertificateChain = keystore.getCertificateChain(currentAlias); 8448 existingPrivateKey = 8449 (PrivateKey) keystore.getKey(currentAlias, privateKeyPassword); 8450 existingCertificate = null; 8451 } 8452 else 8453 { 8454 wrapErr(0, WRAP_COLUMN, 8455 ERR_MANAGE_CERTS_CHANGE_ALIAS_NO_SUCH_ALIAS.get(currentAlias)); 8456 return ResultCode.PARAM_ERROR; 8457 } 8458 } 8459 catch (final Exception e) 8460 { 8461 Debug.debugException(e); 8462 wrapErr(0, WRAP_COLUMN, 8463 ERR_MANAGE_CERTS_CHANGE_ALIAS_CANNOT_GET_EXISTING_ENTRY.get( 8464 currentAlias)); 8465 e.printStackTrace(getErr()); 8466 return ResultCode.LOCAL_ERROR; 8467 } 8468 8469 8470 // Make sure that the keystore does not have an entry with the new alias. 8471 if (hasCertificateAlias(keystore, newAlias) || 8472 hasKeyAlias(keystore, newAlias)) 8473 { 8474 wrapErr(0, WRAP_COLUMN, 8475 ERR_MANAGE_CERTS_CHANGE_ALIAS_NEW_ALIAS_IN_USE.get(newAlias)); 8476 return ResultCode.PARAM_ERROR; 8477 } 8478 8479 8480 // Generate the keytool arguments to use to change the certificate alias. 8481 final BooleanArgument displayKeytoolCommandArgument = 8482 subCommandParser.getBooleanArgument("display-keytool-command"); 8483 if ((displayKeytoolCommandArgument != null) && 8484 displayKeytoolCommandArgument.isPresent()) 8485 { 8486 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8487 keytoolArguments.add("-changealias"); 8488 keytoolArguments.add("-keystore"); 8489 keytoolArguments.add(keystorePath.getAbsolutePath()); 8490 keytoolArguments.add("-storetype"); 8491 keytoolArguments.add(keystoreType); 8492 keytoolArguments.add("-storepass"); 8493 keytoolArguments.add("*****REDACTED*****"); 8494 keytoolArguments.add("-keypass"); 8495 keytoolArguments.add("*****REDACTED*****"); 8496 keytoolArguments.add("-alias"); 8497 keytoolArguments.add(currentAlias); 8498 keytoolArguments.add("-destalias"); 8499 keytoolArguments.add(newAlias); 8500 8501 displayKeytoolCommand(keytoolArguments); 8502 } 8503 8504 8505 // Update the keystore to remove the entry with the current alias and 8506 // re-write it with the new alias. 8507 try 8508 { 8509 keystore.deleteEntry(currentAlias); 8510 if (existingCertificate != null) 8511 { 8512 keystore.setCertificateEntry(newAlias, existingCertificate); 8513 } 8514 else 8515 { 8516 keystore.setKeyEntry(newAlias, existingPrivateKey, 8517 privateKeyPassword, existingCertificateChain); 8518 } 8519 8520 writeKeystore(keystore, keystorePath, keystorePassword); 8521 } 8522 catch (final Exception e) 8523 { 8524 Debug.debugException(e); 8525 wrapErr(0, WRAP_COLUMN, 8526 ERR_MANAGE_CERTS_CHANGE_ALIAS_CANNOT_UPDATE_KEYSTORE.get()); 8527 e.printStackTrace(getErr()); 8528 return ResultCode.LOCAL_ERROR; 8529 } 8530 8531 wrapOut(0, WRAP_COLUMN, 8532 INFO_MANAGE_CERTS_CHANGE_ALIAS_SUCCESSFUL.get(currentAlias, 8533 newAlias)); 8534 return ResultCode.SUCCESS; 8535 } 8536 8537 8538 8539 /** 8540 * Performs the necessary processing for the change-keystore-password 8541 * subcommand. 8542 * 8543 * @return A result code that indicates whether the processing completed 8544 * successfully. 8545 */ 8546 @NotNull() 8547 private ResultCode doChangeKeystorePassword() 8548 { 8549 // Get the values of a number of configured arguments. 8550 final String keystoreType; 8551 final File keystorePath = getKeystorePath(); 8552 try 8553 { 8554 keystoreType = inferKeystoreType(keystorePath); 8555 } 8556 catch (final LDAPException le) 8557 { 8558 Debug.debugException(le); 8559 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8560 return le.getResultCode(); 8561 } 8562 8563 final char[] currentKeystorePassword; 8564 try 8565 { 8566 currentKeystorePassword = getKeystorePassword(keystorePath, "current"); 8567 } 8568 catch (final LDAPException le) 8569 { 8570 Debug.debugException(le); 8571 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8572 return le.getResultCode(); 8573 } 8574 8575 final char[] newKeystorePassword; 8576 try 8577 { 8578 newKeystorePassword = getKeystorePassword(keystorePath, "new"); 8579 } 8580 catch (final LDAPException le) 8581 { 8582 Debug.debugException(le); 8583 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8584 return le.getResultCode(); 8585 } 8586 8587 8588 // Get the keystore. 8589 final KeyStore keystore; 8590 try 8591 { 8592 keystore = getKeystore(keystoreType, keystorePath, 8593 currentKeystorePassword); 8594 } 8595 catch (final LDAPException le) 8596 { 8597 Debug.debugException(le); 8598 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8599 return le.getResultCode(); 8600 } 8601 8602 8603 // Generate the keytool arguments to use to change the keystore password. 8604 final BooleanArgument displayKeytoolCommandArgument = 8605 subCommandParser.getBooleanArgument("display-keytool-command"); 8606 if ((displayKeytoolCommandArgument != null) && 8607 displayKeytoolCommandArgument.isPresent()) 8608 { 8609 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8610 keytoolArguments.add("-storepasswd"); 8611 keytoolArguments.add("-keystore"); 8612 keytoolArguments.add(keystorePath.getAbsolutePath()); 8613 keytoolArguments.add("-storetype"); 8614 keytoolArguments.add(keystoreType); 8615 keytoolArguments.add("-storepass"); 8616 keytoolArguments.add("*****REDACTED*****"); 8617 keytoolArguments.add("-new"); 8618 keytoolArguments.add("*****REDACTED*****"); 8619 8620 displayKeytoolCommand(keytoolArguments); 8621 } 8622 8623 8624 // Rewrite the keystore with the new password. 8625 try 8626 { 8627 writeKeystore(keystore, keystorePath, newKeystorePassword); 8628 } 8629 catch (final LDAPException le) 8630 { 8631 Debug.debugException(le); 8632 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8633 return le.getResultCode(); 8634 } 8635 8636 wrapOut(0, WRAP_COLUMN, 8637 INFO_MANAGE_CERTS_CHANGE_KS_PW_SUCCESSFUL.get( 8638 keystorePath.getAbsolutePath())); 8639 return ResultCode.SUCCESS; 8640 } 8641 8642 8643 8644 /** 8645 * Performs the necessary processing for the change-private-key-password 8646 * subcommand. 8647 * 8648 * @return A result code that indicates whether the processing completed 8649 * successfully. 8650 */ 8651 @NotNull() 8652 private ResultCode doChangePrivateKeyPassword() 8653 { 8654 // Get the values of a number of configured arguments. 8655 final StringArgument aliasArgument = 8656 subCommandParser.getStringArgument("alias"); 8657 final String alias = aliasArgument.getValue(); 8658 8659 final String keystoreType; 8660 final File keystorePath = getKeystorePath(); 8661 try 8662 { 8663 keystoreType = inferKeystoreType(keystorePath); 8664 } 8665 catch (final LDAPException le) 8666 { 8667 Debug.debugException(le); 8668 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8669 return le.getResultCode(); 8670 } 8671 8672 final char[] keystorePassword; 8673 try 8674 { 8675 keystorePassword = getKeystorePassword(keystorePath); 8676 } 8677 catch (final LDAPException le) 8678 { 8679 Debug.debugException(le); 8680 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8681 return le.getResultCode(); 8682 } 8683 8684 8685 // Get the keystore. 8686 final KeyStore keystore; 8687 try 8688 { 8689 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 8690 } 8691 catch (final LDAPException le) 8692 { 8693 Debug.debugException(le); 8694 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8695 return le.getResultCode(); 8696 } 8697 8698 8699 // Make sure that the keystore has a key entry with the specified alias. 8700 if (hasCertificateAlias(keystore, alias)) 8701 { 8702 wrapErr(0, WRAP_COLUMN, 8703 ERR_MANAGE_CERTS_CHANGE_PK_PW_ALIAS_IS_CERT.get(alias)); 8704 return ResultCode.PARAM_ERROR; 8705 } 8706 else if (! hasKeyAlias(keystore, alias)) 8707 { 8708 wrapErr(0, WRAP_COLUMN, 8709 ERR_MANAGE_CERTS_CHANGE_PK_PW_NO_SUCH_ALIAS.get(alias)); 8710 return ResultCode.PARAM_ERROR; 8711 } 8712 8713 8714 // Get the current and new private key passwords. 8715 final char[] currentPrivateKeyPassword; 8716 try 8717 { 8718 currentPrivateKeyPassword = 8719 getPrivateKeyPassword(keystore, alias, "current", keystorePassword); 8720 } 8721 catch (final LDAPException le) 8722 { 8723 Debug.debugException(le); 8724 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8725 return le.getResultCode(); 8726 } 8727 8728 final char[] newPrivateKeyPassword; 8729 try 8730 { 8731 newPrivateKeyPassword = 8732 getPrivateKeyPassword(keystore, alias, "new", keystorePassword); 8733 } 8734 catch (final LDAPException le) 8735 { 8736 Debug.debugException(le); 8737 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8738 return le.getResultCode(); 8739 } 8740 8741 8742 // Generate the keytool arguments to use to change the private key. 8743 final BooleanArgument displayKeytoolCommandArgument = 8744 subCommandParser.getBooleanArgument("display-keytool-command"); 8745 if ((displayKeytoolCommandArgument != null) && 8746 displayKeytoolCommandArgument.isPresent()) 8747 { 8748 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8749 keytoolArguments.add("-keypasswd"); 8750 keytoolArguments.add("-keystore"); 8751 keytoolArguments.add(keystorePath.getAbsolutePath()); 8752 keytoolArguments.add("-storetype"); 8753 keytoolArguments.add(keystoreType); 8754 keytoolArguments.add("-storepass"); 8755 keytoolArguments.add("*****REDACTED*****"); 8756 keytoolArguments.add("-alias"); 8757 keytoolArguments.add(alias); 8758 keytoolArguments.add("-keypass"); 8759 keytoolArguments.add("*****REDACTED*****"); 8760 keytoolArguments.add("-new"); 8761 keytoolArguments.add("*****REDACTED*****"); 8762 8763 displayKeytoolCommand(keytoolArguments); 8764 } 8765 8766 8767 // Get the contents of the private key entry. 8768 final Certificate[] chain; 8769 final PrivateKey privateKey; 8770 try 8771 { 8772 chain = keystore.getCertificateChain(alias); 8773 privateKey = 8774 (PrivateKey) keystore.getKey(alias, currentPrivateKeyPassword); 8775 } 8776 catch (final UnrecoverableKeyException e) 8777 { 8778 Debug.debugException(e); 8779 wrapErr(0, WRAP_COLUMN, 8780 ERR_MANAGE_CERTS_CHANGE_PK_PW_WRONG_PK_PW.get(alias)); 8781 return ResultCode.PARAM_ERROR; 8782 } 8783 catch (final Exception e) 8784 { 8785 Debug.debugException(e); 8786 wrapErr(0, WRAP_COLUMN, 8787 ERR_MANAGE_CERTS_CHANGE_PK_PW_CANNOT_GET_PK.get(alias)); 8788 e.printStackTrace(getErr()); 8789 return ResultCode.LOCAL_ERROR; 8790 } 8791 8792 8793 // Remove the existing key entry and re-add it with the new password. 8794 try 8795 { 8796 keystore.deleteEntry(alias); 8797 keystore.setKeyEntry(alias, privateKey, newPrivateKeyPassword, chain); 8798 writeKeystore(keystore, keystorePath, keystorePassword); 8799 } 8800 catch (final Exception e) 8801 { 8802 Debug.debugException(e); 8803 wrapErr(0, WRAP_COLUMN, 8804 ERR_MANAGE_CERTS_CHANGE_PK_PW_CANNOT_UPDATE_KS.get()); 8805 e.printStackTrace(getErr()); 8806 return ResultCode.LOCAL_ERROR; 8807 } 8808 8809 wrapOut(0, WRAP_COLUMN, 8810 INFO_MANAGE_CERTS_CHANGE_PK_PW_SUCCESSFUL.get(alias)); 8811 return ResultCode.SUCCESS; 8812 } 8813 8814 8815 8816 /** 8817 * Performs the necessary processing for the copy-keystore subcommand. 8818 * 8819 * @return A result code that indicates whether the processing completed 8820 * successfully. 8821 */ 8822 @NotNull() 8823 private ResultCode doCopyKeystore() 8824 { 8825 // Get the source key store. 8826 final String sourceKeyStoreType; 8827 final File sourceKeyStorePath = getKeystorePath("source-keystore"); 8828 try 8829 { 8830 sourceKeyStoreType = inferKeystoreType(sourceKeyStorePath, "source"); 8831 } 8832 catch (final LDAPException le) 8833 { 8834 Debug.debugException(le); 8835 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8836 return le.getResultCode(); 8837 } 8838 8839 final char[] sourceKeyStorePassword; 8840 try 8841 { 8842 sourceKeyStorePassword = 8843 getKeystorePassword(sourceKeyStorePath, "source"); 8844 } 8845 catch (final LDAPException le) 8846 { 8847 Debug.debugException(le); 8848 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8849 return le.getResultCode(); 8850 } 8851 8852 final KeyStore sourceKeyStore; 8853 try 8854 { 8855 sourceKeyStore = getKeystore(sourceKeyStoreType, sourceKeyStorePath, 8856 sourceKeyStorePassword); 8857 } 8858 catch (final LDAPException le) 8859 { 8860 Debug.debugException(le); 8861 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8862 return le.getResultCode(); 8863 } 8864 8865 8866 // Get the destination key store. 8867 final String destinationKeyStoreType; 8868 final File destinationKeyStorePath = 8869 getKeystorePath("destination-keystore"); 8870 try 8871 { 8872 destinationKeyStoreType = inferKeystoreType(destinationKeyStorePath, 8873 "destination"); 8874 } 8875 catch (final LDAPException le) 8876 { 8877 Debug.debugException(le); 8878 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8879 return le.getResultCode(); 8880 } 8881 8882 final boolean destinationExists = destinationKeyStorePath.exists(); 8883 8884 char[] destinationKeyStorePassword; 8885 try 8886 { 8887 destinationKeyStorePassword = 8888 getKeystorePassword(destinationKeyStorePath, "destination"); 8889 if (destinationKeyStorePassword == null) 8890 { 8891 destinationKeyStorePassword = sourceKeyStorePassword; 8892 } 8893 } 8894 catch (final LDAPException le) 8895 { 8896 Debug.debugException(le); 8897 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8898 return le.getResultCode(); 8899 } 8900 8901 final KeyStore destinationKeyStore; 8902 try 8903 { 8904 destinationKeyStore = getKeystore(destinationKeyStoreType, 8905 destinationKeyStorePath, destinationKeyStorePassword); 8906 } 8907 catch (final LDAPException le) 8908 { 8909 Debug.debugException(le); 8910 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8911 return le.getResultCode(); 8912 } 8913 8914 8915 // Get the value of the aliases argument, if it was provided. 8916 final Set<String> aliases = new LinkedHashSet<>(); 8917 try 8918 { 8919 final StringArgument aliasArg = 8920 subCommandParser.getStringArgument("alias"); 8921 if ((aliasArg != null) && aliasArg.isPresent()) 8922 { 8923 for (final String alias : aliasArg.getValues()) 8924 { 8925 aliases.add(alias); 8926 if (! sourceKeyStore.containsAlias(alias)) 8927 { 8928 wrapErr(0, WRAP_COLUMN, 8929 ERR_MANAGE_CERTS_COPY_KS_NO_SUCH_SOURCE_ALIAS.get( 8930 sourceKeyStorePath.getAbsolutePath(), alias)); 8931 return ResultCode.PARAM_ERROR; 8932 } 8933 } 8934 } 8935 else 8936 { 8937 final Enumeration<String> sourceAliases = sourceKeyStore.aliases(); 8938 while (sourceAliases.hasMoreElements()) 8939 { 8940 aliases.add(sourceAliases.nextElement()); 8941 } 8942 } 8943 } 8944 catch (final Exception e) 8945 { 8946 Debug.debugException(e); 8947 wrapErr(0, WRAP_COLUMN, 8948 ERR_MANAGE_CERTS_COPY_KS_CANNOT_GET_SOURCE_ALIASES.get( 8949 sourceKeyStorePath.getAbsolutePath(), 8950 StaticUtils.getExceptionMessage(e))); 8951 return ResultCode.LOCAL_ERROR; 8952 } 8953 8954 8955 // If the set of aliases is empty and the destination key store already 8956 // exists, then exit without doing anything. 8957 if (aliases.isEmpty() && destinationExists) 8958 { 8959 wrapOut(0, WRAP_COLUMN, 8960 INFO_MANAGE_CERTS_COPY_KS_NO_CERTS_COPIED_EXISTING_KS.get( 8961 sourceKeyStorePath.getAbsolutePath(), 8962 destinationKeyStorePath.getAbsolutePath())); 8963 return ResultCode.SUCCESS; 8964 } 8965 8966 8967 // Make sure that none of the target aliases exist in the destination key 8968 // store. 8969 for (final String alias : aliases) 8970 { 8971 try 8972 { 8973 if (destinationKeyStore.containsAlias(alias)) 8974 { 8975 wrapErr(0, WRAP_COLUMN, 8976 ERR_MANAGE_CERTS_COPY_KS_CONFLICTING_ALIAS.get(alias, 8977 destinationKeyStorePath.getAbsolutePath(), 8978 subCommandParser.getCommandName())); 8979 return ResultCode.CONSTRAINT_VIOLATION; 8980 } 8981 } 8982 catch (final Exception e) 8983 { 8984 Debug.debugException(e); 8985 wrapErr(0, WRAP_COLUMN, 8986 ERR_MANAGE_CERTS_COPY_KS_CANNOT_CHECK_DEST_ALIAS.get(alias, 8987 destinationKeyStorePath.getAbsolutePath(), 8988 StaticUtils.getExceptionMessage(e))); 8989 return ResultCode.LOCAL_ERROR; 8990 } 8991 } 8992 8993 8994 // Copy each of the targeted entries from the source key store into the 8995 // destination key store. 8996 char[] sourcePrivateKeyPassword = null; 8997 char[] destinationPrivateKeyPassword = null; 8998 for (final String alias : aliases) 8999 { 9000 try 9001 { 9002 if (sourceKeyStore.isCertificateEntry(alias)) 9003 { 9004 final Certificate certificate = sourceKeyStore.getCertificate(alias); 9005 destinationKeyStore.setCertificateEntry(alias, certificate); 9006 } 9007 else 9008 { 9009 if (sourcePrivateKeyPassword == null) 9010 { 9011 sourcePrivateKeyPassword = getPrivateKeyPassword(sourceKeyStore, 9012 alias, "source", sourceKeyStorePassword); 9013 } 9014 9015 if (destinationPrivateKeyPassword == null) 9016 { 9017 destinationPrivateKeyPassword = getPrivateKeyPassword( 9018 destinationKeyStore, alias, "destination", 9019 destinationKeyStorePassword); 9020 } 9021 9022 final Certificate[] chain = sourceKeyStore.getCertificateChain(alias); 9023 final Key key = 9024 sourceKeyStore.getKey(alias, sourcePrivateKeyPassword); 9025 destinationKeyStore.setKeyEntry(alias, key, 9026 destinationPrivateKeyPassword, chain); 9027 } 9028 } 9029 catch (final Exception e) 9030 { 9031 Debug.debugException(e); 9032 wrapErr(0, WRAP_COLUMN, 9033 ERR_MANAGE_CERTS_COPY_KS_ERROR_COPYING_ENTRY.get(alias, 9034 sourceKeyStorePath.getAbsolutePath(), 9035 destinationKeyStorePath.getAbsolutePath(), 9036 StaticUtils.getExceptionMessage(e))); 9037 return ResultCode.LOCAL_ERROR; 9038 } 9039 } 9040 9041 9042 // Rewrite the destination keystore. 9043 try 9044 { 9045 writeKeystore(destinationKeyStore, destinationKeyStorePath, 9046 destinationKeyStorePassword); 9047 } 9048 catch (final LDAPException le) 9049 { 9050 Debug.debugException(le); 9051 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9052 return le.getResultCode(); 9053 } 9054 9055 if (aliases.isEmpty()) 9056 { 9057 // This should only happen if the alias argument was not provided, the 9058 // source key store is empty, and the destination key store doesn't exist. 9059 // In that case, the destination key store will have been created. 9060 wrapOut(0, WRAP_COLUMN, 9061 INFO_MANAGE_CERTS_COPY_KS_NO_CERTS_COPIED_KS_CREATED.get( 9062 sourceKeyStorePath.getAbsolutePath(), 9063 destinationKeyStoreType, 9064 destinationKeyStorePath.getAbsolutePath())); 9065 } 9066 else 9067 { 9068 // Write a message about the entries that were successfully copied. 9069 wrapOut(0, WRAP_COLUMN, 9070 INFO_MANAGE_CERTS_COPY_KS_CERTS_COPIED_HEADER.get( 9071 sourceKeyStorePath.getAbsolutePath(), 9072 destinationKeyStoreType, 9073 destinationKeyStorePath.getAbsolutePath())); 9074 for (final String alias : aliases) 9075 { 9076 out("* ", alias); 9077 } 9078 } 9079 9080 return ResultCode.SUCCESS; 9081 } 9082 9083 9084 9085 /** 9086 * Performs the necessary processing for the retrieve-server-certificate 9087 * subcommand. 9088 * 9089 * @return A result code that indicates whether the processing completed 9090 * successfully. 9091 */ 9092 @NotNull() 9093 private ResultCode doRetrieveServerCertificate() 9094 { 9095 // Get the values of a number of configured arguments. 9096 final StringArgument hostnameArgument = 9097 subCommandParser.getStringArgument("hostname"); 9098 final String hostname = hostnameArgument.getValue(); 9099 9100 final IntegerArgument portArgument = 9101 subCommandParser.getIntegerArgument("port"); 9102 final int port = portArgument.getValue(); 9103 9104 final BooleanArgument useLDAPStartTLSArgument = 9105 subCommandParser.getBooleanArgument("use-ldap-start-tls"); 9106 final boolean useLDAPStartTLS = 9107 ((useLDAPStartTLSArgument != null) && 9108 useLDAPStartTLSArgument.isPresent()); 9109 9110 final BooleanArgument onlyPeerArgument = 9111 subCommandParser.getBooleanArgument("only-peer-certificate"); 9112 final boolean onlyPeer = 9113 ((onlyPeerArgument != null) && onlyPeerArgument.isPresent()); 9114 9115 final BooleanArgument verboseArgument = 9116 subCommandParser.getBooleanArgument("verbose"); 9117 final boolean verbose = 9118 ((verboseArgument != null) && verboseArgument.isPresent()); 9119 9120 boolean outputPEM = true; 9121 final StringArgument outputFormatArgument = 9122 subCommandParser.getStringArgument("output-format"); 9123 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 9124 { 9125 final String format = outputFormatArgument.getValue().toLowerCase(); 9126 if (format.equals("der") || format.equals("binary") || 9127 format.equals("bin")) 9128 { 9129 outputPEM = false; 9130 } 9131 } 9132 9133 File outputFile = null; 9134 final FileArgument outputFileArgument = 9135 subCommandParser.getFileArgument("output-file"); 9136 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 9137 { 9138 outputFile = outputFileArgument.getValue(); 9139 } 9140 9141 9142 // Spawn a background thread to establish a connection and get the 9143 // certificate chain from the target server. 9144 final LinkedBlockingQueue<Object> responseQueue = 9145 new LinkedBlockingQueue<>(10); 9146 final ManageCertificatesServerCertificateCollector certificateCollector = 9147 new ManageCertificatesServerCertificateCollector(this, hostname, port, 9148 useLDAPStartTLS, verbose, responseQueue); 9149 certificateCollector.start(); 9150 9151 Object responseObject = 9152 ERR_MANAGE_CERTS_RETRIEVE_CERT_NO_CERT_CHAIN_RECEIVED.get( 9153 hostname + ':' + port); 9154 try 9155 { 9156 responseObject = responseQueue.poll(90L, TimeUnit.SECONDS); 9157 } 9158 catch (final Exception e) 9159 { 9160 Debug.debugException(e); 9161 } 9162 9163 final X509Certificate[] chain; 9164 if (responseObject instanceof X509Certificate[]) 9165 { 9166 chain = (X509Certificate[]) responseObject; 9167 if (chain.length == 0) 9168 { 9169 wrapErr(0, WRAP_COLUMN, 9170 ERR_MANAGE_CERTS_RETRIEVE_CERT_EMPTY_CHAIN.get()); 9171 return ResultCode.NO_RESULTS_RETURNED; 9172 } 9173 } 9174 else if (responseObject instanceof CertException) 9175 { 9176 // The error message will have already been recorded by the collector 9177 // thread, so we can just return a non-success result. 9178 return ResultCode.LOCAL_ERROR; 9179 } 9180 else 9181 { 9182 wrapErr(0, WRAP_COLUMN, String.valueOf(responseObject)); 9183 return ResultCode.LOCAL_ERROR; 9184 } 9185 9186 try 9187 { 9188 certificateCollector.join(10_000L); 9189 } 9190 catch (final Exception e) 9191 { 9192 Debug.debugException(e); 9193 } 9194 9195 9196 // If the certificates should be written to a file, then do that now. 9197 if (outputFile != null) 9198 { 9199 try (PrintStream s = new PrintStream(outputFile)) 9200 { 9201 for (final X509Certificate c : chain) 9202 { 9203 if (outputPEM) 9204 { 9205 writePEMCertificate(s, c.getX509CertificateBytes()); 9206 } 9207 else 9208 { 9209 s.write(c.getX509CertificateBytes()); 9210 } 9211 9212 if (onlyPeer) 9213 { 9214 break; 9215 } 9216 } 9217 } 9218 catch (final Exception e) 9219 { 9220 Debug.debugException(e); 9221 wrapErr(0, WRAP_COLUMN, 9222 ERR_MANAGE_CERTS_RETRIEVE_CERT_CANNOT_WRITE_TO_FILE.get( 9223 outputFile.getAbsolutePath(), 9224 StaticUtils.getExceptionMessage(e))); 9225 return ResultCode.LOCAL_ERROR; 9226 } 9227 } 9228 9229 9230 // Display information about the certificates. 9231 for (int i=0; i < chain.length; i++) 9232 { 9233 if (verbose || (i > 0)) 9234 { 9235 out(); 9236 out(); 9237 } 9238 9239 if ((! onlyPeer) && (chain.length > 1)) 9240 { 9241 wrapOut(0, WRAP_COLUMN, 9242 INFO_MANAGE_CERTS_RETRIEVE_CERT_DISPLAY_HEADER.get((i+1), 9243 chain.length)); 9244 out(); 9245 } 9246 9247 final X509Certificate c = chain[i]; 9248 writePEMCertificate(getOut(), c.getX509CertificateBytes()); 9249 out(); 9250 printCertificate(c, "", verbose); 9251 9252 if (onlyPeer) 9253 { 9254 break; 9255 } 9256 } 9257 9258 return ResultCode.SUCCESS; 9259 } 9260 9261 9262 9263 /** 9264 * Performs the necessary processing for the trust-server-certificate 9265 * subcommand. 9266 * 9267 * @return A result code that indicates whether the processing completed 9268 * successfully. 9269 */ 9270 @NotNull() 9271 private ResultCode doTrustServerCertificate() 9272 { 9273 // Get the values of a number of configured arguments. 9274 final StringArgument hostnameArgument = 9275 subCommandParser.getStringArgument("hostname"); 9276 final String hostname = hostnameArgument.getValue(); 9277 9278 final IntegerArgument portArgument = 9279 subCommandParser.getIntegerArgument("port"); 9280 final int port = portArgument.getValue(); 9281 9282 final String alias; 9283 final StringArgument aliasArgument = 9284 subCommandParser.getStringArgument("alias"); 9285 if ((aliasArgument != null) && aliasArgument.isPresent()) 9286 { 9287 alias = aliasArgument.getValue(); 9288 } 9289 else 9290 { 9291 alias = hostname + ':' + port; 9292 } 9293 9294 final BooleanArgument useLDAPStartTLSArgument = 9295 subCommandParser.getBooleanArgument("use-ldap-start-tls"); 9296 final boolean useLDAPStartTLS = 9297 ((useLDAPStartTLSArgument != null) && 9298 useLDAPStartTLSArgument.isPresent()); 9299 9300 final BooleanArgument issuersOnlyArgument = 9301 subCommandParser.getBooleanArgument("issuers-only"); 9302 final boolean issuersOnly = 9303 ((issuersOnlyArgument != null) && issuersOnlyArgument.isPresent()); 9304 9305 final BooleanArgument noPromptArgument = 9306 subCommandParser.getBooleanArgument("no-prompt"); 9307 final boolean noPrompt = 9308 ((noPromptArgument != null) && noPromptArgument.isPresent()); 9309 9310 final BooleanArgument verboseArgument = 9311 subCommandParser.getBooleanArgument("verbose"); 9312 final boolean verbose = 9313 ((verboseArgument != null) && verboseArgument.isPresent()); 9314 9315 final String keystoreType; 9316 final File keystorePath = getKeystorePath(); 9317 final boolean isNewKeystore = (! keystorePath.exists()); 9318 try 9319 { 9320 keystoreType = inferKeystoreType(keystorePath); 9321 } 9322 catch (final LDAPException le) 9323 { 9324 Debug.debugException(le); 9325 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9326 return le.getResultCode(); 9327 } 9328 9329 final char[] keystorePassword; 9330 try 9331 { 9332 keystorePassword = getKeystorePassword(keystorePath); 9333 } 9334 catch (final LDAPException le) 9335 { 9336 Debug.debugException(le); 9337 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9338 return le.getResultCode(); 9339 } 9340 9341 9342 // Get the keystore. 9343 final KeyStore keystore; 9344 try 9345 { 9346 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 9347 } 9348 catch (final LDAPException le) 9349 { 9350 Debug.debugException(le); 9351 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9352 return le.getResultCode(); 9353 } 9354 9355 9356 // Make sure that the specified alias is not already in use. 9357 if (hasCertificateAlias(keystore, alias) || 9358 hasKeyAlias(keystore, alias)) 9359 { 9360 wrapErr(0, WRAP_COLUMN, 9361 ERR_MANAGE_CERTS_TRUST_SERVER_ALIAS_IN_USE.get(alias)); 9362 return ResultCode.PARAM_ERROR; 9363 } 9364 9365 9366 // Spawn a background thread to establish a connection and get the 9367 // certificate chain from the target server. 9368 final LinkedBlockingQueue<Object> responseQueue = 9369 new LinkedBlockingQueue<>(10); 9370 final ManageCertificatesServerCertificateCollector certificateCollector = 9371 new ManageCertificatesServerCertificateCollector(this, hostname, port, 9372 useLDAPStartTLS, verbose, responseQueue); 9373 certificateCollector.start(); 9374 9375 Object responseObject = 9376 ERR_MANAGE_CERTS_TRUST_SERVER_NO_CERT_CHAIN_RECEIVED.get( 9377 hostname + ':' + port); 9378 try 9379 { 9380 responseObject = responseQueue.poll(90L, TimeUnit.SECONDS); 9381 } 9382 catch (final Exception e) 9383 { 9384 Debug.debugException(e); 9385 } 9386 9387 final X509Certificate[] chain; 9388 if (responseObject instanceof X509Certificate[]) 9389 { 9390 chain = (X509Certificate[]) responseObject; 9391 } 9392 else if (responseObject instanceof CertException) 9393 { 9394 // The error message will have already been recorded by the collector 9395 // thread, so we can just return a non-success result. 9396 return ResultCode.LOCAL_ERROR; 9397 } 9398 else 9399 { 9400 wrapErr(0, WRAP_COLUMN, String.valueOf(responseObject)); 9401 return ResultCode.LOCAL_ERROR; 9402 } 9403 9404 try 9405 { 9406 certificateCollector.join(10_000L); 9407 } 9408 catch (final Exception e) 9409 { 9410 Debug.debugException(e); 9411 } 9412 9413 9414 // If we should prompt the user about whether to trust the certificates, 9415 // then do so now. 9416 if (! noPrompt) 9417 { 9418 out(); 9419 wrapOut(0, WRAP_COLUMN, 9420 INFO_MANAGE_CERTS_TRUST_SERVER_RETRIEVED_CHAIN.get( 9421 hostname + ':' + port)); 9422 9423 boolean isFirst = true; 9424 for (final X509Certificate c : chain) 9425 { 9426 out(); 9427 9428 if (isFirst) 9429 { 9430 isFirst = false; 9431 if (issuersOnly && (chain.length > 1)) 9432 { 9433 wrapOut(0, WRAP_COLUMN, 9434 INFO_MANAGE_CERTS_TRUST_SERVER_NOTE_OMITTED.get()); 9435 out(); 9436 } 9437 } 9438 9439 printCertificate(c, "", verbose); 9440 } 9441 9442 out(); 9443 9444 try 9445 { 9446 if (! promptForYesNo(INFO_MANAGE_CERTS_TRUST_SERVER_PROMPT_TRUST.get())) 9447 { 9448 wrapErr(0, WRAP_COLUMN, 9449 ERR_MANAGE_CERTS_TRUST_SERVER_CHAIN_REJECTED.get()); 9450 return ResultCode.USER_CANCELED; 9451 } 9452 } 9453 catch (final LDAPException le) 9454 { 9455 Debug.debugException(le); 9456 err(); 9457 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9458 return le.getResultCode(); 9459 } 9460 } 9461 9462 9463 // Add the certificates to the keystore. 9464 final LinkedHashMap<String,X509Certificate> certsByAlias = 9465 new LinkedHashMap<>(StaticUtils.computeMapCapacity(chain.length)); 9466 for (int i=0; i < chain.length; i++) 9467 { 9468 if (i == 0) 9469 { 9470 if (issuersOnly && (chain.length > 1)) 9471 { 9472 continue; 9473 } 9474 9475 certsByAlias.put(alias, chain[i]); 9476 } 9477 else if ((i == 1) && (chain.length == 2)) 9478 { 9479 certsByAlias.put(alias + "-issuer", chain[i]); 9480 } 9481 else 9482 { 9483 certsByAlias.put(alias + "-issuer-" + i, chain[i]); 9484 } 9485 } 9486 9487 for (final Map.Entry<String,X509Certificate> e : certsByAlias.entrySet()) 9488 { 9489 final String certAlias = e.getKey(); 9490 final X509Certificate cert = e.getValue(); 9491 9492 try 9493 { 9494 Validator.ensureFalse( 9495 (hasCertificateAlias(keystore, certAlias) || 9496 hasKeyAlias(keystore, certAlias)), 9497 "ERROR: Alias '" + certAlias + "' is already in use in the " + 9498 "keystore."); 9499 keystore.setCertificateEntry(certAlias, cert.toCertificate()); 9500 } 9501 catch (final Exception ex) 9502 { 9503 Debug.debugException(ex); 9504 wrapErr(0, WRAP_COLUMN, 9505 ERR_MANAGE_CERTS_TRUST_SERVER_ERROR_ADDING_CERT_TO_KS.get( 9506 cert.getSubjectDN())); 9507 ex.printStackTrace(getErr()); 9508 return ResultCode.LOCAL_ERROR; 9509 } 9510 } 9511 9512 9513 // Save the updated keystore. 9514 try 9515 { 9516 writeKeystore(keystore, keystorePath, keystorePassword); 9517 } 9518 catch (final LDAPException le) 9519 { 9520 Debug.debugException(le); 9521 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9522 return le.getResultCode(); 9523 } 9524 9525 if (isNewKeystore) 9526 { 9527 out(); 9528 wrapOut(0, WRAP_COLUMN, 9529 INFO_MANAGE_CERTS_TRUST_SERVER_CERT_CREATED_KEYSTORE.get( 9530 getUserFriendlyKeystoreType(keystoreType))); 9531 } 9532 9533 out(); 9534 if (certsByAlias.size() == 1) 9535 { 9536 wrapOut(0, WRAP_COLUMN, 9537 INFO_MANAGE_CERTS_TRUST_SERVER_ADDED_CERT_TO_KS.get()); 9538 } 9539 else 9540 { 9541 wrapOut(0, WRAP_COLUMN, 9542 INFO_MANAGE_CERTS_TRUST_SERVER_ADDED_CERTS_TO_KS.get( 9543 certsByAlias.size())); 9544 } 9545 9546 return ResultCode.SUCCESS; 9547 } 9548 9549 9550 9551 /** 9552 * Performs the necessary processing for the check-certificate-usability 9553 * subcommand. 9554 * 9555 * @return A result code that indicates whether the processing completed 9556 * successfully. 9557 */ 9558 @NotNull() 9559 private ResultCode doCheckCertificateUsability() 9560 { 9561 // Get the values of a number of configured arguments. 9562 final StringArgument aliasArgument = 9563 subCommandParser.getStringArgument("alias"); 9564 final String alias = aliasArgument.getValue(); 9565 9566 final String keystoreType; 9567 final File keystorePath = getKeystorePath(); 9568 try 9569 { 9570 keystoreType = inferKeystoreType(keystorePath); 9571 } 9572 catch (final LDAPException le) 9573 { 9574 Debug.debugException(le); 9575 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9576 return le.getResultCode(); 9577 } 9578 9579 final char[] keystorePassword; 9580 try 9581 { 9582 keystorePassword = getKeystorePassword(keystorePath); 9583 } 9584 catch (final LDAPException le) 9585 { 9586 Debug.debugException(le); 9587 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9588 return le.getResultCode(); 9589 } 9590 9591 9592 // Get the keystore. 9593 final KeyStore keystore; 9594 try 9595 { 9596 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 9597 } 9598 catch (final LDAPException le) 9599 { 9600 Debug.debugException(le); 9601 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9602 return le.getResultCode(); 9603 } 9604 9605 9606 // Make sure that the specified entry exists in the keystore and is 9607 // associated with a certificate chain and a private key. 9608 final X509Certificate[] chain; 9609 if (hasKeyAlias(keystore, alias)) 9610 { 9611 try 9612 { 9613 final Certificate[] genericChain = keystore.getCertificateChain(alias); 9614 Validator.ensureTrue((genericChain.length > 0), 9615 "ERROR: The keystore has a private key entry for alias '" + 9616 alias + "', but the associated certificate chain is empty."); 9617 9618 chain = new X509Certificate[genericChain.length]; 9619 for (int i=0; i < genericChain.length; i++) 9620 { 9621 chain[i] = new X509Certificate(genericChain[i].getEncoded()); 9622 } 9623 9624 out(); 9625 wrapOut(0, WRAP_COLUMN, 9626 INFO_MANAGE_CERTS_CHECK_USABILITY_GOT_CHAIN.get(alias)); 9627 9628 for (final X509Certificate c : chain) 9629 { 9630 out(); 9631 printCertificate(c, "", false); 9632 } 9633 } 9634 catch (final Exception e) 9635 { 9636 Debug.debugException(e); 9637 wrapErr(0, WRAP_COLUMN, 9638 ERR_MANAGE_CERTS_CHECK_USABILITY_CANNOT_GET_CHAIN.get(alias)); 9639 e.printStackTrace(getErr()); 9640 return ResultCode.LOCAL_ERROR; 9641 } 9642 } 9643 else if (hasCertificateAlias(keystore, alias)) 9644 { 9645 wrapErr(0, WRAP_COLUMN, 9646 ERR_MANAGE_CERTS_CHECK_USABILITY_NO_PRIVATE_KEY.get(alias)); 9647 return ResultCode.PARAM_ERROR; 9648 } 9649 else 9650 { 9651 wrapErr(0, WRAP_COLUMN, 9652 ERR_MANAGE_CERTS_CHECK_USABILITY_NO_SUCH_ALIAS.get(alias)); 9653 return ResultCode.PARAM_ERROR; 9654 } 9655 9656 9657 // Check to see if the certificate is self-signed. If so, then that's a 9658 // warning. If not, then make sure that the chain is complete and that each 9659 // subsequent certificate is the issuer of the previous. 9660 int numWarnings = 0; 9661 int numErrors = 0; 9662 if (chain[0].isSelfSigned()) 9663 { 9664 err(); 9665 wrapErr(0, WRAP_COLUMN, 9666 WARN_MANAGE_CERTS_CHECK_USABILITY_CERT_IS_SELF_SIGNED.get( 9667 chain[0].getSubjectDN())); 9668 numWarnings++; 9669 } 9670 else if ((chain.length == 1) || (! chain[chain.length - 1].isSelfSigned())) 9671 { 9672 err(); 9673 wrapErr(0, WRAP_COLUMN, 9674 ERR_MANAGE_CERTS_CHECK_USABILITY_END_OF_CHAIN_NOT_SELF_SIGNED.get( 9675 alias)); 9676 numErrors++; 9677 } 9678 else 9679 { 9680 boolean chainError = false; 9681 final StringBuilder nonMatchReason = new StringBuilder(); 9682 for (int i=1; i < chain.length; i++) 9683 { 9684 if (! chain[i].isIssuerFor(chain[i-1], nonMatchReason)) 9685 { 9686 err(); 9687 wrapErr(0, WRAP_COLUMN, 9688 ERR_MANAGE_CERTS_CHECK_USABILITY_CHAIN_ISSUER_MISMATCH.get( 9689 alias, chain[i].getSubjectDN(), chain[i-1].getSubjectDN(), 9690 nonMatchReason)); 9691 numErrors++; 9692 chainError = true; 9693 } 9694 } 9695 9696 if (! chainError) 9697 { 9698 out(); 9699 wrapOut(0, WRAP_COLUMN, 9700 INFO_MANAGE_CERTS_CHECK_USABILITY_CHAIN_COMPLETE.get()); 9701 } 9702 } 9703 9704 9705 // If there are multiple certificates in the chain, and if the last 9706 // certificate in the chain is self-signed, then check to see if it is 9707 // contained in the JVM-default trust manager. If it isn't, then we'll 9708 // display a notice, but we won't consider it a warning in and of itself. 9709 if ((chain.length > 1) && chain[chain.length-1].isSelfSigned()) 9710 { 9711 final X509Certificate caCert = chain[chain.length-1]; 9712 9713 try 9714 { 9715 final String jvmDefaultTrustStoreType = 9716 inferKeystoreType(JVM_DEFAULT_CACERTS_FILE); 9717 final KeyStore jvmDefaultTrustStore = 9718 CryptoHelper.getKeyStore(jvmDefaultTrustStoreType); 9719 try (FileInputStream inputStream = 9720 new FileInputStream(JVM_DEFAULT_CACERTS_FILE)) 9721 { 9722 jvmDefaultTrustStore.load(inputStream, null); 9723 } 9724 9725 boolean found = false; 9726 final Enumeration<String> aliases = jvmDefaultTrustStore.aliases(); 9727 while (aliases.hasMoreElements()) 9728 { 9729 final String jvmDefaultCertAlias = aliases.nextElement(); 9730 if (jvmDefaultTrustStore.isCertificateEntry(jvmDefaultCertAlias)) 9731 { 9732 final Certificate c = 9733 jvmDefaultTrustStore.getCertificate(jvmDefaultCertAlias); 9734 final X509Certificate xc = new X509Certificate(c.getEncoded()); 9735 if ((caCert.getSubjectDN().equals(xc.getSubjectDN())) && 9736 Arrays.equals(caCert.getSignatureValue().getBits(), 9737 xc.getSignatureValue().getBits())) 9738 { 9739 found = true; 9740 break; 9741 } 9742 } 9743 } 9744 9745 if (found) 9746 { 9747 out(); 9748 wrapOut(0, WRAP_COLUMN, 9749 INFO_MANAGE_CERTS_CHECK_USABILITY_CA_TRUSTED_OK.get( 9750 caCert.getSubjectDN())); 9751 } 9752 else 9753 { 9754 out(); 9755 wrapOut(0, WRAP_COLUMN, 9756 INFO_MANAGE_CERTS_CHECK_USABILITY_CA_NOT_IN_JVM_DEFAULT_TS.get( 9757 caCert.getSubjectDN())); 9758 } 9759 } 9760 catch (final Exception e) 9761 { 9762 Debug.debugException(e); 9763 err(); 9764 wrapErr(0, WRAP_COLUMN, 9765 WARN_MANAGE_CERTS_CHECK_USABILITY_CHECK_CA_IN_TS_ERROR.get( 9766 caCert.getSubjectDN(), StaticUtils.getExceptionMessage(e))); 9767 numWarnings++; 9768 } 9769 } 9770 9771 9772 // Make sure that the signature is valid for each certificate in the 9773 // chain. If any certificate has an invalid signature, then that's an 9774 // error. 9775 for (int i=0; i < chain.length; i++) 9776 { 9777 final X509Certificate c = chain[i]; 9778 9779 try 9780 { 9781 if (c.isSelfSigned()) 9782 { 9783 c.verifySignature(null); 9784 } 9785 else if ((i + 1) < chain.length) 9786 { 9787 c.verifySignature(chain[i+1]); 9788 } 9789 9790 out(); 9791 wrapOut(0, WRAP_COLUMN, 9792 INFO_MANAGE_CERTS_CHECK_USABILITY_CERT_SIGNATURE_VALID.get( 9793 c.getSubjectDN())); 9794 } 9795 catch (final CertException ce) 9796 { 9797 err(); 9798 wrapErr(0, WRAP_COLUMN, ce.getMessage()); 9799 numErrors++; 9800 } 9801 } 9802 9803 9804 // Check the validity window for each certificate in the chain. If any of 9805 // them is expired or not yet valid, then that's an error. If any of them 9806 // will expire in the near future, then that's a warning. 9807 final long currentTime = System.currentTimeMillis(); 9808 final long thirtyDaysFromNow = 9809 currentTime + (30L * 24L * 60L * 60L * 1000L); 9810 for (int i=0; i < chain.length; i++) 9811 { 9812 final X509Certificate c = chain[i]; 9813 if (c.getNotBeforeTime() > currentTime) 9814 { 9815 err(); 9816 if (i == 0) 9817 { 9818 wrapErr(0, WRAP_COLUMN, 9819 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_NOT_YET_VALID.get( 9820 c.getSubjectDN(), formatDateAndTime(c.getNotBeforeDate()))); 9821 } 9822 else 9823 { 9824 wrapErr(0, WRAP_COLUMN, 9825 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_NOT_YET_VALID.get( 9826 c.getSubjectDN(), formatDateAndTime(c.getNotBeforeDate()))); 9827 } 9828 9829 numErrors++; 9830 } 9831 else if (c.getNotAfterTime() < currentTime) 9832 { 9833 err(); 9834 if (i == 0) 9835 { 9836 wrapErr(0, WRAP_COLUMN, 9837 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_EXPIRED.get( 9838 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9839 } 9840 else 9841 { 9842 wrapErr(0, WRAP_COLUMN, 9843 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_EXPIRED.get( 9844 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9845 } 9846 9847 numErrors++; 9848 } 9849 else if (c.getNotAfterTime() < thirtyDaysFromNow) 9850 { 9851 err(); 9852 if (i == 0) 9853 { 9854 wrapErr(0, WRAP_COLUMN, 9855 WARN_MANAGE_CERTS_CHECK_USABILITY_END_CERT_NEAR_EXPIRATION.get( 9856 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9857 } 9858 else 9859 { 9860 wrapErr(0, WRAP_COLUMN, 9861 WARN_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_NEAR_EXPIRATION. 9862 get(c.getSubjectDN(), 9863 formatDateAndTime(c.getNotAfterDate()))); 9864 } 9865 9866 numWarnings++; 9867 } 9868 else 9869 { 9870 if (i == 0) 9871 { 9872 out(); 9873 wrapOut(0, WRAP_COLUMN, 9874 INFO_MANAGE_CERTS_CHECK_USABILITY_END_CERT_VALIDITY_OK.get( 9875 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9876 } 9877 else 9878 { 9879 out(); 9880 wrapOut(0, WRAP_COLUMN, 9881 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_VALIDITY_OK.get( 9882 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9883 } 9884 } 9885 } 9886 9887 9888 // Look at all of the extensions for all of the certificates and perform the 9889 // following validation: 9890 // - If the certificate at the head of the chain has an extended key usage 9891 // extension, then make sure it includes the serverAuth usage. If it 9892 // does not include an extended key usage extension, then warn that it 9893 // should. 9894 // - If any of the issuer certificates has a basic constraints extension, 9895 // then make sure it indicates that the associated certificate is a 9896 // certification authority. Further, if it has a path length constraint, 9897 // then make sure the chain does not exceed that length. If any issuer 9898 // certificate does not have a basic constraints extension, then warn that 9899 // it should. 9900 // - If any of the issuer certificates has a key usage extension, then 9901 // make sure it has the certSign usage. If any issuer certificate does 9902 // not have a key usage extension, then warn that it should. 9903 // - TODO: If any certificate has a CRL distribution points extension, then 9904 // retrieve the CRL and make sure the certificate hasn't been revoked. 9905 // - TODO: If any certificate has an authority information access 9906 // extension that points to an OCSP service, then consult that service to 9907 // determine whether the certificate has been revoked. 9908 for (int i=0; i < chain.length; i++) 9909 { 9910 boolean basicConstraintsFound = false; 9911 boolean extendedKeyUsageFound = false; 9912 boolean keyUsageFound = false; 9913 final X509Certificate c = chain[i]; 9914 for (final X509CertificateExtension extension : c.getExtensions()) 9915 { 9916 if (extension instanceof ExtendedKeyUsageExtension) 9917 { 9918 extendedKeyUsageFound = true; 9919 if (i == 0) 9920 { 9921 final ExtendedKeyUsageExtension e = 9922 (ExtendedKeyUsageExtension) extension; 9923 if (!e.getKeyPurposeIDs().contains( 9924 ExtendedKeyUsageID.TLS_SERVER_AUTHENTICATION.getOID())) 9925 { 9926 err(); 9927 wrapErr(0, WRAP_COLUMN, 9928 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_BAD_EKU.get( 9929 c.getSubjectDN())); 9930 numErrors++; 9931 } 9932 else 9933 { 9934 out(); 9935 wrapOut(0, WRAP_COLUMN, 9936 INFO_MANAGE_CERTS_CHECK_USABILITY_END_CERT_GOOD_EKU.get( 9937 c.getSubjectDN())); 9938 } 9939 } 9940 } 9941 else if (extension instanceof BasicConstraintsExtension) 9942 { 9943 basicConstraintsFound = true; 9944 if (i > 0) 9945 { 9946 final BasicConstraintsExtension e = 9947 (BasicConstraintsExtension) extension; 9948 if (!e.isCA()) 9949 { 9950 err(); 9951 wrapErr(0, WRAP_COLUMN, 9952 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_BAD_BC_CA.get( 9953 c.getSubjectDN())); 9954 numErrors++; 9955 } 9956 else if ((e.getPathLengthConstraint() != null) && 9957 ((i - 1) > e.getPathLengthConstraint())) 9958 { 9959 err(); 9960 wrapErr(0, WRAP_COLUMN, 9961 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_BAD_BC_LENGTH. 9962 get(c.getSubjectDN(), e.getPathLengthConstraint(), 9963 chain[0].getSubjectDN(), (i-1))); 9964 numErrors++; 9965 } 9966 else 9967 { 9968 out(); 9969 wrapOut(0, WRAP_COLUMN, 9970 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_GOOD_BC.get( 9971 c.getSubjectDN())); 9972 } 9973 } 9974 } 9975 else if (extension instanceof KeyUsageExtension) 9976 { 9977 keyUsageFound = true; 9978 if (i > 0) 9979 { 9980 final KeyUsageExtension e = (KeyUsageExtension) extension; 9981 if (! e.isKeyCertSignBitSet()) 9982 { 9983 err(); 9984 wrapErr(0, WRAP_COLUMN, 9985 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_NO_CERT_SIGN_KU.get( 9986 c.getSubjectDN())); 9987 numErrors++; 9988 } 9989 else 9990 { 9991 out(); 9992 wrapOut(0, WRAP_COLUMN, 9993 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_GOOD_KU.get( 9994 c.getSubjectDN())); 9995 } 9996 } 9997 } 9998 } 9999 10000 if (i == 0) 10001 { 10002 if (! extendedKeyUsageFound) 10003 { 10004 err(); 10005 wrapErr(0, WRAP_COLUMN, 10006 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_EKU.get( 10007 c.getSubjectDN())); 10008 numWarnings++; 10009 } 10010 } 10011 else 10012 { 10013 if (! basicConstraintsFound) 10014 { 10015 err(); 10016 wrapErr(0, WRAP_COLUMN, 10017 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_BC.get( 10018 c.getSubjectDN())); 10019 numWarnings++; 10020 } 10021 10022 if (! keyUsageFound) 10023 { 10024 err(); 10025 wrapErr(0, WRAP_COLUMN, 10026 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_KU.get( 10027 c.getSubjectDN())); 10028 numWarnings++; 10029 } 10030 } 10031 } 10032 10033 10034 // Make sure that none of the certificates has a signature algorithm that 10035 // uses MD5 or SHA-1. If it uses an unrecognized signature algorithm, then 10036 // that's a warning. 10037 boolean isIssuer = false; 10038 final BooleanArgument ignoreSHA1WarningArg = 10039 subCommandParser.getBooleanArgument( 10040 "allow-sha-1-signature-for-issuer-certificates"); 10041 final boolean ignoreSHA1SignatureWarningForIssuerCertificates = 10042 ((ignoreSHA1WarningArg != null) && ignoreSHA1WarningArg.isPresent()); 10043 for (final X509Certificate c : chain) 10044 { 10045 final OID signatureAlgorithmOID = c.getSignatureAlgorithmOID(); 10046 final SignatureAlgorithmIdentifier id = 10047 SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID); 10048 if (id == null) 10049 { 10050 err(); 10051 wrapErr(0, WRAP_COLUMN, 10052 WARN_MANAGE_CERTS_CHECK_USABILITY_UNKNOWN_SIG_ALG.get( 10053 c.getSubjectDN(), signatureAlgorithmOID)); 10054 numWarnings++; 10055 } 10056 else 10057 { 10058 switch (id) 10059 { 10060 case MD2_WITH_RSA: 10061 case MD5_WITH_RSA: 10062 err(); 10063 wrapErr(0, WRAP_COLUMN, 10064 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_SIG_ALG.get( 10065 c.getSubjectDN(), id.getUserFriendlyName())); 10066 numErrors++; 10067 break; 10068 10069 case SHA_1_WITH_RSA: 10070 case SHA_1_WITH_DSA: 10071 case SHA_1_WITH_ECDSA: 10072 if (isIssuer && ignoreSHA1SignatureWarningForIssuerCertificates) 10073 { 10074 err(); 10075 wrapErr(0, WRAP_COLUMN, 10076 WARN_MANAGE_CERTS_CHECK_USABILITY_ISSUER_WITH_SHA1_SIG.get( 10077 c.getSubjectDN(), id.getUserFriendlyName(), 10078 ignoreSHA1WarningArg.getIdentifierString())); 10079 } 10080 else 10081 { 10082 err(); 10083 wrapErr(0, WRAP_COLUMN, 10084 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_SIG_ALG.get( 10085 c.getSubjectDN(), id.getUserFriendlyName())); 10086 numErrors++; 10087 } 10088 break; 10089 10090 case SHA_224_WITH_RSA: 10091 case SHA_224_WITH_DSA: 10092 case SHA_224_WITH_ECDSA: 10093 case SHA_256_WITH_RSA: 10094 case SHA_256_WITH_DSA: 10095 case SHA_256_WITH_ECDSA: 10096 case SHA_384_WITH_RSA: 10097 case SHA_384_WITH_ECDSA: 10098 case SHA_512_WITH_RSA: 10099 case SHA_512_WITH_ECDSA: 10100 out(); 10101 wrapOut(0, WRAP_COLUMN, 10102 INFO_MANAGE_CERTS_CHECK_USABILITY_SIG_ALG_OK.get( 10103 c.getSubjectDN(), id.getUserFriendlyName())); 10104 break; 10105 } 10106 } 10107 10108 isIssuer = true; 10109 } 10110 10111 10112 // Make sure that none of the certificates that uses the RSA key algorithm 10113 // has a public modulus size smaller than 2048 bits. 10114 for (final X509Certificate c : chain) 10115 { 10116 if ((c.getDecodedPublicKey() != null) && 10117 (c.getDecodedPublicKey() instanceof RSAPublicKey)) 10118 { 10119 final RSAPublicKey rsaPublicKey = 10120 (RSAPublicKey) c.getDecodedPublicKey(); 10121 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10122 int modulusSizeBits = modulusBytes.length * 8; 10123 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10124 { 10125 modulusSizeBits -= 8; 10126 } 10127 10128 if (modulusSizeBits < 2048) 10129 { 10130 err(); 10131 wrapErr(0, WRAP_COLUMN, 10132 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_RSA_MODULUS.get( 10133 c.getSubjectDN(), modulusSizeBits)); 10134 numErrors++; 10135 } 10136 else 10137 { 10138 out(); 10139 wrapOut(0, WRAP_COLUMN, 10140 INFO_MANAGE_CERTS_CHECK_USABILITY_RSA_MODULUS_OK.get( 10141 c.getSubjectDN(), modulusSizeBits)); 10142 } 10143 } 10144 } 10145 10146 10147 switch (numErrors) 10148 { 10149 case 0: 10150 break; 10151 case 1: 10152 err(); 10153 wrapErr(0, WRAP_COLUMN, 10154 ERR_MANAGE_CERTS_CHECK_USABILITY_ONE_ERROR.get()); 10155 return ResultCode.PARAM_ERROR; 10156 default: 10157 err(); 10158 wrapErr(0, WRAP_COLUMN, 10159 ERR_MANAGE_CERTS_CHECK_USABILITY_MULTIPLE_ERRORS.get(numErrors)); 10160 return ResultCode.PARAM_ERROR; 10161 } 10162 10163 switch (numWarnings) 10164 { 10165 case 0: 10166 out(); 10167 wrapOut(0, WRAP_COLUMN, 10168 INFO_MANAGE_CERTS_CHECK_USABILITY_NO_ERRORS_OR_WARNINGS.get()); 10169 return ResultCode.SUCCESS; 10170 case 1: 10171 err(); 10172 wrapErr(0, WRAP_COLUMN, 10173 ERR_MANAGE_CERTS_CHECK_USABILITY_ONE_WARNING.get()); 10174 return ResultCode.PARAM_ERROR; 10175 default: 10176 err(); 10177 wrapErr(0, WRAP_COLUMN, 10178 ERR_MANAGE_CERTS_CHECK_USABILITY_MULTIPLE_WARNINGS.get( 10179 numWarnings)); 10180 return ResultCode.PARAM_ERROR; 10181 } 10182 } 10183 10184 10185 10186 /** 10187 * Performs the necessary processing for the display-certificate-file 10188 * subcommand. 10189 * 10190 * @return A result code that indicates whether the processing completed 10191 * successfully. 10192 */ 10193 @NotNull() 10194 private ResultCode doDisplayCertificateFile() 10195 { 10196 // Get the values of a number of configured arguments. 10197 final FileArgument certificateFileArgument = 10198 subCommandParser.getFileArgument("certificate-file"); 10199 final File certificateFile = certificateFileArgument.getValue(); 10200 10201 final BooleanArgument verboseArgument = 10202 subCommandParser.getBooleanArgument("verbose"); 10203 final boolean verbose = 10204 ((verboseArgument != null) && verboseArgument.isPresent()); 10205 10206 final BooleanArgument displayKeytoolCommandArgument = 10207 subCommandParser.getBooleanArgument("display-keytool-command"); 10208 if ((displayKeytoolCommandArgument != null) && 10209 displayKeytoolCommandArgument.isPresent()) 10210 { 10211 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 10212 keytoolArgs.add("-printcert"); 10213 keytoolArgs.add("-file"); 10214 keytoolArgs.add(certificateFile.getAbsolutePath()); 10215 10216 if (verbose) 10217 { 10218 keytoolArgs.add("-v"); 10219 } 10220 10221 displayKeytoolCommand(keytoolArgs); 10222 } 10223 10224 10225 // Read the certificates from the specified file. 10226 final List<X509Certificate> certificates; 10227 try 10228 { 10229 certificates = readCertificatesFromFile(certificateFile); 10230 } 10231 catch (final LDAPException le) 10232 { 10233 Debug.debugException(le); 10234 wrapErr(0, WRAP_COLUMN, le.getMessage()); 10235 return le.getResultCode(); 10236 } 10237 10238 10239 // If there aren't any certificates in the file, print that. 10240 if (certificates.isEmpty()) 10241 { 10242 wrapOut(0, WRAP_COLUMN, INFO_MANAGE_CERTS_DISPLAY_CERT_NO_CERTS.get( 10243 certificateFile.getAbsolutePath())); 10244 } 10245 else 10246 { 10247 for (final X509Certificate c : certificates) 10248 { 10249 out(); 10250 printCertificate(c, "", verbose); 10251 } 10252 } 10253 10254 return ResultCode.SUCCESS; 10255 } 10256 10257 10258 10259 /** 10260 * Performs the necessary processing for the 10261 * display-certificate-signing-request-file subcommand. 10262 * 10263 * @return A result code that indicates whether the processing completed 10264 * successfully. 10265 */ 10266 @NotNull() 10267 private ResultCode doDisplayCertificateSigningRequestFile() 10268 { 10269 // Get the values of a number of configured arguments. 10270 final FileArgument csrFileArgument = 10271 subCommandParser.getFileArgument("certificate-signing-request-file"); 10272 final File csrFile = csrFileArgument.getValue(); 10273 10274 final BooleanArgument verboseArgument = 10275 subCommandParser.getBooleanArgument("verbose"); 10276 final boolean verbose = 10277 ((verboseArgument != null) && verboseArgument.isPresent()); 10278 10279 final BooleanArgument displayKeytoolCommandArgument = 10280 subCommandParser.getBooleanArgument("display-keytool-command"); 10281 if ((displayKeytoolCommandArgument != null) && 10282 displayKeytoolCommandArgument.isPresent()) 10283 { 10284 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 10285 keytoolArgs.add("-printcertreq"); 10286 keytoolArgs.add("-file"); 10287 keytoolArgs.add(csrFile.getAbsolutePath()); 10288 keytoolArgs.add("-v"); 10289 10290 displayKeytoolCommand(keytoolArgs); 10291 } 10292 10293 10294 // Read the certificate signing request from the specified file. 10295 final PKCS10CertificateSigningRequest csr; 10296 try 10297 { 10298 csr = readCertificateSigningRequestFromFile(csrFile); 10299 } 10300 catch (final LDAPException le) 10301 { 10302 Debug.debugException(le); 10303 wrapErr(0, WRAP_COLUMN, le.getMessage()); 10304 return le.getResultCode(); 10305 } 10306 10307 out(); 10308 printCertificateSigningRequest(csr, verbose, ""); 10309 10310 return ResultCode.SUCCESS; 10311 } 10312 10313 10314 10315 /** 10316 * Prints a string representation of the provided certificate to standard 10317 * output. 10318 * 10319 * @param certificate The certificate to be printed. 10320 * @param indent The string to place at the beginning of each line to 10321 * indent that line. 10322 * @param verbose Indicates whether to display verbose information about 10323 * the certificate. 10324 */ 10325 private void printCertificate(@NotNull final X509Certificate certificate, 10326 @NotNull final String indent, 10327 final boolean verbose) 10328 { 10329 if (verbose) 10330 { 10331 out(indent + 10332 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VERSION.get( 10333 certificate.getVersion().getName())); 10334 } 10335 10336 out(indent + 10337 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_DN.get( 10338 certificate.getSubjectDN())); 10339 out(indent + 10340 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ISSUER_DN.get( 10341 certificate.getIssuerDN())); 10342 10343 if (verbose) 10344 { 10345 out(indent + 10346 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SERIAL_NUMBER.get( 10347 toColonDelimitedHex( 10348 certificate.getSerialNumber().toByteArray()))); 10349 } 10350 10351 out(indent + 10352 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_START.get( 10353 formatDateAndTime(certificate.getNotBeforeDate()))); 10354 out(indent + 10355 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_END.get( 10356 formatDateAndTime(certificate.getNotAfterDate()))); 10357 10358 final long currentTime = System.currentTimeMillis(); 10359 if (currentTime < certificate.getNotBeforeTime()) 10360 { 10361 out(indent + 10362 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_NOT_YET_VALID. 10363 get()); 10364 } 10365 else if (currentTime > certificate.getNotAfterTime()) 10366 { 10367 out(indent + 10368 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_EXPIRED.get()); 10369 } 10370 else 10371 { 10372 out(indent + 10373 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_VALID.get()); 10374 } 10375 10376 out(indent + 10377 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_ALG.get( 10378 certificate.getSignatureAlgorithmNameOrOID())); 10379 if (verbose) 10380 { 10381 String signatureString; 10382 try 10383 { 10384 signatureString = 10385 toColonDelimitedHex(certificate.getSignatureValue().getBytes()); 10386 } 10387 catch (final Exception e) 10388 { 10389 Debug.debugException(e); 10390 signatureString = certificate.getSignatureValue().toString(); 10391 } 10392 out(indent + 10393 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_VALUE.get()); 10394 for (final String line : StaticUtils.wrapLine(signatureString, 78)) 10395 { 10396 out(indent + " " + line); 10397 } 10398 } 10399 10400 final String pkAlg; 10401 final String pkSummary = getPublicKeySummary( 10402 certificate.getPublicKeyAlgorithmOID(), 10403 certificate.getDecodedPublicKey(), 10404 certificate.getPublicKeyAlgorithmParameters()); 10405 if (pkSummary == null) 10406 { 10407 pkAlg = certificate.getPublicKeyAlgorithmNameOrOID(); 10408 } 10409 else 10410 { 10411 pkAlg = certificate.getPublicKeyAlgorithmNameOrOID() + " (" + 10412 pkSummary + ')'; 10413 } 10414 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_PK_ALG.get(pkAlg)); 10415 10416 if (verbose) 10417 { 10418 printPublicKey(certificate.getEncodedPublicKey(), 10419 certificate.getDecodedPublicKey(), 10420 certificate.getPublicKeyAlgorithmParameters(), indent); 10421 10422 if (certificate.getSubjectUniqueID() != null) 10423 { 10424 String subjectUniqueID; 10425 try 10426 { 10427 subjectUniqueID = toColonDelimitedHex( 10428 certificate.getSubjectUniqueID().getBytes()); 10429 } 10430 catch (final Exception e) 10431 { 10432 Debug.debugException(e); 10433 subjectUniqueID = certificate.getSubjectUniqueID().toString(); 10434 } 10435 10436 out(indent + 10437 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_UNIQUE_ID.get()); 10438 for (final String line : StaticUtils.wrapLine(subjectUniqueID, 78)) 10439 { 10440 out(indent + " " + line); 10441 } 10442 } 10443 10444 if (certificate.getIssuerUniqueID() != null) 10445 { 10446 String issuerUniqueID; 10447 try 10448 { 10449 issuerUniqueID = toColonDelimitedHex( 10450 certificate.getIssuerUniqueID().getBytes()); 10451 } 10452 catch (final Exception e) 10453 { 10454 Debug.debugException(e); 10455 issuerUniqueID = certificate.getIssuerUniqueID().toString(); 10456 } 10457 10458 out(indent + 10459 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ISSUER_UNIQUE_ID.get()); 10460 for (final String line : StaticUtils.wrapLine(issuerUniqueID, 78)) 10461 { 10462 out(indent + " " + line); 10463 } 10464 } 10465 10466 printExtensions(certificate.getExtensions(), indent); 10467 } 10468 10469 try 10470 { 10471 out(indent + 10472 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_FINGERPRINT.get("SHA-1", 10473 toColonDelimitedHex(certificate.getSHA1Fingerprint()))); 10474 } 10475 catch (final Exception e) 10476 { 10477 Debug.debugException(e); 10478 } 10479 10480 try 10481 { 10482 out(indent + 10483 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_FINGERPRINT.get("SHA-256", 10484 toColonDelimitedHex(certificate.getSHA256Fingerprint()))); 10485 } 10486 catch (final Exception e) 10487 { 10488 Debug.debugException(e); 10489 } 10490 } 10491 10492 10493 10494 /** 10495 * Prints a string representation of the provided certificate signing request 10496 * to standard output. 10497 * 10498 * @param csr The certificate signing request to be printed. 10499 * @param verbose Indicates whether to display verbose information about 10500 * the contents of the request. 10501 * @param indent The string to place at the beginning of each line to 10502 * indent that line. 10503 */ 10504 private void printCertificateSigningRequest( 10505 @NotNull final PKCS10CertificateSigningRequest csr, 10506 final boolean verbose, @NotNull final String indent) 10507 { 10508 out(indent + 10509 INFO_MANAGE_CERTS_PRINT_CSR_LABEL_VERSION.get( 10510 csr.getVersion().getName())); 10511 out(indent + 10512 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_DN.get( 10513 csr.getSubjectDN())); 10514 out(indent + 10515 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_ALG.get( 10516 csr.getSignatureAlgorithmNameOrOID())); 10517 10518 if (verbose) 10519 { 10520 String signatureString; 10521 try 10522 { 10523 signatureString = 10524 toColonDelimitedHex(csr.getSignatureValue().getBytes()); 10525 } 10526 catch (final Exception e) 10527 { 10528 Debug.debugException(e); 10529 signatureString = csr.getSignatureValue().toString(); 10530 } 10531 out(indent + 10532 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_VALUE.get()); 10533 for (final String line : StaticUtils.wrapLine(signatureString, 78)) 10534 { 10535 out(indent + " " + line); 10536 } 10537 } 10538 10539 final String pkAlg; 10540 final String pkSummary = getPublicKeySummary(csr.getPublicKeyAlgorithmOID(), 10541 csr.getDecodedPublicKey(), csr.getPublicKeyAlgorithmParameters()); 10542 if (pkSummary == null) 10543 { 10544 pkAlg = csr.getPublicKeyAlgorithmNameOrOID(); 10545 } 10546 else 10547 { 10548 pkAlg = csr.getPublicKeyAlgorithmNameOrOID() + " (" + 10549 pkSummary + ')'; 10550 } 10551 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_PK_ALG.get(pkAlg)); 10552 10553 if (verbose) 10554 { 10555 printPublicKey(csr.getEncodedPublicKey(), csr.getDecodedPublicKey(), 10556 csr.getPublicKeyAlgorithmParameters(), indent); 10557 printExtensions(csr.getExtensions(), indent); 10558 } 10559 } 10560 10561 10562 10563 /** 10564 * Prints information about the provided public key. 10565 * 10566 * @param encodedPublicKey The encoded representation of the public key. 10567 * This must not be {@code null}. 10568 * @param decodedPublicKey The decoded representation of the public key, if 10569 * available. 10570 * @param parameters The public key algorithm parameters, if any. 10571 * @param indent The string to place at the beginning of each 10572 * line to indent that line. 10573 */ 10574 private void printPublicKey(@NotNull final ASN1BitString encodedPublicKey, 10575 @Nullable final DecodedPublicKey decodedPublicKey, 10576 @Nullable final ASN1Element parameters, 10577 @NotNull final String indent) 10578 { 10579 if (decodedPublicKey == null) 10580 { 10581 String pkString; 10582 try 10583 { 10584 pkString = toColonDelimitedHex(encodedPublicKey.getBytes()); 10585 } 10586 catch (final Exception e) 10587 { 10588 Debug.debugException(e); 10589 pkString = encodedPublicKey.toString(); 10590 } 10591 10592 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ENCODED_PK.get()); 10593 for (final String line : StaticUtils.wrapLine(pkString, 78)) 10594 { 10595 out(indent + " " + line); 10596 } 10597 10598 return; 10599 } 10600 10601 if (decodedPublicKey instanceof RSAPublicKey) 10602 { 10603 final RSAPublicKey rsaPublicKey = (RSAPublicKey) decodedPublicKey; 10604 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10605 10606 int modulusSizeBits = modulusBytes.length * 8; 10607 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10608 { 10609 modulusSizeBits -= 8; 10610 } 10611 10612 out(indent + 10613 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_RSA_MODULUS.get( 10614 modulusSizeBits)); 10615 final String modulusHex = toColonDelimitedHex(modulusBytes); 10616 for (final String line : StaticUtils.wrapLine(modulusHex, 78)) 10617 { 10618 out(indent + " " + line); 10619 } 10620 10621 out(indent + 10622 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_RSA_EXPONENT.get( 10623 toColonDelimitedHex( 10624 rsaPublicKey.getPublicExponent().toByteArray()))); 10625 } 10626 else if (decodedPublicKey instanceof EllipticCurvePublicKey) 10627 { 10628 final EllipticCurvePublicKey ecPublicKey = 10629 (EllipticCurvePublicKey) decodedPublicKey; 10630 10631 out(indent + 10632 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_IS_COMPRESSED.get( 10633 String.valueOf(ecPublicKey.usesCompressedForm()))); 10634 out(indent + 10635 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_X.get( 10636 String.valueOf(ecPublicKey.getXCoordinate()))); 10637 if (ecPublicKey.getYCoordinate() == null) 10638 { 10639 out(indent + 10640 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_Y_IS_EVEN.get( 10641 String.valueOf(ecPublicKey.yCoordinateIsEven()))); 10642 } 10643 else 10644 { 10645 out(indent + 10646 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_Y.get( 10647 String.valueOf(ecPublicKey.getYCoordinate()))); 10648 } 10649 } 10650 } 10651 10652 10653 10654 /** 10655 * Retrieves a short summary of the provided public key, if available. For 10656 * RSA keys, this will be the modulus size in bits. For elliptic curve keys, 10657 * this will be the named curve, if available. 10658 * 10659 * @param publicKeyAlgorithmOID The OID that identifies the type of public 10660 * key. 10661 * @param publicKey The decoded public key. This may be 10662 * {@code null} if the decoded public key is 10663 * not available. 10664 * @param parameters The encoded public key algorithm parameters. 10665 * This may be {@code null} if no public key 10666 * algorithm parameters are available. 10667 * 10668 * @return A short summary of the provided public key, or {@code null} if 10669 * no summary is available. 10670 */ 10671 @NotNull() 10672 private static String getPublicKeySummary( 10673 @NotNull final OID publicKeyAlgorithmOID, 10674 @Nullable final DecodedPublicKey publicKey, 10675 @Nullable final ASN1Element parameters) 10676 { 10677 if (publicKey instanceof RSAPublicKey) 10678 { 10679 final RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; 10680 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10681 10682 int modulusSizeBits = modulusBytes.length * 8; 10683 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10684 { 10685 modulusSizeBits -= 8; 10686 } 10687 10688 return INFO_MANAGE_CERTS_GET_PK_SUMMARY_RSA_MODULUS_SIZE.get( 10689 modulusSizeBits); 10690 } 10691 else if ((parameters != null) && 10692 publicKeyAlgorithmOID.equals(PublicKeyAlgorithmIdentifier.EC.getOID())) 10693 { 10694 try 10695 { 10696 final OID namedCurveOID = 10697 parameters.decodeAsObjectIdentifier().getOID(); 10698 return NamedCurve.getNameOrOID(namedCurveOID); 10699 } 10700 catch (final Exception e) 10701 { 10702 Debug.debugException(e); 10703 } 10704 } 10705 10706 return null; 10707 } 10708 10709 10710 10711 /** 10712 * Prints information about the provided extensions. 10713 * 10714 * @param extensions The list of extensions to be printed. 10715 * @param indent The string to place at the beginning of each line to 10716 * indent that line. 10717 */ 10718 void printExtensions(@NotNull final List<X509CertificateExtension> extensions, 10719 @NotNull final String indent) 10720 { 10721 if (extensions.isEmpty()) 10722 { 10723 return; 10724 } 10725 10726 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXTENSIONS.get()); 10727 for (final X509CertificateExtension extension : extensions) 10728 { 10729 if (extension instanceof AuthorityKeyIdentifierExtension) 10730 { 10731 out(indent + " " + 10732 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_EXT.get()); 10733 out(indent + " " + 10734 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10735 extension.getOID().toString())); 10736 out(indent + " " + 10737 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10738 String.valueOf(extension.isCritical()))); 10739 10740 final AuthorityKeyIdentifierExtension e = 10741 (AuthorityKeyIdentifierExtension) extension; 10742 if (e.getKeyIdentifier() != null) 10743 { 10744 out(indent + " " + 10745 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_ID.get()); 10746 final String idHex = 10747 toColonDelimitedHex(e.getKeyIdentifier().getValue()); 10748 for (final String line : StaticUtils.wrapLine(idHex, 78)) 10749 { 10750 out(indent + " " + line); 10751 } 10752 } 10753 10754 if (e.getAuthorityCertIssuer() != null) 10755 { 10756 out(indent + " " + 10757 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_ISSUER. 10758 get()); 10759 printGeneralNames(e.getAuthorityCertIssuer(), 10760 indent + " "); 10761 } 10762 10763 if (e.getAuthorityCertSerialNumber() != null) 10764 { 10765 out(indent + " " + 10766 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_SERIAL.get( 10767 toColonDelimitedHex(e.getAuthorityCertSerialNumber(). 10768 toByteArray()))); 10769 } 10770 } 10771 else if (extension instanceof BasicConstraintsExtension) 10772 { 10773 out(indent + " " + 10774 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_EXT.get()); 10775 out(indent + " " + 10776 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10777 extension.getOID().toString())); 10778 out(indent + " " + 10779 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10780 String.valueOf(extension.isCritical()))); 10781 10782 final BasicConstraintsExtension e = 10783 (BasicConstraintsExtension) extension; 10784 out(indent + " " + 10785 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_IS_CA.get( 10786 String.valueOf(e.isCA()))); 10787 10788 if (e.getPathLengthConstraint() != null) 10789 { 10790 out(indent + " " + 10791 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_LENGTH.get( 10792 e.getPathLengthConstraint())); 10793 } 10794 } 10795 else if (extension instanceof CRLDistributionPointsExtension) 10796 { 10797 out(indent + " " + 10798 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_EXT.get()); 10799 out(indent + " " + 10800 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10801 extension.getOID().toString())); 10802 out(indent + " " + 10803 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10804 String.valueOf(extension.isCritical()))); 10805 10806 final CRLDistributionPointsExtension crlDPE = 10807 (CRLDistributionPointsExtension) extension; 10808 for (final CRLDistributionPoint dp : 10809 crlDPE.getCRLDistributionPoints()) 10810 { 10811 out(indent + " " + 10812 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_HEADER.get()); 10813 if (dp.getFullName() != null) 10814 { 10815 out(indent + " " + 10816 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_FULL_NAME. 10817 get()); 10818 printGeneralNames(dp.getFullName(), 10819 indent + " "); 10820 } 10821 10822 if (dp.getNameRelativeToCRLIssuer() != null) 10823 { 10824 out(indent + " " + 10825 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_REL_NAME.get( 10826 dp.getNameRelativeToCRLIssuer())); 10827 } 10828 10829 if (! dp.getPotentialRevocationReasons().isEmpty()) 10830 { 10831 out(indent + " " + 10832 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_REASON.get()); 10833 for (final CRLDistributionPointRevocationReason r : 10834 dp.getPotentialRevocationReasons()) 10835 { 10836 out(indent + " " + r.getName()); 10837 } 10838 } 10839 10840 if (dp.getCRLIssuer() != null) 10841 { 10842 out(indent + " " + 10843 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_CRL_ISSUER. 10844 get()); 10845 printGeneralNames(dp.getCRLIssuer(), 10846 indent + " "); 10847 } 10848 } 10849 } 10850 else if (extension instanceof ExtendedKeyUsageExtension) 10851 { 10852 out(indent + " " + 10853 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_EXT.get()); 10854 out(indent + " " + 10855 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10856 extension.getOID().toString())); 10857 out(indent + " " + 10858 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10859 String.valueOf(extension.isCritical()))); 10860 10861 final ExtendedKeyUsageExtension e = 10862 (ExtendedKeyUsageExtension) extension; 10863 for (final OID oid : e.getKeyPurposeIDs()) 10864 { 10865 final ExtendedKeyUsageID id = ExtendedKeyUsageID.forOID(oid); 10866 if (id == null) 10867 { 10868 out(indent + " " + 10869 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_ID.get(oid)); 10870 } 10871 else 10872 { 10873 out(indent + " " + 10874 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_ID.get( 10875 id.getName())); 10876 } 10877 } 10878 } 10879 else if (extension instanceof IssuerAlternativeNameExtension) 10880 { 10881 out(indent + " " + 10882 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IAN_EXT.get()); 10883 out(indent + " " + 10884 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10885 extension.getOID().toString())); 10886 out(indent + " " + 10887 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10888 String.valueOf(extension.isCritical()))); 10889 10890 final IssuerAlternativeNameExtension e = 10891 (IssuerAlternativeNameExtension) extension; 10892 printGeneralNames(e.getGeneralNames(), indent + " "); 10893 } 10894 else if (extension instanceof KeyUsageExtension) 10895 { 10896 out(indent + " " + 10897 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_EXT.get()); 10898 out(indent + " " + 10899 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10900 extension.getOID().toString())); 10901 out(indent + " " + 10902 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10903 String.valueOf(extension.isCritical()))); 10904 10905 out(indent + " " + 10906 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_USAGES.get()); 10907 final KeyUsageExtension kue = (KeyUsageExtension) extension; 10908 if (kue.isDigitalSignatureBitSet()) 10909 { 10910 out(indent + " " + 10911 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DS.get()); 10912 } 10913 10914 if (kue.isNonRepudiationBitSet()) 10915 { 10916 out(indent + " " + 10917 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_NR.get()); 10918 } 10919 10920 if (kue.isKeyEnciphermentBitSet()) 10921 { 10922 out(indent + " " + 10923 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KE.get()); 10924 } 10925 10926 if (kue.isDataEnciphermentBitSet()) 10927 { 10928 out(indent + " " + 10929 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DE.get()); 10930 } 10931 10932 if (kue.isKeyAgreementBitSet()) 10933 { 10934 out(indent + " " + 10935 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KA.get()); 10936 } 10937 10938 if (kue.isKeyCertSignBitSet()) 10939 { 10940 out(indent + " " + 10941 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KCS.get()); 10942 } 10943 10944 if (kue.isCRLSignBitSet()) 10945 { 10946 out(indent + " " + 10947 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_CRL_SIGN.get()); 10948 } 10949 10950 if (kue.isEncipherOnlyBitSet()) 10951 { 10952 out(indent + " " + 10953 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_EO.get()); 10954 } 10955 10956 if (kue.isDecipherOnlyBitSet()) 10957 { 10958 out(indent + " " + 10959 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DO.get()); 10960 } 10961 } 10962 else if (extension instanceof SubjectAlternativeNameExtension) 10963 { 10964 out(indent + " " + 10965 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SAN_EXT.get()); 10966 out(indent + " " + 10967 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10968 extension.getOID().toString())); 10969 out(indent + " " + 10970 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10971 String.valueOf(extension.isCritical()))); 10972 10973 final SubjectAlternativeNameExtension e = 10974 (SubjectAlternativeNameExtension) extension; 10975 printGeneralNames(e.getGeneralNames(), indent + " "); 10976 } 10977 else if (extension instanceof SubjectKeyIdentifierExtension) 10978 { 10979 out(indent + " " + 10980 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SKI_EXT.get()); 10981 out(indent + " " + 10982 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10983 extension.getOID().toString())); 10984 out(indent + " " + 10985 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10986 String.valueOf(extension.isCritical()))); 10987 10988 final SubjectKeyIdentifierExtension e = 10989 (SubjectKeyIdentifierExtension) extension; 10990 final String idHex = 10991 toColonDelimitedHex(e.getKeyIdentifier().getValue()); 10992 out(indent + " " + 10993 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SKI_ID.get()); 10994 for (final String line : StaticUtils.wrapLine(idHex, 78)) 10995 { 10996 out(indent + " " + line); 10997 } 10998 } 10999 else 11000 { 11001 out(indent + " " + 11002 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_GENERIC.get()); 11003 out(indent + " " + 11004 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 11005 extension.getOID().toString())); 11006 out(indent + " " + 11007 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 11008 String.valueOf(extension.isCritical()))); 11009 11010 final String valueHex = toColonDelimitedHex(extension.getValue()); 11011 out(indent + " " + 11012 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_VALUE.get()); 11013 getOut().print(StaticUtils.toHexPlusASCII(extension.getValue(), 11014 (indent.length() + 15))); 11015 } 11016 } 11017 } 11018 11019 11020 11021 /** 11022 * Prints information about the contents of the provided general names object. 11023 * 11024 * @param generalNames The general names object to print. 11025 * @param indent The string to place at the beginning of each line to 11026 * indent that line. 11027 */ 11028 private void printGeneralNames(@NotNull final GeneralNames generalNames, 11029 @NotNull final String indent) 11030 { 11031 for (final String dnsName : generalNames.getDNSNames()) 11032 { 11033 out(indent + INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_DNS.get(dnsName)); 11034 } 11035 11036 for (final InetAddress ipAddress : generalNames.getIPAddresses()) 11037 { 11038 out(indent + 11039 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_IP.get( 11040 ipAddress.getHostAddress())); 11041 } 11042 11043 for (final String name : generalNames.getRFC822Names()) 11044 { 11045 out(indent + 11046 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_RFC_822_NAME.get(name)); 11047 } 11048 11049 for (final DN dn : generalNames.getDirectoryNames()) 11050 { 11051 out(indent + 11052 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_DIRECTORY_NAME.get( 11053 String.valueOf(dn))); 11054 } 11055 11056 for (final String uri : generalNames.getUniformResourceIdentifiers()) 11057 { 11058 out(indent + INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_URI.get(uri)); 11059 } 11060 11061 for (final OID oid : generalNames.getRegisteredIDs()) 11062 { 11063 out(indent + 11064 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_REGISTERED_ID.get( 11065 oid.toString())); 11066 } 11067 11068 if (! generalNames.getOtherNames().isEmpty()) 11069 { 11070 out(indent + 11071 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_OTHER_NAME_COUNT.get( 11072 generalNames.getOtherNames().size())); 11073 } 11074 11075 if (! generalNames.getX400Addresses().isEmpty()) 11076 { 11077 out(indent + 11078 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_X400_ADDR_COUNT.get( 11079 generalNames.getX400Addresses().size())); 11080 } 11081 11082 if (! generalNames.getEDIPartyNames().isEmpty()) 11083 { 11084 out(indent + 11085 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_EDI_PARTY_NAME_COUNT.get( 11086 generalNames.getEDIPartyNames().size())); 11087 } 11088 } 11089 11090 11091 11092 /** 11093 * Writes a PEM-encoded representation of the provided encoded certificate to 11094 * the given print stream. 11095 * 11096 * @param printStream The print stream to which the PEM-encoded 11097 * certificate should be written. It must not be 11098 * {@code null}. 11099 * @param encodedCertificate The bytes that comprise the encoded 11100 * certificate. It must not be {@code null}. 11101 */ 11102 private static void writePEMCertificate( 11103 @NotNull final PrintStream printStream, 11104 @NotNull final byte[] encodedCertificate) 11105 { 11106 final String certBase64 = Base64.encode(encodedCertificate); 11107 printStream.println("-----BEGIN CERTIFICATE-----"); 11108 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11109 { 11110 printStream.println(line); 11111 } 11112 printStream.println("-----END CERTIFICATE-----"); 11113 } 11114 11115 11116 11117 /** 11118 * Writes a PEM-encoded representation of the provided encoded certificate 11119 * signing request to the given print stream. 11120 * 11121 * @param printStream The print stream to which the PEM-encoded certificate 11122 * signing request should be written. It must not be 11123 * {@code null}. 11124 * @param encodedCSR The bytes that comprise the encoded certificate 11125 * signing request. It must not be {@code null}. 11126 */ 11127 private static void writePEMCertificateSigningRequest( 11128 @NotNull final PrintStream printStream, 11129 @NotNull final byte[] encodedCSR) 11130 { 11131 final String certBase64 = Base64.encode(encodedCSR); 11132 printStream.println("-----BEGIN CERTIFICATE REQUEST-----"); 11133 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11134 { 11135 printStream.println(line); 11136 } 11137 printStream.println("-----END CERTIFICATE REQUEST-----"); 11138 } 11139 11140 11141 11142 /** 11143 * Writes a PEM-encoded representation of the provided encoded private key to 11144 * the given print stream. 11145 * 11146 * @param printStream The print stream to which the PEM-encoded 11147 * private key should be written. It must not be 11148 * {@code null}. 11149 * @param encodedPrivateKey The bytes that comprise the encoded private 11150 * key. It must not be {@code null}. 11151 * @param encryptionPassword The password to use to encrypt the private key. 11152 * It may be {@code null} if the private key 11153 * should not be encrypted. 11154 * 11155 * @throws LDAPException If a problem occurs while trying write the private 11156 * key. 11157 */ 11158 private static void writePEMPrivateKey( 11159 @NotNull final PrintStream printStream, 11160 @NotNull final byte[] encodedPrivateKey, 11161 @Nullable final char[] encryptionPassword) 11162 throws LDAPException 11163 { 11164 if (encryptionPassword == null) 11165 { 11166 final String certBase64 = Base64.encode(encodedPrivateKey); 11167 printStream.println("-----BEGIN PRIVATE KEY-----"); 11168 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11169 { 11170 printStream.println(line); 11171 } 11172 printStream.println("-----END PRIVATE KEY-----"); 11173 } 11174 else 11175 { 11176 final byte[] encryptedPrivateKey; 11177 try 11178 { 11179 encryptedPrivateKey = PKCS8EncryptionHandler.encryptPrivateKey( 11180 encodedPrivateKey, encryptionPassword, 11181 new PKCS8EncryptionProperties()); 11182 } 11183 catch (final CertException e) 11184 { 11185 Debug.debugException(e); 11186 throw new LDAPException(ResultCode.LOCAL_ERROR, e.getMessage(), e); 11187 } 11188 11189 final String encryptedCertBase64 = Base64.encode(encryptedPrivateKey); 11190 printStream.println("-----BEGIN ENCRYPTED PRIVATE KEY-----"); 11191 for (final String line : StaticUtils.wrapLine(encryptedCertBase64, 64)) 11192 { 11193 printStream.println(line); 11194 } 11195 printStream.println("-----END ENCRYPTED PRIVATE KEY-----"); 11196 } 11197 } 11198 11199 11200 11201 /** 11202 * Displays the keytool command that can be invoked to produce approximately 11203 * equivalent functionality. 11204 * 11205 * @param keytoolArgs The arguments to provide to the keytool command. 11206 */ 11207 private void displayKeytoolCommand(@NotNull final List<String> keytoolArgs) 11208 { 11209 final StringBuilder buffer = new StringBuilder(); 11210 buffer.append("# keytool"); 11211 11212 boolean lastWasArgName = false; 11213 for (final String arg : keytoolArgs) 11214 { 11215 if (arg.startsWith("-")) 11216 { 11217 buffer.append(' '); 11218 buffer.append(StaticUtils.getCommandLineContinuationString()); 11219 buffer.append(StaticUtils.EOL); 11220 buffer.append("# "); 11221 buffer.append(arg); 11222 lastWasArgName = true; 11223 } 11224 else if (lastWasArgName) 11225 { 11226 buffer.append(' '); 11227 buffer.append(StaticUtils.cleanExampleCommandLineArgument(arg)); 11228 lastWasArgName = false; 11229 } 11230 else 11231 { 11232 buffer.append(' '); 11233 buffer.append(StaticUtils.getCommandLineContinuationString()); 11234 buffer.append(StaticUtils.EOL); 11235 buffer.append("# "); 11236 buffer.append(arg); 11237 lastWasArgName = false; 11238 } 11239 } 11240 11241 out(); 11242 out(INFO_MANAGE_CERTS_APPROXIMATE_KEYTOOL_COMMAND.get()); 11243 out(buffer); 11244 out(); 11245 } 11246 11247 11248 11249 /** 11250 * Retrieves the path to the target key store file. 11251 * 11252 * @return The path to the target key store file, or {@code null} if no 11253 * keystore path was configured. 11254 */ 11255 @Nullable() 11256 private File getKeystorePath() 11257 { 11258 return getKeystorePath("keystore"); 11259 } 11260 11261 11262 11263 /** 11264 * Retrieves the path to the target key store file. 11265 * 11266 * @param keystoreArgumentName The name of the argument used to specify the 11267 * path to the target key store. 11268 * 11269 * @return The path to the target keystore file, or {@code null} if no 11270 * keystore path was configured. 11271 */ 11272 @Nullable() 11273 private File getKeystorePath(@NotNull final String keystoreArgumentName) 11274 { 11275 final FileArgument keystoreArgument = 11276 subCommandParser.getFileArgument(keystoreArgumentName); 11277 if ((keystoreArgument != null) && keystoreArgument.isPresent()) 11278 { 11279 return keystoreArgument.getValue(); 11280 } 11281 11282 final BooleanArgument useJVMDefaultTrustStoreArgument = 11283 subCommandParser.getBooleanArgument("useJVMDefaultTrustStore"); 11284 if ((useJVMDefaultTrustStoreArgument != null) && 11285 useJVMDefaultTrustStoreArgument.isPresent()) 11286 { 11287 return JVM_DEFAULT_CACERTS_FILE; 11288 } 11289 11290 return null; 11291 } 11292 11293 11294 11295 /** 11296 * Retrieves the password needed to access the keystore. 11297 * 11298 * @param keystoreFile The path to the keystore file for which to get the 11299 * password. 11300 * 11301 * @return The password needed to access the keystore, or {@code null} if 11302 * no keystore password was configured. 11303 * 11304 * @throws LDAPException If a problem is encountered while trying to get the 11305 * keystore password. 11306 */ 11307 @Nullable() 11308 private char[] getKeystorePassword(@NotNull final File keystoreFile) 11309 throws LDAPException 11310 { 11311 return getKeystorePassword(keystoreFile, null); 11312 } 11313 11314 11315 11316 /** 11317 * Retrieves the password needed to access the keystore. 11318 * 11319 * @param keystoreFile The path to the keystore file for which to get the 11320 * password. 11321 * @param prefix The prefix string to use for the arguments. This may 11322 * be {@code null} if no prefix is needed. 11323 * 11324 * @return The password needed to access the keystore, or {@code null} if 11325 * no keystore password was configured. 11326 * 11327 * @throws LDAPException If a problem is encountered while trying to get the 11328 * keystore password. 11329 */ 11330 @Nullable() 11331 private char[] getKeystorePassword(@NotNull final File keystoreFile, 11332 @Nullable final String prefix) 11333 throws LDAPException 11334 { 11335 final String prefixDash; 11336 if (prefix == null) 11337 { 11338 prefixDash = ""; 11339 } 11340 else 11341 { 11342 prefixDash = prefix + '-'; 11343 } 11344 11345 final StringArgument keystorePasswordArgument = 11346 subCommandParser.getStringArgument(prefixDash + "keystore-password"); 11347 if ((keystorePasswordArgument != null) && 11348 keystorePasswordArgument.isPresent()) 11349 { 11350 final char[] keystorePWChars = 11351 keystorePasswordArgument.getValue().toCharArray(); 11352 if ((! keystoreFile.exists()) && (keystorePWChars.length < 6)) 11353 { 11354 throw new LDAPException(ResultCode.PARAM_ERROR, 11355 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11356 } 11357 11358 return keystorePWChars; 11359 } 11360 11361 11362 final FileArgument keystorePasswordFileArgument = 11363 subCommandParser.getFileArgument( 11364 prefixDash + "keystore-password-file"); 11365 if ((keystorePasswordFileArgument != null) && 11366 keystorePasswordFileArgument.isPresent()) 11367 { 11368 final File f = keystorePasswordFileArgument.getValue(); 11369 try 11370 { 11371 final char[] passwordChars = getPasswordFileReader().readPassword(f); 11372 if (passwordChars.length < 6) 11373 { 11374 throw new LDAPException(ResultCode.PARAM_ERROR, 11375 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11376 } 11377 return passwordChars; 11378 } 11379 catch (final LDAPException e) 11380 { 11381 Debug.debugException(e); 11382 throw e; 11383 } 11384 catch (final Exception e) 11385 { 11386 Debug.debugException(e); 11387 throw new LDAPException(ResultCode.LOCAL_ERROR, 11388 ERR_MANAGE_CERTS_GET_KS_PW_ERROR_READING_FILE.get( 11389 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11390 e); 11391 } 11392 } 11393 11394 11395 final BooleanArgument promptArgument = subCommandParser.getBooleanArgument( 11396 "prompt-for-" + prefixDash + "keystore-password"); 11397 if ((promptArgument != null) && promptArgument.isPresent()) 11398 { 11399 out(); 11400 if (keystoreFile.exists() && (! "new".equals(prefix))) 11401 { 11402 // We're only going to prompt once. 11403 if ((prefix != null) && prefix.equals("current")) 11404 { 11405 return promptForPassword( 11406 INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_CURRENT_PROMPT.get( 11407 keystoreFile.getAbsolutePath()), 11408 false); 11409 } 11410 else 11411 { 11412 return promptForPassword( 11413 INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_PROMPT.get( 11414 keystoreFile.getAbsolutePath()), 11415 false); 11416 } 11417 } 11418 else 11419 { 11420 // We're creating a new keystore, so we should prompt for the password 11421 // twice to prevent setting the wrong password because of a typo. 11422 while (true) 11423 { 11424 final String prompt1; 11425 if ("new".equals(prefix)) 11426 { 11427 prompt1 = INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_NEW_PROMPT.get(); 11428 } 11429 else 11430 { 11431 prompt1 = INFO_MANAGE_CERTS_KEY_KS_PW_NEW_PROMPT_1.get( 11432 keystoreFile.getAbsolutePath()); 11433 } 11434 final char[] pwChars = promptForPassword(prompt1, false); 11435 11436 if (pwChars.length < 6) 11437 { 11438 wrapErr(0, WRAP_COLUMN, 11439 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11440 err(); 11441 continue; 11442 } 11443 11444 final char[] confirmChars = promptForPassword( 11445 INFO_MANAGE_CERTS_KEY_KS_PW_NEW_PROMPT_2.get(), true); 11446 11447 if (Arrays.equals(pwChars, confirmChars)) 11448 { 11449 Arrays.fill(confirmChars, '\u0000'); 11450 return pwChars; 11451 } 11452 else 11453 { 11454 wrapErr(0, WRAP_COLUMN, 11455 ERR_MANAGE_CERTS_KEY_KS_PW_PROMPT_MISMATCH.get()); 11456 err(); 11457 } 11458 } 11459 } 11460 } 11461 11462 11463 return null; 11464 } 11465 11466 11467 11468 /** 11469 * Retrieves the password used to encrypt a private key. 11470 * 11471 * @param forDecrypt Indicates whether the password will be used to decrypt 11472 * the private key rather than to encrypt it. 11473 * 11474 * @return The password used to encrypt a private key, or {@code null} if no 11475 * encryption password was specified. 11476 * 11477 * @throws LDAPException If a problem is encountered while trying to get the 11478 * keystore password. 11479 */ 11480 @Nullable() 11481 private char[] getPrivateKeyEncryptionPassword(final boolean forDecrypt) 11482 throws LDAPException 11483 { 11484 final StringArgument passwordArgument = 11485 subCommandParser.getStringArgument("encryption-password"); 11486 if ((passwordArgument != null) && passwordArgument.isPresent()) 11487 { 11488 return passwordArgument.getValue().toCharArray(); 11489 } 11490 11491 11492 final FileArgument passwordFileArgument = 11493 subCommandParser.getFileArgument("encryption-password-file"); 11494 if ((passwordFileArgument != null) && passwordFileArgument.isPresent()) 11495 { 11496 final File f = passwordFileArgument.getValue(); 11497 try 11498 { 11499 return getPasswordFileReader().readPassword(f); 11500 } 11501 catch (final LDAPException e) 11502 { 11503 Debug.debugException(e); 11504 throw e; 11505 } 11506 catch (final Exception e) 11507 { 11508 Debug.debugException(e); 11509 throw new LDAPException(ResultCode.LOCAL_ERROR, 11510 ERR_MANAGE_CERTS_GET_PK_ENC_PW_ERROR_READING_FILE.get( 11511 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11512 e); 11513 } 11514 } 11515 11516 11517 final BooleanArgument promptArgument = subCommandParser.getBooleanArgument( 11518 "prompt-for-encryption-password"); 11519 if ((promptArgument != null) && promptArgument.isPresent()) 11520 { 11521 out(); 11522 if (forDecrypt) 11523 { 11524 // We'll be decrypting an existing private key, so we only need to 11525 // prompt for the password once. 11526 return promptForPassword( 11527 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_DECRYPT.get(), false); 11528 } 11529 else 11530 { 11531 // We'll be encrypting the private key, so we need to prompt twice to 11532 // confirm that the entered password is what the user intended. 11533 while (true) 11534 { 11535 final char[] pwChars = promptForPassword( 11536 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_ENCRYPT_1.get(), false); 11537 final char[] confirmChars = promptForPassword( 11538 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_ENCRYPT_2.get(), true); 11539 11540 if (Arrays.equals(pwChars, confirmChars)) 11541 { 11542 Arrays.fill(confirmChars, '\u0000'); 11543 return pwChars; 11544 } 11545 else 11546 { 11547 wrapErr(0, WRAP_COLUMN, 11548 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_MISMATCH.get()); 11549 err(); 11550 } 11551 } 11552 } 11553 } 11554 11555 11556 return null; 11557 } 11558 11559 11560 11561 /** 11562 * Prompts for a password and retrieves the value that the user entered. 11563 * 11564 * @param prompt The prompt to display to the user. 11565 * @param allowEmpty Indicates whether to allow the password to be empty. 11566 * 11567 * @return The password that was read, or an empty array if the user did not 11568 * type a password before pressing ENTER. 11569 * 11570 * @throws LDAPException If a problem is encountered while reading the 11571 * password. 11572 */ 11573 @NotNull() 11574 private char[] promptForPassword(@NotNull final String prompt, 11575 final boolean allowEmpty) 11576 throws LDAPException 11577 { 11578 final Iterator<String> iterator = 11579 StaticUtils.wrapLine(prompt, WRAP_COLUMN).iterator(); 11580 while (iterator.hasNext()) 11581 { 11582 final String line = iterator.next(); 11583 if (iterator.hasNext()) 11584 { 11585 out(line); 11586 } 11587 else 11588 { 11589 getOut().print(line); 11590 } 11591 } 11592 11593 final char[] passwordChars = PasswordReader.readPasswordChars(); 11594 if ((passwordChars.length == 0) && (! allowEmpty)) 11595 { 11596 wrapErr(0, WRAP_COLUMN, 11597 ERR_MANAGE_CERTS_PROMPT_FOR_PW_EMPTY_PW.get()); 11598 err(); 11599 return promptForPassword(prompt, allowEmpty); 11600 } 11601 11602 return passwordChars; 11603 } 11604 11605 11606 11607 /** 11608 * Prompts the user for a yes or no response. 11609 * 11610 * @param prompt The prompt to display to the end user. 11611 * 11612 * @return {@code true} if the user chooses the "yes" response, or 11613 * {@code false} if the user chooses the "no" throws. 11614 * 11615 * @throws LDAPException If a problem is encountered while reading data from 11616 * the client. 11617 */ 11618 private boolean promptForYesNo(@NotNull final String prompt) 11619 throws LDAPException 11620 { 11621 while (true) 11622 { 11623 final List<String> lines = 11624 StaticUtils.wrapLine((prompt + ' '), WRAP_COLUMN); 11625 11626 final Iterator<String> lineIterator = lines.iterator(); 11627 while (lineIterator.hasNext()) 11628 { 11629 final String line = lineIterator.next(); 11630 if (lineIterator.hasNext()) 11631 { 11632 out(line); 11633 } 11634 else 11635 { 11636 getOut().print(line); 11637 } 11638 } 11639 11640 try 11641 { 11642 final String response = readLineFromIn(); 11643 if (response.equalsIgnoreCase("yes") || response.equalsIgnoreCase("y")) 11644 { 11645 return true; 11646 } 11647 else if (response.equalsIgnoreCase("no") || 11648 response.equalsIgnoreCase("n")) 11649 { 11650 return false; 11651 } 11652 else 11653 { 11654 err(); 11655 wrapErr(0, WRAP_COLUMN, 11656 ERR_MANAGE_CERTS_PROMPT_FOR_YES_NO_INVALID_RESPONSE.get()); 11657 err(); 11658 } 11659 } 11660 catch (final Exception e) 11661 { 11662 Debug.debugException(e); 11663 throw new LDAPException(ResultCode.LOCAL_ERROR, 11664 ERR_MANAGE_CERTS_PROMPT_FOR_YES_NO_READ_ERROR.get( 11665 StaticUtils.getExceptionMessage(e)), 11666 e); 11667 } 11668 } 11669 } 11670 11671 11672 11673 /** 11674 * Reads a line of input from standard input. 11675 * 11676 * @return The line read from standard input. 11677 * 11678 * @throws IOException If a problem is encountered while reading from 11679 * standard input. 11680 */ 11681 @NotNull() 11682 private String readLineFromIn() 11683 throws IOException 11684 { 11685 final ByteStringBuffer buffer = new ByteStringBuffer(); 11686 while (true) 11687 { 11688 final int byteRead = in.read(); 11689 if (byteRead < 0) 11690 { 11691 if (buffer.isEmpty()) 11692 { 11693 return null; 11694 } 11695 else 11696 { 11697 return buffer.toString(); 11698 } 11699 } 11700 11701 if (byteRead == '\n') 11702 { 11703 return buffer.toString(); 11704 } 11705 else if (byteRead == '\r') 11706 { 11707 final int nextByteRead = in.read(); 11708 Validator.ensureTrue(((nextByteRead < 0) || (nextByteRead == '\n')), 11709 "ERROR: Read a carriage return from standard input that was " + 11710 "not followed by a new line."); 11711 return buffer.toString(); 11712 } 11713 else 11714 { 11715 buffer.append((byte) (byteRead & 0xFF)); 11716 } 11717 } 11718 } 11719 11720 11721 11722 /** 11723 * Retrieves the password needed to access the private key. 11724 * 11725 * @param keystore The keystore that contains the target private 11726 * key. This must not be {@code null}. 11727 * @param alias The alias of the target private key. This must 11728 * not be {@code null}. 11729 * @param keystorePassword The keystore password to use if no specific 11730 * private key password was provided. 11731 * 11732 * @return The password needed to access the private key, or the provided 11733 * keystore password if no arguments were provided to specify a 11734 * different private key password. 11735 * 11736 * @throws LDAPException If a problem is encountered while trying to get the 11737 * private key password. 11738 */ 11739 @Nullable() 11740 private char[] getPrivateKeyPassword(@NotNull final KeyStore keystore, 11741 @NotNull final String alias, 11742 @Nullable final char[] keystorePassword) 11743 throws LDAPException 11744 { 11745 return getPrivateKeyPassword(keystore, alias, null, keystorePassword); 11746 } 11747 11748 11749 11750 /** 11751 * Retrieves the password needed to access the private key. 11752 * 11753 * @param keystore The keystore that contains the target private 11754 * key. This must not be {@code null}. 11755 * @param alias The alias of the target private key. This must 11756 * not be {@code null}. 11757 * @param prefix The prefix string to use for the arguments. This 11758 * may be {@code null} if no prefix is needed. 11759 * @param keystorePassword The keystore password to use if no specific 11760 * private key password was provided. 11761 * 11762 * @return The password needed to access the private key, or the provided 11763 * keystore password if no arguments were provided to specify a 11764 * different private key password. 11765 * 11766 * @throws LDAPException If a problem is encountered while trying to get the 11767 * private key password. 11768 */ 11769 @Nullable() 11770 private char[] getPrivateKeyPassword(@NotNull final KeyStore keystore, 11771 @NotNull final String alias, 11772 @Nullable final String prefix, 11773 @Nullable final char[] keystorePassword) 11774 throws LDAPException 11775 { 11776 final String prefixDash; 11777 if (prefix == null) 11778 { 11779 prefixDash = ""; 11780 } 11781 else 11782 { 11783 prefixDash = prefix + '-'; 11784 } 11785 11786 final StringArgument privateKeyPasswordArgument = 11787 subCommandParser.getStringArgument( 11788 prefixDash + "private-key-password"); 11789 if ((privateKeyPasswordArgument != null) && 11790 privateKeyPasswordArgument.isPresent()) 11791 { 11792 final char[] pkPasswordChars = 11793 privateKeyPasswordArgument.getValue().toCharArray(); 11794 if ((pkPasswordChars.length < 6) && 11795 (! (hasCertificateAlias(keystore, alias) || 11796 hasKeyAlias(keystore, alias)))) 11797 { 11798 throw new LDAPException(ResultCode.PARAM_ERROR, 11799 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 11800 } 11801 11802 return pkPasswordChars; 11803 } 11804 11805 11806 final FileArgument privateKeyPasswordFileArgument = 11807 subCommandParser.getFileArgument( 11808 prefixDash + "private-key-password-file"); 11809 if ((privateKeyPasswordFileArgument != null) && 11810 privateKeyPasswordFileArgument.isPresent()) 11811 { 11812 final File f = privateKeyPasswordFileArgument.getValue(); 11813 try 11814 { 11815 final char[] passwordChars = getPasswordFileReader().readPassword(f); 11816 if (passwordChars.length < 6) 11817 { 11818 throw new LDAPException(ResultCode.PARAM_ERROR, 11819 ERR_MANAGE_CERTS_GET_PK_PW_EMPTY_FILE.get(f.getAbsolutePath())); 11820 } 11821 11822 return passwordChars; 11823 } 11824 catch (final LDAPException e) 11825 { 11826 Debug.debugException(e); 11827 throw e; 11828 } 11829 catch (final Exception e) 11830 { 11831 Debug.debugException(e); 11832 throw new LDAPException(ResultCode.LOCAL_ERROR, 11833 ERR_MANAGE_CERTS_GET_PK_PW_ERROR_READING_FILE.get( 11834 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11835 e); 11836 } 11837 } 11838 11839 11840 final BooleanArgument promptArgument = 11841 subCommandParser.getBooleanArgument( 11842 "prompt-for-" + prefixDash + "private-key-password"); 11843 if ((promptArgument != null) && promptArgument.isPresent()) 11844 { 11845 out(); 11846 11847 try 11848 { 11849 if ((hasKeyAlias(keystore, alias) || 11850 hasCertificateAlias(keystore, alias)) && 11851 (! "new".equals(prefix)) && (! "destination".equals(prefix))) 11852 { 11853 // This means that the private key already exists, so we just need to 11854 // prompt once. 11855 final String prompt; 11856 if ("current".equals(prefix)) 11857 { 11858 prompt = 11859 INFO_MANAGE_CERTS_GET_PK_PW_CURRENT_PROMPT.get(alias); 11860 } 11861 else 11862 { 11863 prompt = 11864 INFO_MANAGE_CERTS_GET_PK_PW_EXISTING_PROMPT.get(alias); 11865 } 11866 11867 return promptForPassword(prompt, false); 11868 } 11869 else 11870 { 11871 // This means that we'll be creating a new private key, so we need to 11872 // prompt twice. 11873 while (true) 11874 { 11875 final String prompt; 11876 if ("new".equals(prefix)) 11877 { 11878 prompt = INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT.get(); 11879 } 11880 else 11881 { 11882 prompt = INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT_1.get(alias); 11883 } 11884 11885 final char[] pwChars = promptForPassword(prompt, false); 11886 if (pwChars.length < 6) 11887 { 11888 wrapErr(0, WRAP_COLUMN, 11889 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 11890 err(); 11891 continue; 11892 } 11893 11894 final char[] confirmChars = promptForPassword( 11895 INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT_2.get(), true); 11896 11897 if (Arrays.equals(pwChars, confirmChars)) 11898 { 11899 Arrays.fill(confirmChars, '\u0000'); 11900 return pwChars; 11901 } 11902 else 11903 { 11904 wrapErr(0, WRAP_COLUMN, 11905 ERR_MANAGE_CERTS_GET_PK_PW_PROMPT_MISMATCH.get()); 11906 err(); 11907 } 11908 } 11909 } 11910 } 11911 catch (final LDAPException le) 11912 { 11913 Debug.debugException(le); 11914 throw le; 11915 } 11916 catch (final Exception e) 11917 { 11918 Debug.debugException(e); 11919 throw new LDAPException(ResultCode.LOCAL_ERROR, 11920 ERR_MANAGE_CERTS_GET_PK_PW_PROMPT_ERROR.get(alias, 11921 StaticUtils.getExceptionMessage(e)), 11922 e); 11923 } 11924 } 11925 11926 11927 return keystorePassword; 11928 } 11929 11930 11931 11932 /** 11933 * Infers the keystore type from the provided keystore file. 11934 * 11935 * @param keystorePath The path to the file to examine. 11936 * 11937 * @return The keystore type inferred from the provided keystore file. 11938 * 11939 * @throws LDAPException If a problem is encountered while trying to infer 11940 * the keystore type. 11941 */ 11942 @NotNull() 11943 private String inferKeystoreType(@NotNull final File keystorePath) 11944 throws LDAPException 11945 { 11946 return inferKeystoreType(keystorePath, null); 11947 } 11948 11949 11950 11951 /** 11952 * Infers the keystore type from the provided keystore file. 11953 * 11954 * @param keystorePath The path to the file to examine. 11955 * @param prefix The prefix string to use for the arguments. This 11956 * may be {@code null} if no prefix is needed. 11957 * 11958 * @return The keystore type inferred from the provided keystore file. 11959 * 11960 * @throws LDAPException If a problem is encountered while trying to infer 11961 * the keystore type. 11962 */ 11963 @NotNull() 11964 private String inferKeystoreType(@NotNull final File keystorePath, 11965 @Nullable final String prefix) 11966 throws LDAPException 11967 { 11968 // If the keystore type argument was specified, then use its value. 11969 final StringArgument keystoreTypeArgument; 11970 if (prefix == null) 11971 { 11972 keystoreTypeArgument = 11973 subCommandParser.getStringArgument("keystore-type"); 11974 } 11975 else 11976 { 11977 keystoreTypeArgument = 11978 subCommandParser.getStringArgument(prefix + "-keystore-type"); 11979 } 11980 11981 if ((keystoreTypeArgument != null) && keystoreTypeArgument.isPresent()) 11982 { 11983 final String ktaValue = keystoreTypeArgument.getValue(); 11984 if (ktaValue.equalsIgnoreCase("PKCS11") || 11985 ktaValue.equalsIgnoreCase("PKCS 11") || 11986 ktaValue.equalsIgnoreCase("PKCS#11") || 11987 ktaValue.equalsIgnoreCase("PKCS #11")) 11988 { 11989 return CryptoHelper.KEY_STORE_TYPE_PKCS_11; 11990 } 11991 else if (ktaValue.equalsIgnoreCase("PKCS12") || 11992 ktaValue.equalsIgnoreCase("PKCS 12") || 11993 ktaValue.equalsIgnoreCase("PKCS#12") || 11994 ktaValue.equalsIgnoreCase("PKCS #12")) 11995 { 11996 return CryptoHelper.KEY_STORE_TYPE_PKCS_12; 11997 } 11998 else if (ktaValue.equalsIgnoreCase(BCFKS_KEYSTORE_TYPE)) 11999 { 12000 return BCFKS_KEYSTORE_TYPE; 12001 } 12002 else 12003 { 12004 return CryptoHelper.KEY_STORE_TYPE_JKS; 12005 } 12006 } 12007 12008 12009 // If we've gotten here, then the keystore type was not explicitly specified 12010 // so we will need to infer it. If the LDAP SDK is running in FIPS mode, 12011 // then we'll always use the BCFKS key store type. 12012 if (CryptoHelper.usingFIPSMode()) 12013 { 12014 return BouncyCastleFIPSHelper.FIPS_KEY_STORE_TYPE; 12015 } 12016 12017 12018 // If the key store file doesn't exist, then we must be creating it. Use 12019 // the default key store type. 12020 if (! keystorePath.exists()) 12021 { 12022 return DEFAULT_KEYSTORE_TYPE; 12023 } 12024 12025 12026 try 12027 { 12028 return CryptoHelper.inferKeyStoreType(keystorePath); 12029 } 12030 catch (final Exception e) 12031 { 12032 Debug.debugException(e); 12033 throw new LDAPException(ResultCode.PARAM_ERROR, e.getMessage(), e); 12034 } 12035 } 12036 12037 12038 12039 /** 12040 * Retrieves a user-friendly representation of the provided keystore type. 12041 * 12042 * @param keystoreType The keystore type for which to get the user-friendly 12043 * name. 12044 * 12045 * @return "JKS" if the provided keystore type is for a JKS keystore, 12046 * "PKCS #12" if the provided keystore type is for a PKCS #12 12047 * keystore, or the provided string if it is for some other keystore 12048 * type. 12049 */ 12050 @NotNull() 12051 static String getUserFriendlyKeystoreType(@NotNull final String keystoreType) 12052 { 12053 if (keystoreType.equalsIgnoreCase("JKS")) 12054 { 12055 return "JKS"; 12056 } 12057 else if (keystoreType.equalsIgnoreCase("PKCS11") || 12058 keystoreType.equalsIgnoreCase("PKCS 11") || 12059 keystoreType.equalsIgnoreCase("PKCS#11") || 12060 keystoreType.equalsIgnoreCase("PKCS #11")) 12061 { 12062 return "PKCS #11"; 12063 } 12064 else if (keystoreType.equalsIgnoreCase("PKCS12") || 12065 keystoreType.equalsIgnoreCase("PKCS 12") || 12066 keystoreType.equalsIgnoreCase("PKCS#12") || 12067 keystoreType.equalsIgnoreCase("PKCS #12")) 12068 { 12069 return "PKCS #12"; 12070 } 12071 else if (keystoreType.equalsIgnoreCase(BCFKS_KEYSTORE_TYPE)) 12072 { 12073 return BCFKS_KEYSTORE_TYPE; 12074 } 12075 else 12076 { 12077 return keystoreType; 12078 } 12079 } 12080 12081 12082 12083 /** 12084 * Gets access to a keystore based on information included in command-line 12085 * arguments. 12086 * 12087 * @param keystoreType The keystore type for the keystore to access. 12088 * @param keystorePath The path to the keystore file. 12089 * @param keystorePassword The password to use to access the keystore. 12090 * 12091 * @return The configured keystore instance. 12092 * 12093 * @throws LDAPException If it is not possible to access the keystore. 12094 */ 12095 @NotNull() 12096 static KeyStore getKeystore(@NotNull final String keystoreType, 12097 @NotNull final File keystorePath, 12098 @Nullable final char[] keystorePassword) 12099 throws LDAPException 12100 { 12101 // Instantiate a keystore instance of the desired keystore type. 12102 final KeyStore keystore; 12103 try 12104 { 12105 if (keystoreType.equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11)) 12106 { 12107 // NOTE: For PKCS #11 key store types, the key store path will be 12108 // treated as the path to the provider configuration file. 12109 final Provider pkcs11Provider = PKCS11KeyManager.getProvider(null, 12110 keystorePath, keystoreType, true); 12111 keystore = CryptoHelper.getKeyStore(keystoreType, pkcs11Provider); 12112 } 12113 else if (keystoreType.equals(BCFKS_KEYSTORE_TYPE)) 12114 { 12115 keystore = CryptoHelper.getKeyStore(keystoreType, 12116 BouncyCastleFIPSHelper.getBouncyCastleFIPSProvider()); 12117 } 12118 else 12119 { 12120 keystore = CryptoHelper.getKeyStore(keystoreType); 12121 } 12122 } 12123 catch (final Exception e) 12124 { 12125 Debug.debugException(e); 12126 throw new LDAPException(ResultCode.LOCAL_ERROR, 12127 ERR_MANAGE_CERTS_CANNOT_INSTANTIATE_KS_TYPE.get(keystoreType, 12128 StaticUtils.getExceptionMessage(e)), 12129 e); 12130 } 12131 12132 12133 // Get an input stream that may be used to access the keystore. 12134 final InputStream inputStream; 12135 try 12136 { 12137 if (keystorePath.exists() && 12138 (! keystoreType.equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11))) 12139 { 12140 inputStream = new FileInputStream(keystorePath); 12141 } 12142 else 12143 { 12144 inputStream = null; 12145 } 12146 } 12147 catch (final Exception e) 12148 { 12149 Debug.debugException(e); 12150 throw new LDAPException(ResultCode.LOCAL_ERROR, 12151 ERR_MANAGE_CERTS_CANNOT_OPEN_KS_FILE_FOR_READING.get( 12152 keystorePath.getAbsolutePath(), 12153 StaticUtils.getExceptionMessage(e)), 12154 e); 12155 } 12156 12157 try 12158 { 12159 keystore.load(inputStream, keystorePassword); 12160 } 12161 catch (final Exception e) 12162 { 12163 Debug.debugException(e); 12164 final Throwable cause = e.getCause(); 12165 if ((e instanceof IOException) && (cause != null) && 12166 (cause instanceof UnrecoverableKeyException) && 12167 (keystorePassword != null)) 12168 { 12169 throw new LDAPException(ResultCode.PARAM_ERROR, 12170 ERR_MANAGE_CERTS_CANNOT_LOAD_KS_WRONG_PW.get( 12171 keystorePath.getAbsolutePath()), 12172 e); 12173 } 12174 else 12175 { 12176 throw new LDAPException(ResultCode.PARAM_ERROR, 12177 ERR_MANAGE_CERTS_ERROR_CANNOT_LOAD_KS.get( 12178 keystorePath.getAbsolutePath(), 12179 StaticUtils.getExceptionMessage(e)), 12180 e); 12181 } 12182 } 12183 finally 12184 { 12185 try 12186 { 12187 if (inputStream != null) 12188 { 12189 inputStream.close(); 12190 } 12191 } 12192 catch (final Exception e) 12193 { 12194 Debug.debugException(e); 12195 } 12196 } 12197 12198 return keystore; 12199 } 12200 12201 12202 12203 /** 12204 * Reads all of the certificates contained in the specified file. The file 12205 * must exist and may contain zero or more certificates that are either all in 12206 * PEM format or all in DER format. 12207 * 12208 * @param f The path to the certificate file to read. It must not be 12209 * {@code null}. 12210 * 12211 * @return A list of the certificates read from the specified file. 12212 * 12213 * @throws LDAPException If a problem is encountered while reading 12214 * certificates from the specified file. 12215 */ 12216 @NotNull() 12217 public static List<X509Certificate> readCertificatesFromFile( 12218 @NotNull final File f) 12219 throws LDAPException 12220 { 12221 // Read the first byte of the file to see if it contains DER-formatted data, 12222 // which we can determine by seeing if the first byte is 0x30. 12223 try (BufferedInputStream inputStream = 12224 new BufferedInputStream(new FileInputStream(f))) 12225 { 12226 inputStream.mark(1); 12227 final int firstByte = inputStream.read(); 12228 12229 if (firstByte < 0) 12230 { 12231 // This means that the file is empty. 12232 return Collections.emptyList(); 12233 } 12234 else 12235 { 12236 inputStream.reset(); 12237 } 12238 12239 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 12240 if ((firstByte & 0xFF) == 0x30) 12241 { 12242 // It is a DER-encoded file. Read ASN.1 elements and decode them as 12243 // X.509 certificates. 12244 while (true) 12245 { 12246 final ASN1Element certElement; 12247 try 12248 { 12249 certElement = ASN1Element.readFrom(inputStream); 12250 } 12251 catch (final Exception e) 12252 { 12253 Debug.debugException(e); 12254 throw new LDAPException(ResultCode.LOCAL_ERROR, 12255 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DER_NOT_VALID_ASN1.get( 12256 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12257 e); 12258 } 12259 12260 if (certElement == null) 12261 { 12262 // We've reached the end of the input stream. 12263 return certList; 12264 } 12265 12266 try 12267 { 12268 certList.add(new X509Certificate(certElement.encode())); 12269 } 12270 catch (final CertException e) 12271 { 12272 Debug.debugException(e); 12273 throw new LDAPException(ResultCode.PARAM_ERROR, 12274 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DER_NOT_VALID_CERT.get( 12275 f.getAbsolutePath(), e.getMessage()), 12276 e); 12277 } 12278 } 12279 } 12280 else 12281 { 12282 try (BufferedReader reader = 12283 new BufferedReader(new InputStreamReader(inputStream))) 12284 { 12285 boolean inCert = false; 12286 final StringBuilder buffer = new StringBuilder(); 12287 while (true) 12288 { 12289 String line = reader.readLine(); 12290 if (line == null) 12291 { 12292 if (inCert) 12293 { 12294 throw new LDAPException(ResultCode.PARAM_ERROR, 12295 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_EOF_WITHOUT_END.get( 12296 f.getAbsolutePath())); 12297 } 12298 12299 return certList; 12300 } 12301 12302 line = line.trim(); 12303 if (line.isEmpty() || line.startsWith("#")) 12304 { 12305 continue; 12306 } 12307 12308 if (line.equals("-----BEGIN CERTIFICATE-----")) 12309 { 12310 if (inCert) 12311 { 12312 throw new LDAPException(ResultCode.PARAM_ERROR, 12313 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_MULTIPLE_BEGIN.get( 12314 f.getAbsolutePath())); 12315 } 12316 else 12317 { 12318 inCert = true; 12319 } 12320 } 12321 else if (line.equals("-----END CERTIFICATE-----")) 12322 { 12323 if (! inCert) 12324 { 12325 throw new LDAPException(ResultCode.PARAM_ERROR, 12326 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_END_WITHOUT_BEGIN. 12327 get(f.getAbsolutePath())); 12328 } 12329 12330 inCert = false; 12331 final byte[] certBytes; 12332 try 12333 { 12334 certBytes = Base64.decode(buffer.toString()); 12335 } 12336 catch (final Exception e) 12337 { 12338 Debug.debugException(e); 12339 throw new LDAPException(ResultCode.PARAM_ERROR, 12340 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_PEM_CERT_NOT_BASE64. 12341 get(f.getAbsolutePath(), 12342 StaticUtils.getExceptionMessage(e)), 12343 e); 12344 } 12345 12346 try 12347 { 12348 certList.add(new X509Certificate(certBytes)); 12349 } 12350 catch (final CertException e) 12351 { 12352 Debug.debugException(e); 12353 throw new LDAPException(ResultCode.PARAM_ERROR, 12354 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_PEM_CERT_NOT_CERT. 12355 get(f.getAbsolutePath(), e.getMessage()), 12356 e); 12357 } 12358 12359 buffer.setLength(0); 12360 } 12361 else if (inCert) 12362 { 12363 buffer.append(line); 12364 } 12365 else 12366 { 12367 throw new LDAPException(ResultCode.PARAM_ERROR, 12368 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12369 f.getAbsolutePath())); 12370 } 12371 } 12372 } 12373 } 12374 } 12375 catch (final LDAPException le) 12376 { 12377 Debug.debugException(le); 12378 throw le; 12379 } 12380 catch (final Exception e) 12381 { 12382 Debug.debugException(e); 12383 throw new LDAPException(ResultCode.LOCAL_ERROR, 12384 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_READ_ERROR.get( 12385 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12386 e); 12387 } 12388 } 12389 12390 12391 12392 /** 12393 * Reads a private key from the specified file. The file must exist and must 12394 * contain exactly one PEM-encoded or DER-encoded PKCS #8 private key. 12395 * 12396 * @param f The path to the private key file to read. It 12397 * must not be {@code null}. 12398 * @param encryptionPassword The password to use to encrypt the private key. 12399 * It may be {@code null} if the private key is 12400 * not encrypted. 12401 * 12402 * @return The private key read from the file. 12403 * 12404 * @throws LDAPException If a problem is encountered while reading the 12405 * private key. 12406 */ 12407 @NotNull() 12408 static PKCS8PrivateKey readPrivateKeyFromFile(@NotNull final File f, 12409 @Nullable final char[] encryptionPassword) 12410 throws LDAPException 12411 { 12412 // Read the first byte of the file to see if it contains DER-formatted data, 12413 // which we can determine by seeing if the first byte is 0x30. 12414 try (BufferedInputStream inputStream = 12415 new BufferedInputStream(new FileInputStream(f))) 12416 { 12417 inputStream.mark(1); 12418 final int firstByte = inputStream.read(); 12419 12420 if (firstByte < 0) 12421 { 12422 // This means that the file is empty. 12423 throw new LDAPException(ResultCode.PARAM_ERROR, 12424 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12425 f.getAbsolutePath())); 12426 } 12427 else 12428 { 12429 inputStream.reset(); 12430 } 12431 12432 PKCS8PrivateKey privateKey = null; 12433 if ((firstByte & 0xFF) == 0x30) 12434 { 12435 // It is a DER-encoded file. Read an ASN.1 element and decode it as a 12436 // certificate. 12437 while (true) 12438 { 12439 final ASN1Element pkElement; 12440 try 12441 { 12442 pkElement = ASN1Element.readFrom(inputStream); 12443 } 12444 catch (final Exception e) 12445 { 12446 Debug.debugException(e); 12447 throw new LDAPException(ResultCode.LOCAL_ERROR, 12448 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DER_NOT_VALID_ASN1.get( 12449 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12450 e); 12451 } 12452 12453 if (pkElement == null) 12454 { 12455 // We've reached the end of the input stream. 12456 if (privateKey == null) 12457 { 12458 throw new LDAPException(ResultCode.PARAM_ERROR, 12459 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12460 f.getAbsolutePath())); 12461 } 12462 else 12463 { 12464 return privateKey; 12465 } 12466 } 12467 else if (privateKey == null) 12468 { 12469 try 12470 { 12471 if (encryptionPassword == null) 12472 { 12473 privateKey = new PKCS8PrivateKey(pkElement.encode()); 12474 } 12475 else 12476 { 12477 privateKey = PKCS8EncryptionHandler.decryptPrivateKey( 12478 pkElement.encode(), encryptionPassword); 12479 } 12480 } 12481 catch (final Exception e) 12482 { 12483 Debug.debugException(e); 12484 throw new LDAPException(ResultCode.PARAM_ERROR, 12485 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DER_NOT_VALID_PK.get( 12486 f.getAbsolutePath(), e.getMessage()), 12487 e); 12488 } 12489 } 12490 else 12491 { 12492 throw new LDAPException(ResultCode.PARAM_ERROR, 12493 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_KEYS.get( 12494 f.getAbsolutePath())); 12495 } 12496 } 12497 } 12498 else 12499 { 12500 try (BufferedReader reader = 12501 new BufferedReader(new InputStreamReader(inputStream))) 12502 { 12503 boolean inKey = false; 12504 boolean isRSAKey = false; 12505 boolean isEncryptedKey = false; 12506 final StringBuilder buffer = new StringBuilder(); 12507 while (true) 12508 { 12509 String line = reader.readLine(); 12510 if (line == null) 12511 { 12512 if (inKey) 12513 { 12514 throw new LDAPException(ResultCode.PARAM_ERROR, 12515 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EOF_WITHOUT_END.get( 12516 f.getAbsolutePath())); 12517 } 12518 12519 if (privateKey == null) 12520 { 12521 throw new LDAPException(ResultCode.PARAM_ERROR, 12522 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12523 f.getAbsolutePath())); 12524 } 12525 else 12526 { 12527 return privateKey; 12528 } 12529 } 12530 12531 line = line.trim(); 12532 if (line.isEmpty() || line.startsWith("#")) 12533 { 12534 continue; 12535 } 12536 12537 if (line.equals("-----BEGIN PRIVATE KEY-----") || 12538 line.equals("-----BEGIN RSA PRIVATE KEY-----") || 12539 line.equals("-----BEGIN ENCRYPTED PRIVATE KEY-----")) 12540 { 12541 if (inKey) 12542 { 12543 throw new LDAPException(ResultCode.PARAM_ERROR, 12544 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_BEGIN.get( 12545 f.getAbsolutePath())); 12546 } 12547 else if (privateKey != null) 12548 { 12549 throw new LDAPException(ResultCode.PARAM_ERROR, 12550 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_KEYS.get( 12551 f.getAbsolutePath())); 12552 } 12553 else 12554 { 12555 inKey = true; 12556 if (line.equals("-----BEGIN RSA PRIVATE KEY-----")) 12557 { 12558 isRSAKey = true; 12559 } 12560 else if (line.equals("-----BEGIN ENCRYPTED PRIVATE KEY-----")) 12561 { 12562 isEncryptedKey = true; 12563 if (encryptionPassword == null) 12564 { 12565 throw new LDAPException(ResultCode.PARAM_ERROR, 12566 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PK_ENCRYPTED_NO_PW. 12567 get(f.getAbsolutePath())); 12568 } 12569 } 12570 } 12571 } 12572 else if (line.equals("-----END PRIVATE KEY-----") || 12573 line.equals("-----END RSA PRIVATE KEY-----") || 12574 line.equals("-----END ENCRYPTED PRIVATE KEY-----")) 12575 { 12576 if (! inKey) 12577 { 12578 throw new LDAPException(ResultCode.PARAM_ERROR, 12579 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_END_WITHOUT_BEGIN.get( 12580 f.getAbsolutePath())); 12581 } 12582 12583 inKey = false; 12584 byte[] pkBytes; 12585 try 12586 { 12587 pkBytes = Base64.decode(buffer.toString()); 12588 } 12589 catch (final Exception e) 12590 { 12591 Debug.debugException(e); 12592 throw new LDAPException(ResultCode.PARAM_ERROR, 12593 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PEM_PK_NOT_BASE64.get( 12594 f.getAbsolutePath(), 12595 StaticUtils.getExceptionMessage(e)), 12596 e); 12597 } 12598 12599 if (isRSAKey) 12600 { 12601 pkBytes = PKCS8PrivateKey.wrapRSAPrivateKey(pkBytes); 12602 } 12603 12604 try 12605 { 12606 if (isEncryptedKey) 12607 { 12608 privateKey = PKCS8EncryptionHandler. 12609 decryptPrivateKey(pkBytes, encryptionPassword); 12610 } 12611 else 12612 { 12613 privateKey = new PKCS8PrivateKey(pkBytes); 12614 } 12615 } 12616 catch (final CertException e) 12617 { 12618 Debug.debugException(e); 12619 throw new LDAPException(ResultCode.PARAM_ERROR, 12620 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PEM_PK_NOT_PK.get( 12621 f.getAbsolutePath(), e.getMessage()), 12622 e); 12623 } 12624 12625 buffer.setLength(0); 12626 } 12627 else if (inKey) 12628 { 12629 buffer.append(line); 12630 } 12631 else 12632 { 12633 throw new LDAPException(ResultCode.PARAM_ERROR, 12634 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12635 f.getAbsolutePath())); 12636 } 12637 } 12638 } 12639 } 12640 } 12641 catch (final LDAPException le) 12642 { 12643 Debug.debugException(le); 12644 throw le; 12645 } 12646 catch (final Exception e) 12647 { 12648 Debug.debugException(e); 12649 throw new LDAPException(ResultCode.LOCAL_ERROR, 12650 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_READ_ERROR.get( 12651 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12652 e); 12653 } 12654 } 12655 12656 12657 12658 /** 12659 * Reads a certificate signing request from the specified file. The file must 12660 * exist and must contain exactly one PEM-encoded or DER-encoded PKCS #10 12661 * certificate signing request. 12662 * 12663 * @param f The path to the private key file to read. It must not be 12664 * {@code null}. 12665 * 12666 * @return The certificate signing request read from the file. 12667 * 12668 * @throws LDAPException If a problem is encountered while reading the 12669 * certificate signing request. 12670 */ 12671 @NotNull() 12672 public static PKCS10CertificateSigningRequest 12673 readCertificateSigningRequestFromFile( 12674 @NotNull final File f) 12675 throws LDAPException 12676 { 12677 // Read the first byte of the file to see if it contains DER-formatted data, 12678 // which we can determine by seeing if the first byte is 0x30. 12679 try (BufferedInputStream inputStream = 12680 new BufferedInputStream(new FileInputStream(f))) 12681 { 12682 inputStream.mark(1); 12683 final int firstByte = inputStream.read(); 12684 12685 if (firstByte < 0) 12686 { 12687 // This means that the file is empty. 12688 throw new LDAPException(ResultCode.PARAM_ERROR, 12689 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12690 f.getAbsolutePath())); 12691 } 12692 else 12693 { 12694 inputStream.reset(); 12695 } 12696 12697 PKCS10CertificateSigningRequest csr = null; 12698 if ((firstByte & 0xFF) == 0x30) 12699 { 12700 // It is a DER-encoded file. Read an ASN.1 element and decode it as a 12701 // certificate. 12702 while (true) 12703 { 12704 final ASN1Element csrElement; 12705 try 12706 { 12707 csrElement = ASN1Element.readFrom(inputStream); 12708 } 12709 catch (final Exception e) 12710 { 12711 Debug.debugException(e); 12712 throw new LDAPException(ResultCode.LOCAL_ERROR, 12713 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DER_NOT_VALID_ASN1.get( 12714 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12715 e); 12716 } 12717 12718 if (csrElement == null) 12719 { 12720 // We've reached the end of the input stream. 12721 if (csr == null) 12722 { 12723 throw new LDAPException(ResultCode.PARAM_ERROR, 12724 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12725 f.getAbsolutePath())); 12726 } 12727 else 12728 { 12729 return csr; 12730 } 12731 } 12732 else if (csr == null) 12733 { 12734 try 12735 { 12736 csr = new PKCS10CertificateSigningRequest(csrElement.encode()); 12737 } 12738 catch (final Exception e) 12739 { 12740 Debug.debugException(e); 12741 throw new LDAPException(ResultCode.PARAM_ERROR, 12742 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DER_NOT_VALID_CSR.get( 12743 f.getAbsolutePath(), e.getMessage()), 12744 e); 12745 } 12746 } 12747 else 12748 { 12749 throw new LDAPException(ResultCode.PARAM_ERROR, 12750 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_CSRS.get( 12751 f.getAbsolutePath())); 12752 } 12753 } 12754 } 12755 else 12756 { 12757 try (BufferedReader reader = 12758 new BufferedReader(new InputStreamReader(inputStream))) 12759 { 12760 boolean inCSR = false; 12761 final StringBuilder buffer = new StringBuilder(); 12762 while (true) 12763 { 12764 String line = reader.readLine(); 12765 if (line == null) 12766 { 12767 if (inCSR) 12768 { 12769 throw new LDAPException(ResultCode.PARAM_ERROR, 12770 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EOF_WITHOUT_END.get( 12771 f.getAbsolutePath())); 12772 } 12773 12774 if (csr == null) 12775 { 12776 throw new LDAPException(ResultCode.PARAM_ERROR, 12777 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12778 f.getAbsolutePath())); 12779 } 12780 else 12781 { 12782 return csr; 12783 } 12784 } 12785 12786 line = line.trim(); 12787 if (line.isEmpty() || line.startsWith("#")) 12788 { 12789 continue; 12790 } 12791 12792 if (line.equals("-----BEGIN CERTIFICATE REQUEST-----") || 12793 line.equals("-----BEGIN NEW CERTIFICATE REQUEST-----")) 12794 { 12795 if (inCSR) 12796 { 12797 throw new LDAPException(ResultCode.PARAM_ERROR, 12798 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_BEGIN.get( 12799 f.getAbsolutePath())); 12800 } 12801 else if (csr != null) 12802 { 12803 throw new LDAPException(ResultCode.PARAM_ERROR, 12804 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_CSRS.get( 12805 f.getAbsolutePath())); 12806 } 12807 else 12808 { 12809 inCSR = true; 12810 } 12811 } 12812 else if (line.equals("-----END CERTIFICATE REQUEST-----") || 12813 line.equals("-----END NEW CERTIFICATE REQUEST-----")) 12814 { 12815 if (! inCSR) 12816 { 12817 throw new LDAPException(ResultCode.PARAM_ERROR, 12818 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_END_WITHOUT_BEGIN.get( 12819 f.getAbsolutePath())); 12820 } 12821 12822 inCSR = false; 12823 final byte[] csrBytes; 12824 try 12825 { 12826 csrBytes = Base64.decode(buffer.toString()); 12827 } 12828 catch (final Exception e) 12829 { 12830 Debug.debugException(e); 12831 throw new LDAPException(ResultCode.PARAM_ERROR, 12832 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_PEM_CSR_NOT_BASE64.get( 12833 f.getAbsolutePath(), 12834 StaticUtils.getExceptionMessage(e)), 12835 e); 12836 } 12837 12838 try 12839 { 12840 csr = new PKCS10CertificateSigningRequest(csrBytes); 12841 } 12842 catch (final CertException e) 12843 { 12844 Debug.debugException(e); 12845 throw new LDAPException(ResultCode.PARAM_ERROR, 12846 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_PEM_CSR_NOT_CSR.get( 12847 f.getAbsolutePath(), e.getMessage()), 12848 e); 12849 } 12850 12851 buffer.setLength(0); 12852 } 12853 else if (inCSR) 12854 { 12855 buffer.append(line); 12856 } 12857 else 12858 { 12859 throw new LDAPException(ResultCode.PARAM_ERROR, 12860 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12861 f.getAbsolutePath())); 12862 } 12863 } 12864 } 12865 } 12866 } 12867 catch (final LDAPException le) 12868 { 12869 Debug.debugException(le); 12870 throw le; 12871 } 12872 catch (final Exception e) 12873 { 12874 Debug.debugException(e); 12875 throw new LDAPException(ResultCode.LOCAL_ERROR, 12876 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_READ_ERROR.get( 12877 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12878 e); 12879 } 12880 } 12881 12882 12883 12884 /** 12885 * Retrieves a colon-delimited hexadecimal representation of the contents of 12886 * the provided byte array. 12887 * 12888 * @param bytes The byte array for which to get the hexadecimal 12889 * representation. It must not be {@code null}. 12890 * 12891 * @return A colon-delimited hexadecimal representation of the contents of 12892 * the provided byte array. 12893 */ 12894 @NotNull() 12895 private static String toColonDelimitedHex(@NotNull final byte... bytes) 12896 { 12897 final StringBuilder buffer = new StringBuilder(bytes.length * 3); 12898 StaticUtils.toHex(bytes, ":", buffer); 12899 return buffer.toString(); 12900 } 12901 12902 12903 12904 /** 12905 * Retrieves a formatted representation of the provided date in a 12906 * human-readable format that includes an offset from the current time. 12907 * 12908 * @param d The date to format. It must not be {@code null}. 12909 * 12910 * @return A formatted representation of the provided date. 12911 */ 12912 @NotNull() 12913 private static String formatDateAndTime(@NotNull final Date d) 12914 { 12915 // Example: Sunday, January 1, 2017 12916 final String dateFormatString = "EEEE, MMMM d, yyyy"; 12917 final String formattedDate = 12918 new SimpleDateFormat(dateFormatString).format(d); 12919 12920 // Example: 12:34:56 AM CDT 12921 final String timeFormatString = "hh:mm:ss aa z"; 12922 final String formattedTime = 12923 new SimpleDateFormat(timeFormatString).format(d); 12924 12925 final long providedTime = d.getTime(); 12926 final long currentTime = System.currentTimeMillis(); 12927 if (providedTime > currentTime) 12928 { 12929 final long secondsInFuture = ((providedTime - currentTime) / 1000L); 12930 final String durationInFuture = 12931 StaticUtils.secondsToHumanReadableDuration(secondsInFuture); 12932 return INFO_MANAGE_CERTS_FORMAT_DATE_AND_TIME_IN_FUTURE.get(formattedDate, 12933 formattedTime, durationInFuture); 12934 } 12935 else 12936 { 12937 final long secondsInPast = ((currentTime - providedTime) / 1000L); 12938 final String durationInPast = 12939 StaticUtils.secondsToHumanReadableDuration(secondsInPast); 12940 return INFO_MANAGE_CERTS_FORMAT_DATE_AND_TIME_IN_PAST.get(formattedDate, 12941 formattedTime, durationInPast); 12942 } 12943 } 12944 12945 12946 12947 /** 12948 * Retrieves a formatted representation of the provided date in a format 12949 * suitable for use as the validity start time value provided to the keytool 12950 * command. 12951 * 12952 * @param d The date to format. It must not be {@code null}. 12953 * 12954 * @return A formatted representation of the provided date. 12955 */ 12956 @NotNull() 12957 private static String formatValidityStartTime(@NotNull final Date d) 12958 { 12959 // Example: 2017/01/01 01:23:45 12960 final String dateFormatString = "yyyy'/'MM'/'dd HH':'mm':'ss"; 12961 return new SimpleDateFormat(dateFormatString).format(d); 12962 } 12963 12964 12965 12966 /** 12967 * Retrieves the certificate chain for the specified certificate from the 12968 * given keystore. If any issuer certificate is not in the provided keystore, 12969 * then the JVM-default trust store will be checked to see if it can be found 12970 * there. 12971 * 12972 * @param alias The alias of the certificate for which to get the 12973 * certificate chain. This must not be 12974 * {@code null}. 12975 * @param keystore The keystore from which to get the certificate 12976 * chain. This must not be {@code null}. 12977 * @param missingIssuerRef A reference that will be updated with the DN of a 12978 * missing issuer certificate, if any certificate in 12979 * the chain cannot be located. This must not be 12980 * {@code null}. 12981 * 12982 * @return The certificate chain for the specified certificate, or an empty 12983 * array if no certificate exists with the specified alias. 12984 * 12985 * @throws LDAPException If a problem is encountered while getting the 12986 * certificate chain. 12987 */ 12988 @NotNull() 12989 private static X509Certificate[] getCertificateChain( 12990 @NotNull final String alias, 12991 @NotNull final KeyStore keystore, 12992 @NotNull final AtomicReference<DN> missingIssuerRef) 12993 throws LDAPException 12994 { 12995 try 12996 { 12997 // First, see if the keystore will give us the certificate chain. This 12998 // will only happen if the alias references an entry that includes the 12999 // private key, but it will save us a lot of work. 13000 final Certificate[] chain = keystore.getCertificateChain(alias); 13001 if ((chain != null) && (chain.length > 0)) 13002 { 13003 final X509Certificate[] x509Chain = new X509Certificate[chain.length]; 13004 for (int i=0; i < chain.length; i++) 13005 { 13006 x509Chain[i] = new X509Certificate(chain[i].getEncoded()); 13007 } 13008 return x509Chain; 13009 } 13010 13011 13012 // We couldn't get the keystore to give us the chain, but see if we can 13013 // get a certificate with the specified alias. 13014 final Certificate endCert = keystore.getCertificate(alias); 13015 if (endCert == null) 13016 { 13017 // This means there isn't any certificate with the specified alias. 13018 // Return an empty chain. 13019 return new X509Certificate[0]; 13020 } 13021 13022 final ArrayList<X509Certificate> chainList = new ArrayList<>(5); 13023 X509Certificate certificate = new X509Certificate(endCert.getEncoded()); 13024 chainList.add(certificate); 13025 13026 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 13027 new AtomicReference<>(); 13028 while (true) 13029 { 13030 final X509Certificate issuerCertificate = 13031 getIssuerCertificate(certificate, keystore, 13032 jvmDefaultTrustStoreRef, missingIssuerRef); 13033 if (issuerCertificate == null) 13034 { 13035 break; 13036 } 13037 13038 chainList.add(issuerCertificate); 13039 certificate = issuerCertificate; 13040 } 13041 13042 final X509Certificate[] x509Chain = new X509Certificate[chainList.size()]; 13043 return chainList.toArray(x509Chain); 13044 } 13045 catch (final Exception e) 13046 { 13047 Debug.debugException(e); 13048 throw new LDAPException(ResultCode.LOCAL_ERROR, 13049 ERR_MANAGE_CERTS_GET_CHAIN_ERROR.get(alias, 13050 StaticUtils.getExceptionMessage(e)), 13051 e); 13052 } 13053 } 13054 13055 13056 13057 /** 13058 * Attempts to retrieve the issuer certificate for the provided certificate 13059 * from the given keystore or the JVM-default trust store. 13060 * 13061 * @param certificate The certificate for which to retrieve the 13062 * issuer certificate. 13063 * @param keystore The keystore in which to look for the 13064 * issuer certificate. 13065 * @param jvmDefaultTrustStoreRef A reference that will be used to hold the 13066 * JVM-default trust store if it is obtained 13067 * in the process of retrieving the issuer 13068 * certificate. 13069 * @param missingIssuerRef A reference that will be updated with the 13070 * DN of a missing issuer certificate, if any 13071 * certificate in the chain cannot be 13072 * located. This must not be {@code null}. 13073 * 13074 * @return The issuer certificate for the provided certificate, or 13075 * {@code null} if the issuer certificate could not be retrieved. 13076 * 13077 * @throws Exception If a problem is encountered while trying to retrieve 13078 * the issuer certificate. 13079 */ 13080 @Nullable() 13081 private static X509Certificate getIssuerCertificate( 13082 @NotNull final X509Certificate certificate, 13083 @NotNull final KeyStore keystore, 13084 @NotNull final AtomicReference<KeyStore> jvmDefaultTrustStoreRef, 13085 @NotNull final AtomicReference<DN> missingIssuerRef) 13086 throws Exception 13087 { 13088 final DN subjectDN = certificate.getSubjectDN(); 13089 final DN issuerDN = certificate.getIssuerDN(); 13090 if (subjectDN.equals(issuerDN)) 13091 { 13092 // This means that the certificate is self-signed, so there is no issuer. 13093 return null; 13094 } 13095 13096 13097 // See if we can find the issuer certificate in the provided keystore. 13098 X509Certificate issuerCertificate = getIssuerCertificate(certificate, 13099 keystore); 13100 if (issuerCertificate != null) 13101 { 13102 return issuerCertificate; 13103 } 13104 13105 13106 // See if we can get the JVM-default trust store. 13107 KeyStore jvmDefaultTrustStore = jvmDefaultTrustStoreRef.get(); 13108 if (jvmDefaultTrustStore == null) 13109 { 13110 if (JVM_DEFAULT_CACERTS_FILE == null) 13111 { 13112 missingIssuerRef.set(issuerDN); 13113 return null; 13114 } 13115 13116 final String[] keystoreTypes = 13117 { 13118 CryptoHelper.KEY_STORE_TYPE_JKS, 13119 CryptoHelper.KEY_STORE_TYPE_PKCS_12, 13120 BouncyCastleFIPSHelper.FIPS_KEY_STORE_TYPE 13121 }; 13122 13123 for (final String keystoreType : keystoreTypes) 13124 { 13125 try 13126 { 13127 final KeyStore ks = 13128 CryptoHelper.getKeyStore(keystoreType, null, true); 13129 try (FileInputStream inputStream = 13130 new FileInputStream(JVM_DEFAULT_CACERTS_FILE)) 13131 { 13132 ks.load(inputStream, null); 13133 jvmDefaultTrustStore = ks; 13134 jvmDefaultTrustStoreRef.set(jvmDefaultTrustStore); 13135 break; 13136 } 13137 } 13138 catch (final Exception e) 13139 { 13140 Debug.debugException(e); 13141 } 13142 } 13143 } 13144 13145 if (jvmDefaultTrustStore != null) 13146 { 13147 issuerCertificate = getIssuerCertificate(certificate, 13148 jvmDefaultTrustStore); 13149 } 13150 13151 if (issuerCertificate == null) 13152 { 13153 missingIssuerRef.set(issuerDN); 13154 } 13155 13156 return issuerCertificate; 13157 } 13158 13159 13160 13161 /** 13162 * Attempts to retrieve the issuer certificate for the provided certificate 13163 * from the given keystore. 13164 * 13165 * @param certificate The certificate for which to retrieve the issuer 13166 * certificate. 13167 * @param keystore The keystore in which to look for the issuer 13168 * certificate. 13169 * 13170 * @return The issuer certificate for the provided certificate, or 13171 * {@code null} if the issuer certificate could not be retrieved. 13172 * 13173 * @throws Exception If a problem is encountered while trying to retrieve 13174 * the issuer certificate. 13175 */ 13176 @Nullable() 13177 private static X509Certificate getIssuerCertificate( 13178 @NotNull final X509Certificate certificate, 13179 @NotNull final KeyStore keystore) 13180 throws Exception 13181 { 13182 final Enumeration<String> aliases = keystore.aliases(); 13183 while (aliases.hasMoreElements()) 13184 { 13185 final String alias = aliases.nextElement(); 13186 13187 Certificate[] certs = null; 13188 if (hasCertificateAlias(keystore, alias)) 13189 { 13190 final Certificate c = keystore.getCertificate(alias); 13191 if (c == null) 13192 { 13193 continue; 13194 } 13195 13196 certs = new Certificate[] { c }; 13197 } 13198 else if (hasKeyAlias(keystore, alias)) 13199 { 13200 certs = keystore.getCertificateChain(alias); 13201 } 13202 13203 if (certs != null) 13204 { 13205 for (final Certificate c : certs) 13206 { 13207 final X509Certificate xc = new X509Certificate(c.getEncoded()); 13208 if (xc.isIssuerFor(certificate)) 13209 { 13210 return xc; 13211 } 13212 } 13213 } 13214 } 13215 13216 return null; 13217 } 13218 13219 13220 13221 /** 13222 * Retrieves the authority key identifier value for the provided certificate, 13223 * if present. 13224 * 13225 * @param c The certificate for which to retrieve the authority key 13226 * identifier. 13227 * 13228 * @return The authority key identifier value for the provided certificate, 13229 * or {@code null} if the certificate does not have an authority 13230 * key identifier. 13231 */ 13232 @Nullable() 13233 private static byte[] getAuthorityKeyIdentifier( 13234 @NotNull final X509Certificate c) 13235 { 13236 for (final X509CertificateExtension extension : c.getExtensions()) 13237 { 13238 if (extension instanceof AuthorityKeyIdentifierExtension) 13239 { 13240 final AuthorityKeyIdentifierExtension e = 13241 (AuthorityKeyIdentifierExtension) extension; 13242 if (e.getKeyIdentifier() != null) 13243 { 13244 return e.getKeyIdentifier().getValue(); 13245 } 13246 } 13247 } 13248 13249 return null; 13250 } 13251 13252 13253 13254 /** 13255 * Writes the provided keystore to the specified file. If the keystore file 13256 * already exists, a new temporary file will be created, the old file renamed 13257 * out of the way, the new file renamed into place, and the old file deleted. 13258 * If the keystore file does not exist, then it will simply be created in the 13259 * correct place. 13260 * 13261 * @param keystore The keystore to be written. 13262 * @param keystorePath The path to the keystore file to be written. 13263 * @param keystorePassword The password to use for the keystore. 13264 * 13265 * @throws LDAPException If a problem is encountered while writing the 13266 * keystore. 13267 */ 13268 static void writeKeystore(@NotNull final KeyStore keystore, 13269 @NotNull final File keystorePath, 13270 @Nullable final char[] keystorePassword) 13271 throws LDAPException 13272 { 13273 // If the key store type is PKCS #11, then we don't need to worry about a 13274 // key store file. 13275 if (keystore.getType().equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11)) 13276 { 13277 try 13278 { 13279 keystore.store(null); 13280 return; 13281 } 13282 catch (final Exception e) 13283 { 13284 Debug.debugException(e); 13285 throw new LDAPException(ResultCode.LOCAL_ERROR, 13286 ERR_MANAGE_CERTS_PKCS11_WRITE_ERROR.get( 13287 StaticUtils.getExceptionMessage(e)), 13288 e); 13289 } 13290 } 13291 13292 13293 File copyOfExistingKeystore = null; 13294 final String timestamp = 13295 StaticUtils.encodeGeneralizedTime(System.currentTimeMillis()); 13296 if (keystorePath.exists()) 13297 { 13298 copyOfExistingKeystore = new File(keystorePath.getAbsolutePath() + 13299 ".backup-" + timestamp); 13300 try 13301 { 13302 Files.copy(keystorePath.toPath(), copyOfExistingKeystore.toPath()); 13303 } 13304 catch (final Exception e) 13305 { 13306 Debug.debugException(e); 13307 throw new LDAPException(ResultCode.LOCAL_ERROR, 13308 ERR_MANAGE_CERTS_WRITE_KS_ERROR_COPYING_EXISTING_KS.get( 13309 keystorePath.getAbsolutePath(), 13310 copyOfExistingKeystore.getAbsolutePath(), 13311 StaticUtils.getExceptionMessage(e)), 13312 e); 13313 } 13314 } 13315 13316 try (FileOutputStream outputStream = new FileOutputStream(keystorePath)) 13317 { 13318 keystore.store(outputStream, keystorePassword); 13319 } 13320 catch (final Exception e) 13321 { 13322 Debug.debugException(e); 13323 if (copyOfExistingKeystore == null) 13324 { 13325 throw new LDAPException(ResultCode.LOCAL_ERROR, 13326 ERR_MANAGE_CERTS_WRITE_KS_ERROR_WRITING_NEW_KS.get( 13327 keystorePath.getAbsolutePath(), 13328 StaticUtils.getExceptionMessage(e)), 13329 e); 13330 } 13331 else 13332 { 13333 throw new LDAPException(ResultCode.LOCAL_ERROR, 13334 ERR_MANAGE_CERTS_WRITE_KS_ERROR_OVERWRITING_KS.get( 13335 keystorePath.getAbsolutePath(), 13336 StaticUtils.getExceptionMessage(e), 13337 copyOfExistingKeystore.getAbsolutePath()), 13338 e); 13339 } 13340 } 13341 13342 if (copyOfExistingKeystore != null) 13343 { 13344 try 13345 { 13346 Files.delete(copyOfExistingKeystore.toPath()); 13347 } 13348 catch (final Exception e) 13349 { 13350 Debug.debugException(e); 13351 throw new LDAPException(ResultCode.LOCAL_ERROR, 13352 ERR_MANAGE_CERTS_WRITE_KS_ERROR_DELETING_KS_BACKUP.get( 13353 copyOfExistingKeystore.getAbsolutePath(), 13354 keystorePath.getAbsolutePath(), 13355 StaticUtils.getExceptionMessage(e)), 13356 e); 13357 } 13358 } 13359 } 13360 13361 13362 13363 /** 13364 * Indicates whether the provided keystore has a certificate entry with the 13365 * specified alias. 13366 * 13367 * @param keystore The keystore to examine. 13368 * @param alias The alias for which to make the determination. 13369 * 13370 * @return {@code true} if the keystore has a certificate entry with the 13371 * specified alias, or {@code false} if the alias doesn't exist or 13372 * is associated with some other type of entry (like a key). 13373 */ 13374 private static boolean hasCertificateAlias(@NotNull final KeyStore keystore, 13375 @NotNull final String alias) 13376 { 13377 try 13378 { 13379 return keystore.isCertificateEntry(alias); 13380 } 13381 catch (final Exception e) 13382 { 13383 // This should never happen. If it does, then we'll assume the alias 13384 // doesn't exist or isn't associated with a certificate. 13385 Debug.debugException(e); 13386 return false; 13387 } 13388 } 13389 13390 13391 13392 /** 13393 * Indicates whether the provided keystore has a key entry with the specified 13394 * alias. 13395 * 13396 * @param keystore The keystore to examine. 13397 * @param alias The alias for which to make the determination. 13398 * 13399 * @return {@code true} if the keystore has a key entry with the specified 13400 * alias, or {@code false} if the alias doesn't exist or is 13401 * associated with some other type of entry (like a certificate). 13402 */ 13403 private static boolean hasKeyAlias(@NotNull final KeyStore keystore, 13404 @NotNull final String alias) 13405 { 13406 try 13407 { 13408 return keystore.isKeyEntry(alias); 13409 } 13410 catch (final Exception e) 13411 { 13412 // This should never happen. If it does, then we'll assume the alias 13413 // doesn't exist or isn't associated with a key. 13414 Debug.debugException(e); 13415 return false; 13416 } 13417 } 13418 13419 13420 13421 /** 13422 * Adds arguments for each of the provided extensions to the given list. 13423 * 13424 * @param keytoolArguments The list to which the extension arguments should 13425 * be added. 13426 * @param basicConstraints The basic constraints extension to include. It 13427 * may be {@code null} if this extension should not 13428 * be included. 13429 * @param keyUsage The key usage extension to include. It may be 13430 * {@code null} if this extension should not be 13431 * included. 13432 * @param extendedKeyUsage The extended key usage extension to include. It 13433 * may be {@code null} if this extension should not 13434 * be included. 13435 * @param sanValues The list of subject alternative name values to 13436 * include. It must not be {@code null} but may be 13437 * empty. 13438 * @param ianValues The list of issuer alternative name values to 13439 * include. It must not be {@code null} but may be 13440 * empty. 13441 * @param genericExtensions The list of generic extensions to include. It 13442 * must not be {@code null} but may be empty. 13443 */ 13444 private static void addExtensionArguments( 13445 @NotNull final List<String> keytoolArguments, 13446 @Nullable final BasicConstraintsExtension basicConstraints, 13447 @Nullable final KeyUsageExtension keyUsage, 13448 @Nullable final ExtendedKeyUsageExtension extendedKeyUsage, 13449 @NotNull final Set<String> sanValues, 13450 @NotNull final Set<String> ianValues, 13451 @NotNull final List<X509CertificateExtension> genericExtensions) 13452 { 13453 if (basicConstraints != null) 13454 { 13455 final StringBuilder basicConstraintsValue = new StringBuilder(); 13456 basicConstraintsValue.append("ca:"); 13457 basicConstraintsValue.append(basicConstraints.isCA()); 13458 13459 if (basicConstraints.getPathLengthConstraint() != null) 13460 { 13461 basicConstraintsValue.append(",pathlen:"); 13462 basicConstraintsValue.append( 13463 basicConstraints.getPathLengthConstraint()); 13464 } 13465 13466 keytoolArguments.add("-ext"); 13467 keytoolArguments.add("BasicConstraints=" + basicConstraintsValue); 13468 } 13469 13470 if (keyUsage != null) 13471 { 13472 final StringBuilder keyUsageValue = new StringBuilder(); 13473 if (keyUsage.isDigitalSignatureBitSet()) 13474 { 13475 commaAppend(keyUsageValue, "digitalSignature"); 13476 } 13477 13478 if (keyUsage.isNonRepudiationBitSet()) 13479 { 13480 commaAppend(keyUsageValue, "nonRepudiation"); 13481 } 13482 13483 if (keyUsage.isKeyEnciphermentBitSet()) 13484 { 13485 commaAppend(keyUsageValue, "keyEncipherment"); 13486 } 13487 13488 if (keyUsage.isDataEnciphermentBitSet()) 13489 { 13490 commaAppend(keyUsageValue, "dataEncipherment"); 13491 } 13492 13493 if (keyUsage.isKeyAgreementBitSet()) 13494 { 13495 commaAppend(keyUsageValue, "keyAgreement"); 13496 } 13497 13498 if (keyUsage.isKeyCertSignBitSet()) 13499 { 13500 commaAppend(keyUsageValue, "keyCertSign"); 13501 } 13502 13503 if (keyUsage.isCRLSignBitSet()) 13504 { 13505 commaAppend(keyUsageValue, "cRLSign"); 13506 } 13507 13508 if (keyUsage.isEncipherOnlyBitSet()) 13509 { 13510 commaAppend(keyUsageValue, "encipherOnly"); 13511 } 13512 13513 if (keyUsage.isEncipherOnlyBitSet()) 13514 { 13515 commaAppend(keyUsageValue, "decipherOnly"); 13516 } 13517 13518 keytoolArguments.add("-ext"); 13519 keytoolArguments.add("KeyUsage=" + keyUsageValue); 13520 } 13521 13522 if (extendedKeyUsage != null) 13523 { 13524 final StringBuilder extendedKeyUsageValue = new StringBuilder(); 13525 for (final OID oid : extendedKeyUsage.getKeyPurposeIDs()) 13526 { 13527 final ExtendedKeyUsageID id = ExtendedKeyUsageID.forOID(oid); 13528 if (id == null) 13529 { 13530 commaAppend(extendedKeyUsageValue, oid.toString()); 13531 } 13532 else 13533 { 13534 switch (id) 13535 { 13536 case TLS_SERVER_AUTHENTICATION: 13537 commaAppend(extendedKeyUsageValue, "serverAuth"); 13538 break; 13539 case TLS_CLIENT_AUTHENTICATION: 13540 commaAppend(extendedKeyUsageValue, "clientAuth"); 13541 break; 13542 case CODE_SIGNING: 13543 commaAppend(extendedKeyUsageValue, "codeSigning"); 13544 break; 13545 case EMAIL_PROTECTION: 13546 commaAppend(extendedKeyUsageValue, "emailProtection"); 13547 break; 13548 case TIME_STAMPING: 13549 commaAppend(extendedKeyUsageValue, "timeStamping"); 13550 break; 13551 case OCSP_SIGNING: 13552 commaAppend(extendedKeyUsageValue, "OCSPSigning"); 13553 break; 13554 default: 13555 // This should never happen. 13556 commaAppend(extendedKeyUsageValue, id.getOID().toString()); 13557 break; 13558 } 13559 } 13560 } 13561 13562 keytoolArguments.add("-ext"); 13563 keytoolArguments.add("ExtendedKeyUsage=" + extendedKeyUsageValue); 13564 } 13565 13566 if (! sanValues.isEmpty()) 13567 { 13568 final StringBuilder subjectAltNameValue = new StringBuilder(); 13569 for (final String sanValue : sanValues) 13570 { 13571 commaAppend(subjectAltNameValue, sanValue); 13572 } 13573 13574 keytoolArguments.add("-ext"); 13575 keytoolArguments.add("SAN=" + subjectAltNameValue); 13576 } 13577 13578 if (! ianValues.isEmpty()) 13579 { 13580 final StringBuilder issuerAltNameValue = new StringBuilder(); 13581 for (final String ianValue : ianValues) 13582 { 13583 commaAppend(issuerAltNameValue, ianValue); 13584 } 13585 13586 keytoolArguments.add("-ext"); 13587 keytoolArguments.add("IAN=" + issuerAltNameValue); 13588 } 13589 13590 for (final X509CertificateExtension e : genericExtensions) 13591 { 13592 keytoolArguments.add("-ext"); 13593 if (e.isCritical()) 13594 { 13595 keytoolArguments.add(e.getOID().toString() + ":critical=" + 13596 toColonDelimitedHex(e.getValue())); 13597 } 13598 else 13599 { 13600 keytoolArguments.add(e.getOID().toString() + '=' + 13601 toColonDelimitedHex(e.getValue())); 13602 } 13603 } 13604 } 13605 13606 13607 13608 /** 13609 * Appends the provided value to the given buffer. If the buffer is not 13610 * empty, the new value will be preceded by a comma. There will not be any 13611 * spaces on either side of the comma. 13612 * 13613 * @param buffer The buffer to which the value should be appended. 13614 * @param value The value to append to the buffer. 13615 */ 13616 private static void commaAppend(@NotNull final StringBuilder buffer, 13617 @NotNull final String value) 13618 { 13619 if (buffer.length() > 0) 13620 { 13621 buffer.append(','); 13622 } 13623 13624 buffer.append(value); 13625 } 13626 13627 13628 13629 /** 13630 * Retrieves a set of information that may be used to generate example usage 13631 * information. Each element in the returned map should consist of a map 13632 * between an example set of arguments and a string that describes the 13633 * behavior of the tool when invoked with that set of arguments. 13634 * 13635 * @return A set of information that may be used to generate example usage 13636 * information. It may be {@code null} or empty if no example usage 13637 * information is available. 13638 */ 13639 @Override() 13640 @NotNull() 13641 public LinkedHashMap<String[],String> getExampleUsages() 13642 { 13643 final String keystorePath = getPlatformSpecificPath("config", "keystore"); 13644 final String keystorePWPath = 13645 getPlatformSpecificPath("config", "keystore.pin"); 13646 final String privateKeyPWPath = 13647 getPlatformSpecificPath("config", "server-cert-private-key.pin"); 13648 final String exportCertOutputFile = 13649 getPlatformSpecificPath("server-cert.crt"); 13650 final String exportKeyOutputFile = 13651 getPlatformSpecificPath("server-cert.private-key"); 13652 final String genCSROutputFile = getPlatformSpecificPath("server-cert.csr"); 13653 final String truststorePath = 13654 getPlatformSpecificPath("config", "truststore"); 13655 final String truststorePWPath = 13656 getPlatformSpecificPath("config", "truststore.pin"); 13657 13658 final LinkedHashMap<String[],String> examples = 13659 new LinkedHashMap<>(StaticUtils.computeMapCapacity(20)); 13660 13661 examples.put( 13662 new String[] 13663 { 13664 "list-certificates", 13665 "--keystore", keystorePath, 13666 "--keystore-password-file", keystorePWPath, 13667 "--verbose", 13668 "--display-keytool-command" 13669 }, 13670 INFO_MANAGE_CERTS_EXAMPLE_LIST_1.get(keystorePath)); 13671 13672 examples.put( 13673 new String[] 13674 { 13675 "export-certificate", 13676 "--keystore", keystorePath, 13677 "--keystore-password-file", keystorePWPath, 13678 "--alias", "server-cert", 13679 "--output-file", exportCertOutputFile, 13680 "--output-format", "PEM", 13681 "--verbose", 13682 "--display-keytool-command" 13683 }, 13684 INFO_MANAGE_CERTS_EXAMPLE_EXPORT_CERT_1.get(keystorePath, 13685 exportCertOutputFile)); 13686 13687 examples.put( 13688 new String[] 13689 { 13690 "export-private-key", 13691 "--keystore", keystorePath, 13692 "--keystore-password-file", keystorePWPath, 13693 "--private-key-password-file", privateKeyPWPath, 13694 "--alias", "server-cert", 13695 "--output-file", exportKeyOutputFile, 13696 "--output-format", "PEM", 13697 "--verbose", 13698 "--display-keytool-command" 13699 }, 13700 INFO_MANAGE_CERTS_EXAMPLE_EXPORT_KEY_1.get(keystorePath, 13701 exportKeyOutputFile)); 13702 13703 examples.put( 13704 new String[] 13705 { 13706 "import-certificate", 13707 "--keystore", keystorePath, 13708 "--keystore-type", "JKS", 13709 "--keystore-password-file", keystorePWPath, 13710 "--alias", "server-cert", 13711 "--certificate-file", exportCertOutputFile, 13712 "--private-key-file", exportKeyOutputFile, 13713 "--display-keytool-command" 13714 }, 13715 INFO_MANAGE_CERTS_EXAMPLE_IMPORT_1.get(exportCertOutputFile, 13716 exportKeyOutputFile, keystorePath)); 13717 13718 examples.put( 13719 new String[] 13720 { 13721 "delete-certificate", 13722 "--keystore", keystorePath, 13723 "--keystore-password-file", keystorePWPath, 13724 "--alias", "server-cert" 13725 }, 13726 INFO_MANAGE_CERTS_EXAMPLE_DELETE_1.get(keystorePath)); 13727 13728 examples.put( 13729 new String[] 13730 { 13731 "generate-self-signed-certificate", 13732 "--keystore", keystorePath, 13733 "--keystore-type", "PKCS12", 13734 "--keystore-password-file", keystorePWPath, 13735 "--alias", "ca-cert", 13736 "--subject-dn", "CN=Example Authority,O=Example Corporation,C=US", 13737 "--days-valid", "7300", 13738 "--validity-start-time", "20170101000000", 13739 "--key-algorithm", "RSA", 13740 "--key-size-bits", "4096", 13741 "--signature-algorithm", "SHA256withRSA", 13742 "--basic-constraints-is-ca", "true", 13743 "--key-usage", "key-cert-sign", 13744 "--key-usage", "crl-sign", 13745 "--display-keytool-command" 13746 }, 13747 INFO_MANAGE_CERTS_EXAMPLE_GEN_CERT_1.get(keystorePath)); 13748 13749 examples.put( 13750 new String[] 13751 { 13752 "generate-certificate-signing-request", 13753 "--keystore", keystorePath, 13754 "--keystore-type", "PKCS12", 13755 "--keystore-password-file", keystorePWPath, 13756 "--output-file", genCSROutputFile, 13757 "--alias", "server-cert", 13758 "--subject-dn", "CN=ldap.example.com,O=Example Corporation,C=US", 13759 "--key-algorithm", "EC", 13760 "--key-size-bits", "256", 13761 "--signature-algorithm", "SHA256withECDSA", 13762 "--subject-alternative-name-dns", "ldap1.example.com", 13763 "--subject-alternative-name-dns", "ldap2.example.com", 13764 "--extended-key-usage", "server-auth", 13765 "--extended-key-usage", "client-auth", 13766 "--display-keytool-command" 13767 }, 13768 INFO_MANAGE_CERTS_EXAMPLE_GEN_CSR_1.get(keystorePath, 13769 genCSROutputFile)); 13770 13771 examples.put( 13772 new String[] 13773 { 13774 "generate-certificate-signing-request", 13775 "--keystore", keystorePath, 13776 "--keystore-password-file", keystorePWPath, 13777 "--alias", "server-cert", 13778 "--use-existing-key-pair", 13779 "--inherit-extensions", 13780 "--display-keytool-command" 13781 }, 13782 INFO_MANAGE_CERTS_EXAMPLE_GEN_CSR_2.get(keystorePath)); 13783 13784 examples.put( 13785 new String[] 13786 { 13787 "sign-certificate-signing-request", 13788 "--keystore", keystorePath, 13789 "--keystore-password-file", keystorePWPath, 13790 "--request-input-file", genCSROutputFile, 13791 "--certificate-output-file", exportCertOutputFile, 13792 "--alias", "ca-cert", 13793 "--days-valid", "730", 13794 "--include-requested-extensions", 13795 "--display-keytool-command" 13796 }, 13797 INFO_MANAGE_CERTS_EXAMPLE_SIGN_CERT_1.get(keystorePath, 13798 genCSROutputFile, exportCertOutputFile)); 13799 13800 examples.put( 13801 new String[] 13802 { 13803 "change-certificate-alias", 13804 "--keystore", keystorePath, 13805 "--keystore-password-file", keystorePWPath, 13806 "--current-alias", "server-cert", 13807 "--new-alias", "server-certificate", 13808 "--display-keytool-command" 13809 }, 13810 INFO_MANAGE_CERTS_EXAMPLE_CHANGE_ALIAS_1.get(keystorePath, 13811 genCSROutputFile, exportCertOutputFile)); 13812 13813 examples.put( 13814 new String[] 13815 { 13816 "change-keystore-password", 13817 "--keystore", getPlatformSpecificPath("config", "keystore"), 13818 "--current-keystore-password-file", 13819 getPlatformSpecificPath("config", "current.pin"), 13820 "--new-keystore-password-file", 13821 getPlatformSpecificPath("config", "new.pin"), 13822 "--display-keytool-command" 13823 }, 13824 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_EXAMPLE_1.get( 13825 getPlatformSpecificPath("config", "keystore"), 13826 getPlatformSpecificPath("config", "current.pin"), 13827 getPlatformSpecificPath("config", "new.pin"))); 13828 13829 examples.put( 13830 new String[] 13831 { 13832 "retrieve-server-certificate", 13833 "--hostname", "ds.example.com", 13834 "--port", "636" 13835 }, 13836 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_1.get( 13837 getPlatformSpecificPath("config", "truststore"))); 13838 13839 examples.put( 13840 new String[] 13841 { 13842 "copy-keystore", 13843 "--source-keystore", 13844 getPlatformSpecificPath("config", "keystore.jks"), 13845 "--source-keystore-password-file", 13846 getPlatformSpecificPath("config", "keystore.pin"), 13847 "--source-keystore-type", "JKS", 13848 "--destination-keystore", 13849 getPlatformSpecificPath("config", "keystore.p12"), 13850 "--destination-keystore-password-file", 13851 getPlatformSpecificPath("config", "keystore.pin"), 13852 "--destination-keystore-type", "PKCS12" 13853 }, 13854 INFO_MANAGE_CERTS_SC_COPY_KS_EXAMPLE_1.get("keystore.jks", 13855 "keystore.p12")); 13856 13857 examples.put( 13858 new String[] 13859 { 13860 "trust-server-certificate", 13861 "--hostname", "ldap.example.com", 13862 "--port", "636", 13863 "--keystore", truststorePath, 13864 "--keystore-password-file", truststorePWPath, 13865 "--alias", "ldap.example.com:636" 13866 }, 13867 INFO_MANAGE_CERTS_EXAMPLE_TRUST_SERVER_1.get(truststorePath)); 13868 13869 examples.put( 13870 new String[] 13871 { 13872 "check-certificate-usability", 13873 "--keystore", keystorePath, 13874 "--keystore-password-file", keystorePWPath, 13875 "--alias", "server-cert" 13876 }, 13877 INFO_MANAGE_CERTS_EXAMPLE_CHECK_USABILITY_1.get(keystorePath)); 13878 13879 examples.put( 13880 new String[] 13881 { 13882 "display-certificate-file", 13883 "--certificate-file", exportCertOutputFile, 13884 "--verbose", 13885 "--display-keytool-command" 13886 }, 13887 INFO_MANAGE_CERTS_EXAMPLE_DISPLAY_CERT_1.get(keystorePath)); 13888 13889 examples.put( 13890 new String[] 13891 { 13892 "display-certificate-signing-request-file", 13893 "--certificate-signing-request-file", genCSROutputFile, 13894 "--display-keytool-command" 13895 }, 13896 INFO_MANAGE_CERTS_EXAMPLE_DISPLAY_CSR_1.get(keystorePath)); 13897 13898 examples.put( 13899 new String[] 13900 { 13901 "--help-subcommands" 13902 }, 13903 INFO_MANAGE_CERTS_EXAMPLE_HELP_SUBCOMMANDS_1.get(keystorePath)); 13904 13905 return examples; 13906 } 13907}