001/* 002 * Copyright 2017-2026 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2017-2026 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-2026 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 importCertSkipValidation = new BooleanArgument(null, 1282 "skip-validation", 1, 1283 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_SKIP_VALIDATION_DESC.get()); 1284 importCertSkipValidation.addLongIdentifier("skipValidation", true); 1285 importCertSkipValidation.setHidden(true); 1286 importCertParser.addArgument(importCertSkipValidation); 1287 1288 final BooleanArgument importCertDisplayCommand = new BooleanArgument(null, 1289 "display-keytool-command", 1, 1290 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1291 importCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1292 importCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1293 importCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1294 importCertParser.addArgument(importCertDisplayCommand); 1295 1296 importCertParser.addRequiredArgumentSet(importCertKeystorePassword, 1297 importCertKeystorePasswordFile, importCertPromptForKeystorePassword); 1298 importCertParser.addExclusiveArgumentSet(importCertKeystorePassword, 1299 importCertKeystorePasswordFile, importCertPromptForKeystorePassword); 1300 importCertParser.addExclusiveArgumentSet(importCertPKPassword, 1301 importCertPKPasswordFile, importCertPromptForPKPassword); 1302 importCertParser.addExclusiveArgumentSet(importCertEncryptionPassword, 1303 importCertEncryptionPasswordFile, 1304 importCertPromptForEncryptionPassword); 1305 1306 final LinkedHashMap<String[],String> importCertExamples = 1307 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 1308 importCertExamples.put( 1309 new String[] 1310 { 1311 "import-certificate", 1312 "--keystore", getPlatformSpecificPath("config", "keystore"), 1313 "--keystore-password-file", 1314 getPlatformSpecificPath("config", "keystore.pin"), 1315 "--alias", "server-cert", 1316 "--certificate-file", "server-cert.crt" 1317 }, 1318 INFO_MANAGE_CERTS_SC_IMPORT_CERT_EXAMPLE_1.get("server-cert.crt")); 1319 importCertExamples.put( 1320 new String[] 1321 { 1322 "import-certificate", 1323 "--keystore", getPlatformSpecificPath("config", "keystore"), 1324 "--keystore-password-file", 1325 getPlatformSpecificPath("config", "keystore.pin"), 1326 "--alias", "server-cert", 1327 "--certificate-file", "server-cert.crt", 1328 "--certificate-file", "server-cert-issuer.crt", 1329 "--private-key-file", "server-cert.key", 1330 "--display-keytool-command" 1331 }, 1332 INFO_MANAGE_CERTS_SC_IMPORT_CERT_EXAMPLE_2.get()); 1333 1334 final SubCommand importCertSubCommand = new SubCommand("import-certificate", 1335 INFO_MANAGE_CERTS_SC_IMPORT_CERT_DESC.get(), importCertParser, 1336 importCertExamples); 1337 importCertSubCommand.addName("importCertificate", true); 1338 importCertSubCommand.addName("import-certificates", true); 1339 importCertSubCommand.addName("importCertificates", true); 1340 importCertSubCommand.addName("import-cert", true); 1341 importCertSubCommand.addName("importCert", true); 1342 importCertSubCommand.addName("import-certs", true); 1343 importCertSubCommand.addName("importCerts", true); 1344 importCertSubCommand.addName("import-certificate-chain", true); 1345 importCertSubCommand.addName("importCertificateChain", true); 1346 importCertSubCommand.addName("import-chain", true); 1347 importCertSubCommand.addName("importChain", true); 1348 importCertSubCommand.addName("import", true); 1349 1350 parser.addSubCommand(importCertSubCommand); 1351 1352 1353 // Define the "delete-certificate" subcommand and all of its arguments. 1354 final ArgumentParser deleteCertParser = new ArgumentParser( 1355 "delete-certificate", INFO_MANAGE_CERTS_SC_DELETE_CERT_DESC.get()); 1356 1357 final FileArgument deleteCertKeystore = new FileArgument(null, "keystore", 1358 true, 1, null, INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_DESC.get(), 1359 true, true, true, false); 1360 deleteCertKeystore.addLongIdentifier("keystore-path", true); 1361 deleteCertKeystore.addLongIdentifier("keystorePath", true); 1362 deleteCertKeystore.addLongIdentifier("keystore-file", true); 1363 deleteCertKeystore.addLongIdentifier("keystoreFile", true); 1364 deleteCertParser.addArgument(deleteCertKeystore); 1365 1366 final StringArgument deleteCertKeystorePassword = new StringArgument(null, 1367 "keystore-password", false, 1, 1368 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1369 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_PW_DESC.get()); 1370 deleteCertKeystorePassword.addLongIdentifier("keystorePassword", true); 1371 deleteCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 1372 deleteCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 1373 deleteCertKeystorePassword.addLongIdentifier("keystore-pin", true); 1374 deleteCertKeystorePassword.addLongIdentifier("keystorePIN", true); 1375 deleteCertKeystorePassword.addLongIdentifier("storepass", true); 1376 deleteCertKeystorePassword.setSensitive(true); 1377 deleteCertParser.addArgument(deleteCertKeystorePassword); 1378 1379 final FileArgument deleteCertKeystorePasswordFile = new FileArgument(null, 1380 "keystore-password-file", false, 1, null, 1381 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 1382 true, false); 1383 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 1384 true); 1385 deleteCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 1386 true); 1387 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 1388 true); 1389 deleteCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 1390 true); 1391 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 1392 deleteCertParser.addArgument(deleteCertKeystorePasswordFile); 1393 1394 final BooleanArgument deleteCertPromptForKeystorePassword = 1395 new BooleanArgument(null, "prompt-for-keystore-password", 1396 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 1397 deleteCertPromptForKeystorePassword.addLongIdentifier( 1398 "promptForKeystorePassword", true); 1399 deleteCertPromptForKeystorePassword.addLongIdentifier( 1400 "prompt-for-keystore-passphrase", true); 1401 deleteCertPromptForKeystorePassword.addLongIdentifier( 1402 "promptForKeystorePassphrase", true); 1403 deleteCertPromptForKeystorePassword.addLongIdentifier( 1404 "prompt-for-keystore-pin", true); 1405 deleteCertPromptForKeystorePassword.addLongIdentifier( 1406 "promptForKeystorePIN", true); 1407 deleteCertParser.addArgument(deleteCertPromptForKeystorePassword); 1408 1409 final StringArgument deleteCertKeystoreType = new StringArgument(null, 1410 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 1411 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_TYPE_DESC.get(), 1412 ALLOWED_KEYSTORE_TYPE_VALUES); 1413 deleteCertKeystoreType.addLongIdentifier("key-store-type", true); 1414 deleteCertKeystoreType.addLongIdentifier("keystoreType", true); 1415 deleteCertKeystoreType.addLongIdentifier("keystore-format", true); 1416 deleteCertKeystoreType.addLongIdentifier("key-store-format", true); 1417 deleteCertKeystoreType.addLongIdentifier("keystoreFormat", true); 1418 deleteCertKeystoreType.addLongIdentifier("storetype", true); 1419 deleteCertParser.addArgument(deleteCertKeystoreType); 1420 1421 final StringArgument deleteCertAlias = new StringArgument(null, "alias", 1422 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 1423 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_ALIAS_DESC.get()); 1424 deleteCertAlias.addLongIdentifier("nickname", true); 1425 deleteCertParser.addArgument(deleteCertAlias); 1426 1427 final BooleanArgument deleteCertNoPrompt = new BooleanArgument(null, 1428 "no-prompt", 1, 1429 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_NO_PROMPT_DESC.get()); 1430 deleteCertNoPrompt.addLongIdentifier("noPrompt", true); 1431 deleteCertParser.addArgument(deleteCertNoPrompt); 1432 1433 final BooleanArgument deleteCertDisplayCommand = new BooleanArgument(null, 1434 "display-keytool-command", 1, 1435 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1436 deleteCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1437 deleteCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1438 deleteCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1439 deleteCertParser.addArgument(deleteCertDisplayCommand); 1440 1441 deleteCertParser.addExclusiveArgumentSet(deleteCertKeystorePassword, 1442 deleteCertKeystorePasswordFile, deleteCertPromptForKeystorePassword); 1443 deleteCertParser.addRequiredArgumentSet(deleteCertKeystorePassword, 1444 deleteCertKeystorePasswordFile, deleteCertPromptForKeystorePassword); 1445 1446 final LinkedHashMap<String[],String> deleteCertExamples = 1447 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 1448 deleteCertExamples.put( 1449 new String[] 1450 { 1451 "delete-certificate", 1452 "--keystore", getPlatformSpecificPath("config", "keystore"), 1453 "--alias", "server-cert" 1454 }, 1455 INFO_MANAGE_CERTS_SC_DELETE_CERT_EXAMPLE_1.get( 1456 getPlatformSpecificPath("config", "keystore"))); 1457 1458 final SubCommand deleteCertSubCommand = new SubCommand("delete-certificate", 1459 INFO_MANAGE_CERTS_SC_DELETE_CERT_DESC.get(), deleteCertParser, 1460 deleteCertExamples); 1461 deleteCertSubCommand.addName("deleteCertificate", true); 1462 deleteCertSubCommand.addName("remove-certificate", true); 1463 deleteCertSubCommand.addName("removeCertificate", true); 1464 deleteCertSubCommand.addName("delete", true); 1465 deleteCertSubCommand.addName("remove", true); 1466 1467 parser.addSubCommand(deleteCertSubCommand); 1468 1469 1470 // Define the "generate-self-signed-certificate" subcommand and all of its 1471 // arguments. 1472 final ArgumentParser genCertParser = new ArgumentParser( 1473 "generate-self-signed-certificate", 1474 INFO_MANAGE_CERTS_SC_GEN_CERT_DESC.get()); 1475 1476 final FileArgument genCertKeystore = new FileArgument(null, "keystore", 1477 true, 1, null, INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_DESC.get(), false, 1478 true, true, false); 1479 genCertKeystore.addLongIdentifier("keystore-path", true); 1480 genCertKeystore.addLongIdentifier("keystorePath", true); 1481 genCertKeystore.addLongIdentifier("keystore-file", true); 1482 genCertKeystore.addLongIdentifier("keystoreFile", true); 1483 genCertParser.addArgument(genCertKeystore); 1484 1485 final StringArgument genCertKeystorePassword = new StringArgument(null, 1486 "keystore-password", false, 1, 1487 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1488 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_PW_DESC.get()); 1489 genCertKeystorePassword.addLongIdentifier("keystorePassword", true); 1490 genCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 1491 genCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 1492 genCertKeystorePassword.addLongIdentifier("keystore-pin", true); 1493 genCertKeystorePassword.addLongIdentifier("keystorePIN", true); 1494 genCertKeystorePassword.addLongIdentifier("storepass", true); 1495 genCertKeystorePassword.setSensitive(true); 1496 genCertParser.addArgument(genCertKeystorePassword); 1497 1498 final FileArgument genCertKeystorePasswordFile = new FileArgument(null, 1499 "keystore-password-file", false, 1, null, 1500 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 1501 true, false); 1502 genCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 1503 true); 1504 genCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 1505 true); 1506 genCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 1507 true); 1508 genCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 1509 true); 1510 genCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 1511 genCertParser.addArgument(genCertKeystorePasswordFile); 1512 1513 final BooleanArgument genCertPromptForKeystorePassword = 1514 new BooleanArgument(null, "prompt-for-keystore-password", 1515 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 1516 genCertPromptForKeystorePassword.addLongIdentifier( 1517 "promptForKeystorePassword", true); 1518 genCertPromptForKeystorePassword.addLongIdentifier( 1519 "prompt-for-keystore-passphrase", true); 1520 genCertPromptForKeystorePassword.addLongIdentifier( 1521 "promptForKeystorePassphrase", true); 1522 genCertPromptForKeystorePassword.addLongIdentifier( 1523 "prompt-for-keystore-pin", true); 1524 genCertPromptForKeystorePassword.addLongIdentifier( 1525 "promptForKeystorePIN", true); 1526 genCertParser.addArgument(genCertPromptForKeystorePassword); 1527 1528 final StringArgument genCertPKPassword = new StringArgument(null, 1529 "private-key-password", false, 1, 1530 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1531 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PK_PW_DESC.get()); 1532 genCertPKPassword.addLongIdentifier("privateKeyPassword", true); 1533 genCertPKPassword.addLongIdentifier("private-key-passphrase", true); 1534 genCertPKPassword.addLongIdentifier("privateKeyPassphrase", true); 1535 genCertPKPassword.addLongIdentifier("private-key-pin", true); 1536 genCertPKPassword.addLongIdentifier("privateKeyPIN", true); 1537 genCertPKPassword.addLongIdentifier("key-password", true); 1538 genCertPKPassword.addLongIdentifier("keyPassword", true); 1539 genCertPKPassword.addLongIdentifier("key-passphrase", true); 1540 genCertPKPassword.addLongIdentifier("keyPassphrase", true); 1541 genCertPKPassword.addLongIdentifier("key-pin", true); 1542 genCertPKPassword.addLongIdentifier("keyPIN", true); 1543 genCertPKPassword.addLongIdentifier("keypass", true); 1544 genCertPKPassword.setSensitive(true); 1545 genCertParser.addArgument(genCertPKPassword); 1546 1547 final FileArgument genCertPKPasswordFile = new FileArgument(null, 1548 "private-key-password-file", false, 1, null, 1549 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PK_PW_FILE_DESC.get(), true, true, 1550 true, false); 1551 genCertPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 1552 genCertPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 1553 true); 1554 genCertPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 1555 true); 1556 genCertPKPasswordFile.addLongIdentifier("private-key-pin-file", 1557 true); 1558 genCertPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 1559 genCertPKPasswordFile.addLongIdentifier("key-password-file", true); 1560 genCertPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 1561 genCertPKPasswordFile.addLongIdentifier("key-passphrase-file", 1562 true); 1563 genCertPKPasswordFile.addLongIdentifier("keyPassphraseFile", 1564 true); 1565 genCertPKPasswordFile.addLongIdentifier("key-pin-file", 1566 true); 1567 genCertPKPasswordFile.addLongIdentifier("keyPINFile", true); 1568 genCertParser.addArgument(genCertPKPasswordFile); 1569 1570 final BooleanArgument genCertPromptForPKPassword = 1571 new BooleanArgument(null, "prompt-for-private-key-password", 1572 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PROMPT_FOR_PK_PW_DESC.get()); 1573 genCertPromptForPKPassword.addLongIdentifier( 1574 "promptForPrivateKeyPassword", true); 1575 genCertPromptForPKPassword.addLongIdentifier( 1576 "prompt-for-private-key-passphrase", true); 1577 genCertPromptForPKPassword.addLongIdentifier( 1578 "promptForPrivateKeyPassphrase", true); 1579 genCertPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 1580 true); 1581 genCertPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 1582 true); 1583 genCertPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 1584 true); 1585 genCertPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 1586 true); 1587 genCertPromptForPKPassword.addLongIdentifier( 1588 "prompt-for-key-passphrase", true); 1589 genCertPromptForPKPassword.addLongIdentifier( 1590 "promptForKeyPassphrase", true); 1591 genCertPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 1592 genCertPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 1593 genCertParser.addArgument(genCertPromptForPKPassword); 1594 1595 final StringArgument genCertKeystoreType = new StringArgument(null, 1596 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 1597 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_TYPE_DESC.get(), 1598 ALLOWED_KEYSTORE_TYPE_VALUES); 1599 genCertKeystoreType.addLongIdentifier("key-store-type", true); 1600 genCertKeystoreType.addLongIdentifier("keystoreType", true); 1601 genCertKeystoreType.addLongIdentifier("keystore-format", true); 1602 genCertKeystoreType.addLongIdentifier("key-store-format", true); 1603 genCertKeystoreType.addLongIdentifier("keystoreFormat", true); 1604 genCertKeystoreType.addLongIdentifier("storetype", true); 1605 genCertParser.addArgument(genCertKeystoreType); 1606 1607 final StringArgument genCertAlias = new StringArgument(null, "alias", 1608 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 1609 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_ALIAS_DESC.get()); 1610 genCertAlias.addLongIdentifier("nickname", true); 1611 genCertParser.addArgument(genCertAlias); 1612 1613 final BooleanArgument genCertUseExistingKeyPair = new BooleanArgument(null, 1614 "use-existing-key-pair", 1, 1615 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_USE_EXISTING_KP_DESC.get()); 1616 genCertUseExistingKeyPair.addLongIdentifier("use-existing-keypair", true); 1617 genCertUseExistingKeyPair.addLongIdentifier("useExistingKeypair", true); 1618 genCertUseExistingKeyPair.addLongIdentifier("replace-existing-certificate", 1619 true); 1620 genCertUseExistingKeyPair.addLongIdentifier("replaceExistingCertificate", 1621 true); 1622 genCertUseExistingKeyPair.addLongIdentifier("replace-certificate", true); 1623 genCertUseExistingKeyPair.addLongIdentifier("replaceCertificate", true); 1624 genCertUseExistingKeyPair.addLongIdentifier("replace-existing", true); 1625 genCertUseExistingKeyPair.addLongIdentifier("replaceExisting", true); 1626 genCertUseExistingKeyPair.addLongIdentifier("replace", true); 1627 genCertParser.addArgument(genCertUseExistingKeyPair); 1628 1629 final DNArgument genCertSubjectDN = new DNArgument(null, "subject-dn", 1630 false, 1, null, 1631 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SUBJECT_DN_DESC.get()); 1632 genCertSubjectDN.addLongIdentifier("subjectDN", true); 1633 genCertSubjectDN.addLongIdentifier("subject", true); 1634 genCertSubjectDN.addLongIdentifier("dname", true); 1635 genCertParser.addArgument(genCertSubjectDN); 1636 1637 final IntegerArgument genCertDaysValid = new IntegerArgument(null, 1638 "days-valid", false, 1, null, 1639 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_DAYS_VALID_DESC.get(), 1, 1640 Integer.MAX_VALUE); 1641 genCertDaysValid.addLongIdentifier("daysValid", true); 1642 genCertDaysValid.addLongIdentifier("validity", true); 1643 genCertParser.addArgument(genCertDaysValid); 1644 1645 final TimestampArgument genCertNotBefore = new TimestampArgument(null, 1646 "validity-start-time", false, 1, 1647 INFO_MANAGE_CERTS_PLACEHOLDER_TIMESTAMP.get(), 1648 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_VALIDITY_START_TIME_DESC.get( 1649 "20180102123456")); 1650 genCertNotBefore.addLongIdentifier("validityStartTime", true); 1651 genCertNotBefore.addLongIdentifier("not-before", true); 1652 genCertNotBefore.addLongIdentifier("notBefore", true); 1653 genCertParser.addArgument(genCertNotBefore); 1654 1655 final StringArgument genCertKeyAlgorithm = new StringArgument(null, 1656 "key-algorithm", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1657 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KEY_ALGORITHM_DESC.get()); 1658 genCertKeyAlgorithm.addLongIdentifier("keyAlgorithm", true); 1659 genCertKeyAlgorithm.addLongIdentifier("key-alg", true); 1660 genCertKeyAlgorithm.addLongIdentifier("keyAlg", true); 1661 genCertParser.addArgument(genCertKeyAlgorithm); 1662 1663 final IntegerArgument genCertKeySizeBits = new IntegerArgument(null, 1664 "key-size-bits", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_BITS.get(), 1665 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KEY_SIZE_BITS_DESC.get(), 1, 1666 Integer.MAX_VALUE); 1667 genCertKeySizeBits.addLongIdentifier("keySizeBits", true); 1668 genCertKeySizeBits.addLongIdentifier("key-length-bits", true); 1669 genCertKeySizeBits.addLongIdentifier("keyLengthBits", true); 1670 genCertKeySizeBits.addLongIdentifier("key-size", true); 1671 genCertKeySizeBits.addLongIdentifier("keySize", true); 1672 genCertKeySizeBits.addLongIdentifier("key-length", true); 1673 genCertKeySizeBits.addLongIdentifier("keyLength", true); 1674 genCertParser.addArgument(genCertKeySizeBits); 1675 1676 final StringArgument genCertSignatureAlgorithm = new StringArgument(null, 1677 "signature-algorithm", false, 1, 1678 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1679 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SIG_ALG_DESC.get()); 1680 genCertSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 1681 genCertSignatureAlgorithm.addLongIdentifier("signature-alg", true); 1682 genCertSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 1683 genCertSignatureAlgorithm.addLongIdentifier("sig-alg", true); 1684 genCertSignatureAlgorithm.addLongIdentifier("sigAlg", true); 1685 genCertParser.addArgument(genCertSignatureAlgorithm); 1686 1687 final BooleanArgument genCertInheritExtensions = new BooleanArgument(null, 1688 "inherit-extensions", 1, 1689 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_INHERIT_EXT_DESC.get()); 1690 genCertInheritExtensions.addLongIdentifier("inheritExtensions", true); 1691 genCertParser.addArgument(genCertInheritExtensions); 1692 1693 final StringArgument genCertSubjectAltDNS = new StringArgument(null, 1694 "subject-alternative-name-dns", false, 0, 1695 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1696 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_DNS_DESC.get()); 1697 genCertSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 1698 genCertSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 1699 genCertSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 1700 genCertSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 1701 genCertSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 1702 genCertSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 1703 genCertSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 1704 genCertSubjectAltDNS.addLongIdentifier("san-dns", true); 1705 genCertSubjectAltDNS.addLongIdentifier("sanDNS", true); 1706 genCertSubjectAltDNS.addValueValidator( 1707 new IA5StringArgumentValueValidator(false)); 1708 genCertParser.addArgument(genCertSubjectAltDNS); 1709 1710 final StringArgument genCertSubjectAltIP = new StringArgument(null, 1711 "subject-alternative-name-ip-address", false, 0, 1712 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1713 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_IP_DESC.get()); 1714 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 1715 true); 1716 genCertSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 1717 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 1718 genCertSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 1719 genCertSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 1720 genCertSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 1721 genCertSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 1722 genCertSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 1723 true); 1724 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 1725 genCertSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 1726 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 1727 genCertSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 1728 genCertSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 1729 genCertSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 1730 genCertSubjectAltIP.addLongIdentifier("subjectAltIP", true); 1731 genCertSubjectAltIP.addLongIdentifier("san-ip-address", true); 1732 genCertSubjectAltIP.addLongIdentifier("sanIPAddress", true); 1733 genCertSubjectAltIP.addLongIdentifier("san-ip", true); 1734 genCertSubjectAltIP.addLongIdentifier("sanIP", true); 1735 genCertSubjectAltIP.addValueValidator( 1736 new IPAddressArgumentValueValidator(true, true)); 1737 genCertParser.addArgument(genCertSubjectAltIP); 1738 1739 final StringArgument genCertSubjectAltEmail = new StringArgument(null, 1740 "subject-alternative-name-email-address", false, 0, 1741 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1742 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_EMAIL_DESC.get()); 1743 genCertSubjectAltEmail.addLongIdentifier( 1744 "subjectAlternativeNameEmailAddress", true); 1745 genCertSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 1746 true); 1747 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 1748 true); 1749 genCertSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 1750 true); 1751 genCertSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 1752 true); 1753 genCertSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 1754 genCertSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 1755 genCertSubjectAltEmail.addLongIdentifier( 1756 "subject-alternative-email-address", true); 1757 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 1758 true); 1759 genCertSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 1760 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 1761 genCertSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 1762 genCertSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 1763 genCertSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 1764 genCertSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 1765 genCertSubjectAltEmail.addLongIdentifier("san-email-address", true); 1766 genCertSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 1767 genCertSubjectAltEmail.addLongIdentifier("san-email", true); 1768 genCertSubjectAltEmail.addLongIdentifier("sanEmail", true); 1769 genCertSubjectAltEmail.addValueValidator( 1770 new IA5StringArgumentValueValidator(false)); 1771 genCertParser.addArgument(genCertSubjectAltEmail); 1772 1773 final StringArgument genCertSubjectAltURI = new StringArgument(null, 1774 "subject-alternative-name-uri", false, 0, 1775 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 1776 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_URI_DESC.get()); 1777 genCertSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 1778 genCertSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 1779 genCertSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 1780 genCertSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 1781 genCertSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 1782 genCertSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 1783 genCertSubjectAltURI.addLongIdentifier("subjectAltURI", true); 1784 genCertSubjectAltURI.addLongIdentifier("san-uri", true); 1785 genCertSubjectAltURI.addLongIdentifier("sanURI", true); 1786 genCertParser.addArgument(genCertSubjectAltURI); 1787 1788 final StringArgument genCertSubjectAltOID = new StringArgument(null, 1789 "subject-alternative-name-oid", false, 0, 1790 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 1791 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_OID_DESC.get()); 1792 genCertSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 1793 genCertSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 1794 genCertSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 1795 genCertSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 1796 genCertSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 1797 genCertSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 1798 genCertSubjectAltOID.addLongIdentifier("subjectAltOID", true); 1799 genCertSubjectAltOID.addLongIdentifier("san-oid", true); 1800 genCertSubjectAltOID.addLongIdentifier("sanOID", true); 1801 genCertSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 1802 genCertParser.addArgument(genCertSubjectAltOID); 1803 1804 final BooleanValueArgument genCertBasicConstraintsIsCA = 1805 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 1806 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_IS_CA_DESC.get()); 1807 genCertBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 1808 genCertBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 1809 genCertBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 1810 genCertParser.addArgument(genCertBasicConstraintsIsCA); 1811 1812 final IntegerArgument genCertBasicConstraintsPathLength = 1813 new IntegerArgument(null, "basic-constraints-maximum-path-length", 1814 false, 1, null, 1815 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 1816 Integer.MAX_VALUE); 1817 genCertBasicConstraintsPathLength.addLongIdentifier( 1818 "basicConstraintsMaximumPathLength", true); 1819 genCertBasicConstraintsPathLength.addLongIdentifier( 1820 "basic-constraints-max-path-length", true); 1821 genCertBasicConstraintsPathLength.addLongIdentifier( 1822 "basicConstraintsMaxPathLength", true); 1823 genCertBasicConstraintsPathLength.addLongIdentifier( 1824 "basic-constraints-path-length", true); 1825 genCertBasicConstraintsPathLength.addLongIdentifier( 1826 "basicConstraintsPathLength", true); 1827 genCertBasicConstraintsPathLength.addLongIdentifier( 1828 "bc-maximum-path-length", true); 1829 genCertBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 1830 true); 1831 genCertBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 1832 true); 1833 genCertBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 1834 true); 1835 genCertBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 1836 genCertBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 1837 genCertParser.addArgument(genCertBasicConstraintsPathLength); 1838 1839 final StringArgument genCertKeyUsage = new StringArgument(null, "key-usage", 1840 false, 0, null, INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KU_DESC.get()); 1841 genCertKeyUsage.addLongIdentifier("keyUsage", true); 1842 genCertParser.addArgument(genCertKeyUsage); 1843 1844 final StringArgument genCertExtendedKeyUsage = new StringArgument(null, 1845 "extended-key-usage", false, 0, null, 1846 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_EKU_DESC.get()); 1847 genCertExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 1848 genCertParser.addArgument(genCertExtendedKeyUsage); 1849 1850 final StringArgument genCertExtension = new StringArgument(null, 1851 "extension", false, 0, null, 1852 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_EXT_DESC.get()); 1853 genCertExtension.addLongIdentifier("ext", true); 1854 genCertParser.addArgument(genCertExtension); 1855 1856 final FileArgument genCertOutputFile = new FileArgument(null, "output-file", 1857 false, 1, null, 1858 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_OUTPUT_FILE_DESC.get(), false, true, 1859 true, false); 1860 genCertOutputFile.addLongIdentifier("outputFile", true); 1861 genCertOutputFile.addLongIdentifier("filename", true); 1862 genCertOutputFile.addLongIdentifier("file", true); 1863 genCertParser.addArgument(genCertOutputFile); 1864 1865 final Set<String> genCertOutputFormatAllowedValues = StaticUtils.setOf( 1866 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 1867 final StringArgument genCertOutputFormat = new StringArgument(null, 1868 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 1869 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_FORMAT_DESC.get(), 1870 genCertOutputFormatAllowedValues, "PEM"); 1871 genCertOutputFormat.addLongIdentifier("outputFormat", true); 1872 genCertParser.addArgument(genCertOutputFormat); 1873 1874 final BooleanArgument genCertDisplayCommand = new BooleanArgument(null, 1875 "display-keytool-command", 1, 1876 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1877 genCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1878 genCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1879 genCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1880 genCertParser.addArgument(genCertDisplayCommand); 1881 1882 genCertParser.addRequiredArgumentSet(genCertKeystorePassword, 1883 genCertKeystorePasswordFile, genCertPromptForKeystorePassword); 1884 genCertParser.addExclusiveArgumentSet(genCertKeystorePassword, 1885 genCertKeystorePasswordFile, genCertPromptForKeystorePassword); 1886 genCertParser.addExclusiveArgumentSet(genCertPKPassword, 1887 genCertPKPasswordFile, genCertPromptForPKPassword); 1888 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1889 genCertKeyAlgorithm); 1890 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1891 genCertKeySizeBits); 1892 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1893 genCertSignatureAlgorithm); 1894 genCertParser.addDependentArgumentSet(genCertBasicConstraintsPathLength, 1895 genCertBasicConstraintsIsCA); 1896 genCertParser.addDependentArgumentSet(genCertOutputFormat, 1897 genCertOutputFile); 1898 1899 final LinkedHashMap<String[],String> genCertExamples = 1900 new LinkedHashMap<>(StaticUtils.computeMapCapacity(4)); 1901 genCertExamples.put( 1902 new String[] 1903 { 1904 "generate-self-signed-certificate", 1905 "--keystore", getPlatformSpecificPath("config", "keystore"), 1906 "--keystore-password-file", 1907 getPlatformSpecificPath("config", "keystore.pin"), 1908 "--alias", "server-cert", 1909 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US" 1910 }, 1911 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_1.get()); 1912 genCertExamples.put( 1913 new String[] 1914 { 1915 "generate-self-signed-certificate", 1916 "--keystore", getPlatformSpecificPath("config", "keystore"), 1917 "--keystore-password-file", 1918 getPlatformSpecificPath("config", "keystore.pin"), 1919 "--alias", "server-cert", 1920 "--use-existing-key-pair", 1921 "--inherit-extensions" 1922 }, 1923 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_2.get()); 1924 genCertExamples.put( 1925 new String[] 1926 { 1927 "generate-self-signed-certificate", 1928 "--keystore", getPlatformSpecificPath("config", "keystore"), 1929 "--keystore-password-file", 1930 getPlatformSpecificPath("config", "keystore.pin"), 1931 "--alias", "server-cert", 1932 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US", 1933 "--days-valid", "3650", 1934 "--validity-start-time", "20170101000000", 1935 "--key-algorithm", "RSA", 1936 "--key-size-bits", "4096", 1937 "--signature-algorithm", "SHA256withRSA", 1938 "--subject-alternative-name-dns", "ldap1.example.com", 1939 "--subject-alternative-name-dns", "ldap2.example.com", 1940 "--subject-alternative-name-ip-address", "1.2.3.4", 1941 "--subject-alternative-name-ip-address", "1.2.3.5", 1942 "--extended-key-usage", "server-auth", 1943 "--extended-key-usage", "client-auth", 1944 "--display-keytool-command" 1945 }, 1946 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_3.get()); 1947 genCertExamples.put( 1948 new String[] 1949 { 1950 "generate-self-signed-certificate", 1951 "--keystore", getPlatformSpecificPath("config", "keystore"), 1952 "--keystore-password-file", 1953 getPlatformSpecificPath("config", "keystore.pin"), 1954 "--alias", "ca-cert", 1955 "--subject-dn", 1956 "CN=Example Certification Authority,O=Example Corp,C=US", 1957 "--days-valid", "7300", 1958 "--validity-start-time", "20170101000000", 1959 "--key-algorithm", "EC", 1960 "--key-size-bits", "256", 1961 "--signature-algorithm", "SHA256withECDSA", 1962 "--basic-constraints-is-ca", "true", 1963 "--key-usage", "key-cert-sign", 1964 "--key-usage", "crl-sign", 1965 "--display-keytool-command" 1966 }, 1967 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_4.get()); 1968 1969 final SubCommand genCertSubCommand = new SubCommand( 1970 "generate-self-signed-certificate", 1971 INFO_MANAGE_CERTS_SC_GEN_CERT_DESC.get(), genCertParser, 1972 genCertExamples); 1973 genCertSubCommand.addName("generateSelfSignedCertificate", true); 1974 genCertSubCommand.addName("generate-certificate", true); 1975 genCertSubCommand.addName("generateCertificate", true); 1976 genCertSubCommand.addName("self-signed-certificate", true); 1977 genCertSubCommand.addName("selfSignedCertificate", true); 1978 genCertSubCommand.addName("selfcert", true); 1979 1980 parser.addSubCommand(genCertSubCommand); 1981 1982 1983 // Define the "generate-certificate-signing-request" subcommand and all of 1984 // its arguments. 1985 final ArgumentParser genCSRParser = new ArgumentParser( 1986 "generate-certificate-signing-request", 1987 INFO_MANAGE_CERTS_SC_GEN_CSR_DESC.get()); 1988 1989 final Set<String> genCSROutputFormatAllowedValues = StaticUtils.setOf( 1990 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 1991 final StringArgument genCSROutputFormat = new StringArgument(null, 1992 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 1993 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_FORMAT_DESC.get(), 1994 genCSROutputFormatAllowedValues, "PEM"); 1995 genCSROutputFormat.addLongIdentifier("outputFormat", true); 1996 genCSRParser.addArgument(genCSROutputFormat); 1997 1998 final FileArgument genCSROutputFile = new FileArgument(null, "output-file", 1999 false, 1, null, 2000 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_OUTPUT_FILE_DESC.get(), false, true, 2001 true, false); 2002 genCSROutputFile.addLongIdentifier("outputFile", true); 2003 genCSROutputFile.addLongIdentifier("filename", true); 2004 genCSROutputFile.addLongIdentifier("file", true); 2005 genCSRParser.addArgument(genCSROutputFile); 2006 2007 final FileArgument genCSRKeystore = new FileArgument(null, "keystore", 2008 true, 1, null, INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_DESC.get(), false, 2009 true, true, false); 2010 genCSRKeystore.addLongIdentifier("keystore-path", true); 2011 genCSRKeystore.addLongIdentifier("keystorePath", true); 2012 genCSRKeystore.addLongIdentifier("keystore-file", true); 2013 genCSRKeystore.addLongIdentifier("keystoreFile", true); 2014 genCSRParser.addArgument(genCSRKeystore); 2015 2016 final StringArgument genCSRKeystorePassword = new StringArgument(null, 2017 "keystore-password", false, 1, 2018 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2019 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_PW_DESC.get()); 2020 genCSRKeystorePassword.addLongIdentifier("keystorePassword", true); 2021 genCSRKeystorePassword.addLongIdentifier("keystore-passphrase", true); 2022 genCSRKeystorePassword.addLongIdentifier("keystorePassphrase", true); 2023 genCSRKeystorePassword.addLongIdentifier("keystore-pin", true); 2024 genCSRKeystorePassword.addLongIdentifier("keystorePIN", true); 2025 genCSRKeystorePassword.addLongIdentifier("storepass", true); 2026 genCSRKeystorePassword.setSensitive(true); 2027 genCSRParser.addArgument(genCSRKeystorePassword); 2028 2029 final FileArgument genCSRKeystorePasswordFile = new FileArgument(null, 2030 "keystore-password-file", false, 1, null, 2031 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_PW_FILE_DESC.get(), true, true, 2032 true, false); 2033 genCSRKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 2034 true); 2035 genCSRKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 2036 true); 2037 genCSRKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 2038 true); 2039 genCSRKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 2040 true); 2041 genCSRKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 2042 genCSRParser.addArgument(genCSRKeystorePasswordFile); 2043 2044 final BooleanArgument genCSRPromptForKeystorePassword = 2045 new BooleanArgument(null, "prompt-for-keystore-password", 2046 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PROMPT_FOR_KS_PW_DESC.get()); 2047 genCSRPromptForKeystorePassword.addLongIdentifier( 2048 "promptForKeystorePassword", true); 2049 genCSRPromptForKeystorePassword.addLongIdentifier( 2050 "prompt-for-keystore-passphrase", true); 2051 genCSRPromptForKeystorePassword.addLongIdentifier( 2052 "promptForKeystorePassphrase", true); 2053 genCSRPromptForKeystorePassword.addLongIdentifier( 2054 "prompt-for-keystore-pin", true); 2055 genCSRPromptForKeystorePassword.addLongIdentifier( 2056 "promptForKeystorePIN", true); 2057 genCSRParser.addArgument(genCSRPromptForKeystorePassword); 2058 2059 final StringArgument genCSRPKPassword = new StringArgument(null, 2060 "private-key-password", false, 1, 2061 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2062 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PK_PW_DESC.get()); 2063 genCSRPKPassword.addLongIdentifier("privateKeyPassword", true); 2064 genCSRPKPassword.addLongIdentifier("private-key-passphrase", true); 2065 genCSRPKPassword.addLongIdentifier("privateKeyPassphrase", true); 2066 genCSRPKPassword.addLongIdentifier("private-key-pin", true); 2067 genCSRPKPassword.addLongIdentifier("privateKeyPIN", true); 2068 genCSRPKPassword.addLongIdentifier("key-password", true); 2069 genCSRPKPassword.addLongIdentifier("keyPassword", true); 2070 genCSRPKPassword.addLongIdentifier("key-passphrase", true); 2071 genCSRPKPassword.addLongIdentifier("keyPassphrase", true); 2072 genCSRPKPassword.addLongIdentifier("key-pin", true); 2073 genCSRPKPassword.addLongIdentifier("keyPIN", true); 2074 genCSRPKPassword.addLongIdentifier("keypass", true); 2075 genCSRPKPassword.setSensitive(true); 2076 genCSRParser.addArgument(genCSRPKPassword); 2077 2078 final FileArgument genCSRPKPasswordFile = new FileArgument(null, 2079 "private-key-password-file", false, 1, null, 2080 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PK_PW_FILE_DESC.get(), true, true, 2081 true, false); 2082 genCSRPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 2083 genCSRPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 2084 true); 2085 genCSRPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 2086 true); 2087 genCSRPKPasswordFile.addLongIdentifier("private-key-pin-file", 2088 true); 2089 genCSRPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 2090 genCSRPKPasswordFile.addLongIdentifier("key-password-file", true); 2091 genCSRPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 2092 genCSRPKPasswordFile.addLongIdentifier("key-passphrase-file", 2093 true); 2094 genCSRPKPasswordFile.addLongIdentifier("keyPassphraseFile", 2095 true); 2096 genCSRPKPasswordFile.addLongIdentifier("key-pin-file", 2097 true); 2098 genCSRPKPasswordFile.addLongIdentifier("keyPINFile", true); 2099 genCSRParser.addArgument(genCSRPKPasswordFile); 2100 2101 final BooleanArgument genCSRPromptForPKPassword = 2102 new BooleanArgument(null, "prompt-for-private-key-password", 2103 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PROMPT_FOR_PK_PW_DESC.get()); 2104 genCSRPromptForPKPassword.addLongIdentifier( 2105 "promptForPrivateKeyPassword", true); 2106 genCSRPromptForPKPassword.addLongIdentifier( 2107 "prompt-for-private-key-passphrase", true); 2108 genCSRPromptForPKPassword.addLongIdentifier( 2109 "promptForPrivateKeyPassphrase", true); 2110 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 2111 true); 2112 genCSRPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 2113 true); 2114 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 2115 true); 2116 genCSRPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 2117 true); 2118 genCSRPromptForPKPassword.addLongIdentifier( 2119 "prompt-for-key-passphrase", true); 2120 genCSRPromptForPKPassword.addLongIdentifier( 2121 "promptForKeyPassphrase", true); 2122 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 2123 genCSRPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 2124 genCSRParser.addArgument(genCSRPromptForPKPassword); 2125 2126 final StringArgument genCSRKeystoreType = new StringArgument(null, 2127 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 2128 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_TYPE_DESC.get(), 2129 ALLOWED_KEYSTORE_TYPE_VALUES); 2130 genCSRKeystoreType.addLongIdentifier("key-store-type", true); 2131 genCSRKeystoreType.addLongIdentifier("keystoreType", true); 2132 genCSRKeystoreType.addLongIdentifier("keystore-format", true); 2133 genCSRKeystoreType.addLongIdentifier("key-store-format", true); 2134 genCSRKeystoreType.addLongIdentifier("keystoreFormat", true); 2135 genCSRKeystoreType.addLongIdentifier("storetype", true); 2136 genCSRParser.addArgument(genCSRKeystoreType); 2137 2138 final StringArgument genCSRAlias = new StringArgument(null, "alias", 2139 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 2140 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_ALIAS_DESC.get()); 2141 genCSRAlias.addLongIdentifier("nickname", true); 2142 genCSRParser.addArgument(genCSRAlias); 2143 2144 final BooleanArgument genCSRUseExistingKeyPair = new BooleanArgument(null, 2145 "use-existing-key-pair", 1, 2146 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_USE_EXISTING_KP_DESC.get()); 2147 genCSRUseExistingKeyPair.addLongIdentifier("use-existing-keypair", true); 2148 genCSRUseExistingKeyPair.addLongIdentifier("useExistingKeyPair", true); 2149 genCSRUseExistingKeyPair.addLongIdentifier("replace-existing-certificate", 2150 true); 2151 genCSRUseExistingKeyPair.addLongIdentifier("replaceExistingCertificate", 2152 true); 2153 genCSRUseExistingKeyPair.addLongIdentifier("replace-certificate", true); 2154 genCSRUseExistingKeyPair.addLongIdentifier("replaceCertificate", true); 2155 genCSRUseExistingKeyPair.addLongIdentifier("replace-existing", true); 2156 genCSRUseExistingKeyPair.addLongIdentifier("replaceExisting", true); 2157 genCSRUseExistingKeyPair.addLongIdentifier("replace", true); 2158 genCSRParser.addArgument(genCSRUseExistingKeyPair); 2159 2160 final DNArgument genCSRSubjectDN = new DNArgument(null, "subject-dn", 2161 false, 1, null, 2162 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SUBJECT_DN_DESC.get()); 2163 genCSRSubjectDN.addLongIdentifier("subjectDN", true); 2164 genCSRSubjectDN.addLongIdentifier("subject", true); 2165 genCSRSubjectDN.addLongIdentifier("dname", true); 2166 genCSRParser.addArgument(genCSRSubjectDN); 2167 2168 final StringArgument genCSRKeyAlgorithm = new StringArgument(null, 2169 "key-algorithm", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2170 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KEY_ALGORITHM_DESC.get()); 2171 genCSRKeyAlgorithm.addLongIdentifier("keyAlgorithm", true); 2172 genCSRKeyAlgorithm.addLongIdentifier("key-alg", true); 2173 genCSRKeyAlgorithm.addLongIdentifier("keyAlg", true); 2174 genCSRParser.addArgument(genCSRKeyAlgorithm); 2175 2176 final IntegerArgument genCSRKeySizeBits = new IntegerArgument(null, 2177 "key-size-bits", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_BITS.get(), 2178 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KEY_SIZE_BITS_DESC.get(), 1, 2179 Integer.MAX_VALUE); 2180 genCSRKeySizeBits.addLongIdentifier("keySizeBits", true); 2181 genCSRKeySizeBits.addLongIdentifier("key-length-bits", true); 2182 genCSRKeySizeBits.addLongIdentifier("keyLengthBits", true); 2183 genCSRKeySizeBits.addLongIdentifier("key-size", true); 2184 genCSRKeySizeBits.addLongIdentifier("keySize", true); 2185 genCSRKeySizeBits.addLongIdentifier("key-length", true); 2186 genCSRKeySizeBits.addLongIdentifier("keyLength", true); 2187 genCSRParser.addArgument(genCSRKeySizeBits); 2188 2189 final StringArgument genCSRSignatureAlgorithm = new StringArgument(null, 2190 "signature-algorithm", false, 1, 2191 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2192 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SIG_ALG_DESC.get()); 2193 genCSRSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 2194 genCSRSignatureAlgorithm.addLongIdentifier("signature-alg", true); 2195 genCSRSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 2196 genCSRSignatureAlgorithm.addLongIdentifier("sig-alg", true); 2197 genCSRSignatureAlgorithm.addLongIdentifier("sigAlg", true); 2198 genCSRParser.addArgument(genCSRSignatureAlgorithm); 2199 2200 final BooleanArgument genCSRInheritExtensions = new BooleanArgument(null, 2201 "inherit-extensions", 1, 2202 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_INHERIT_EXT_DESC.get()); 2203 genCSRInheritExtensions.addLongIdentifier("inheritExtensions", true); 2204 genCSRParser.addArgument(genCSRInheritExtensions); 2205 2206 final StringArgument genCSRSubjectAltDNS = new StringArgument(null, 2207 "subject-alternative-name-dns", false, 0, 2208 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2209 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_DNS_DESC.get()); 2210 genCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 2211 genCSRSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 2212 genCSRSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 2213 genCSRSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 2214 genCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 2215 genCSRSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 2216 genCSRSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 2217 genCSRSubjectAltDNS.addLongIdentifier("san-dns", true); 2218 genCSRSubjectAltDNS.addLongIdentifier("sanDNS", true); 2219 genCSRSubjectAltDNS.addValueValidator( 2220 new IA5StringArgumentValueValidator(false)); 2221 genCSRParser.addArgument(genCSRSubjectAltDNS); 2222 2223 final StringArgument genCSRSubjectAltIP = new StringArgument(null, 2224 "subject-alternative-name-ip-address", false, 0, 2225 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2226 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_IP_DESC.get()); 2227 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 2228 true); 2229 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 2230 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 2231 genCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 2232 genCSRSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 2233 genCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 2234 genCSRSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 2235 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 2236 true); 2237 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 2238 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 2239 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 2240 genCSRSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 2241 genCSRSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 2242 genCSRSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 2243 genCSRSubjectAltIP.addLongIdentifier("subjectAltIP", true); 2244 genCSRSubjectAltIP.addLongIdentifier("san-ip-address", true); 2245 genCSRSubjectAltIP.addLongIdentifier("sanIPAddress", true); 2246 genCSRSubjectAltIP.addLongIdentifier("san-ip", true); 2247 genCSRSubjectAltIP.addLongIdentifier("sanIP", true); 2248 genCSRSubjectAltIP.addValueValidator( 2249 new IPAddressArgumentValueValidator(true, true)); 2250 genCSRParser.addArgument(genCSRSubjectAltIP); 2251 2252 final StringArgument genCSRSubjectAltEmail = new StringArgument(null, 2253 "subject-alternative-name-email-address", false, 0, 2254 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2255 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_EMAIL_DESC.get()); 2256 genCSRSubjectAltEmail.addLongIdentifier( 2257 "subjectAlternativeNameEmailAddress", true); 2258 genCSRSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 2259 true); 2260 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 2261 true); 2262 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 2263 true); 2264 genCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 2265 true); 2266 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 2267 genCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 2268 genCSRSubjectAltEmail.addLongIdentifier( 2269 "subject-alternative-email-address", true); 2270 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 2271 true); 2272 genCSRSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 2273 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 2274 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 2275 genCSRSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 2276 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 2277 genCSRSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 2278 genCSRSubjectAltEmail.addLongIdentifier("san-email-address", true); 2279 genCSRSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 2280 genCSRSubjectAltEmail.addLongIdentifier("san-email", true); 2281 genCSRSubjectAltEmail.addLongIdentifier("sanEmail", true); 2282 genCSRSubjectAltEmail.addValueValidator( 2283 new IA5StringArgumentValueValidator(false)); 2284 genCSRParser.addArgument(genCSRSubjectAltEmail); 2285 2286 final StringArgument genCSRSubjectAltURI = new StringArgument(null, 2287 "subject-alternative-name-uri", false, 0, 2288 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2289 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_URI_DESC.get()); 2290 genCSRSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 2291 genCSRSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 2292 genCSRSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 2293 genCSRSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 2294 genCSRSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 2295 genCSRSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 2296 genCSRSubjectAltURI.addLongIdentifier("subjectAltURI", true); 2297 genCSRSubjectAltURI.addLongIdentifier("san-uri", true); 2298 genCSRSubjectAltURI.addLongIdentifier("sanURI", true); 2299 genCSRParser.addArgument(genCSRSubjectAltURI); 2300 2301 final StringArgument genCSRSubjectAltOID = new StringArgument(null, 2302 "subject-alternative-name-oid", false, 0, 2303 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2304 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_OID_DESC.get()); 2305 genCSRSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 2306 genCSRSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 2307 genCSRSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 2308 genCSRSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 2309 genCSRSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 2310 genCSRSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 2311 genCSRSubjectAltOID.addLongIdentifier("subjectAltOID", true); 2312 genCSRSubjectAltOID.addLongIdentifier("san-oid", true); 2313 genCSRSubjectAltOID.addLongIdentifier("sanOID", true); 2314 genCSRSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2315 genCSRParser.addArgument(genCSRSubjectAltOID); 2316 2317 final BooleanValueArgument genCSRBasicConstraintsIsCA = 2318 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 2319 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_BC_IS_CA_DESC.get()); 2320 genCSRBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 2321 genCSRBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 2322 genCSRBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 2323 genCSRParser.addArgument(genCSRBasicConstraintsIsCA); 2324 2325 final IntegerArgument genCSRBasicConstraintsPathLength = 2326 new IntegerArgument(null, "basic-constraints-maximum-path-length", 2327 false, 1, null, 2328 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 2329 Integer.MAX_VALUE); 2330 genCSRBasicConstraintsPathLength.addLongIdentifier( 2331 "basicConstraintsMaximumPathLength", true); 2332 genCSRBasicConstraintsPathLength.addLongIdentifier( 2333 "basic-constraints-max-path-length", true); 2334 genCSRBasicConstraintsPathLength.addLongIdentifier( 2335 "basicConstraintsMaxPathLength", true); 2336 genCSRBasicConstraintsPathLength.addLongIdentifier( 2337 "basic-constraints-path-length", true); 2338 genCSRBasicConstraintsPathLength.addLongIdentifier( 2339 "basicConstraintsPathLength", true); 2340 genCSRBasicConstraintsPathLength.addLongIdentifier( 2341 "bc-maximum-path-length", true); 2342 genCSRBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 2343 true); 2344 genCSRBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 2345 true); 2346 genCSRBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 2347 true); 2348 genCSRBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 2349 genCSRBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 2350 genCSRParser.addArgument(genCSRBasicConstraintsPathLength); 2351 2352 final StringArgument genCSRKeyUsage = new StringArgument(null, "key-usage", 2353 false, 0, null, INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KU_DESC.get()); 2354 genCSRKeyUsage.addLongIdentifier("keyUsage", true); 2355 genCSRParser.addArgument(genCSRKeyUsage); 2356 2357 final StringArgument genCSRExtendedKeyUsage = new StringArgument(null, 2358 "extended-key-usage", false, 0, null, 2359 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_EKU_DESC.get()); 2360 genCSRExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 2361 genCSRParser.addArgument(genCSRExtendedKeyUsage); 2362 2363 final StringArgument genCSRExtension = new StringArgument(null, 2364 "extension", false, 0, null, 2365 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_EXT_DESC.get()); 2366 genCSRExtension.addLongIdentifier("ext", true); 2367 genCSRParser.addArgument(genCSRExtension); 2368 2369 final BooleanArgument genCSRDisplayCommand = new BooleanArgument(null, 2370 "display-keytool-command", 1, 2371 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 2372 genCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 2373 genCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 2374 genCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 2375 genCSRParser.addArgument(genCSRDisplayCommand); 2376 2377 genCSRParser.addRequiredArgumentSet(genCSRKeystorePassword, 2378 genCSRKeystorePasswordFile, genCSRPromptForKeystorePassword); 2379 genCSRParser.addExclusiveArgumentSet(genCSRKeystorePassword, 2380 genCSRKeystorePasswordFile, genCSRPromptForKeystorePassword); 2381 genCSRParser.addExclusiveArgumentSet(genCSRPKPassword, 2382 genCSRPKPasswordFile, genCSRPromptForPKPassword); 2383 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2384 genCSRKeyAlgorithm); 2385 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2386 genCSRKeySizeBits); 2387 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2388 genCSRSignatureAlgorithm); 2389 genCSRParser.addDependentArgumentSet(genCSRBasicConstraintsPathLength, 2390 genCSRBasicConstraintsIsCA); 2391 2392 final LinkedHashMap<String[],String> genCSRExamples = 2393 new LinkedHashMap<>(StaticUtils.computeMapCapacity(3)); 2394 genCSRExamples.put( 2395 new String[] 2396 { 2397 "generate-certificate-signing-request", 2398 "--keystore", getPlatformSpecificPath("config", "keystore"), 2399 "--keystore-password-file", 2400 getPlatformSpecificPath("config", "keystore.pin"), 2401 "--alias", "server-cert", 2402 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US" 2403 }, 2404 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_1.get()); 2405 genCSRExamples.put( 2406 new String[] 2407 { 2408 "generate-certificate-signing-request", 2409 "--keystore", getPlatformSpecificPath("config", "keystore"), 2410 "--keystore-password-file", 2411 getPlatformSpecificPath("config", "keystore.pin"), 2412 "--alias", "server-cert", 2413 "--use-existing-key-pair", 2414 "--inherit-extensions", 2415 "--output-file", "server-cert.csr" 2416 }, 2417 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_2.get()); 2418 genCSRExamples.put( 2419 new String[] 2420 { 2421 "generate-certificate-signing-request", 2422 "--keystore", getPlatformSpecificPath("config", "keystore"), 2423 "--keystore-password-file", 2424 getPlatformSpecificPath("config", "keystore.pin"), 2425 "--alias", "server-cert", 2426 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US", 2427 "--key-algorithm", "EC", 2428 "--key-size-bits", "256", 2429 "--signature-algorithm", "SHA256withECDSA", 2430 "--subject-alternative-name-dns", "ldap1.example.com", 2431 "--subject-alternative-name-dns", "ldap2.example.com", 2432 "--subject-alternative-name-ip-address", "1.2.3.4", 2433 "--subject-alternative-name-ip-address", "1.2.3.5", 2434 "--extended-key-usage", "server-auth", 2435 "--extended-key-usage", "client-auth", 2436 "--output-file", "server-cert.csr", 2437 "--display-keytool-command" 2438 }, 2439 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_3.get()); 2440 2441 final SubCommand genCSRSubCommand = new SubCommand( 2442 "generate-certificate-signing-request", 2443 INFO_MANAGE_CERTS_SC_GEN_CSR_DESC.get(), genCSRParser, 2444 genCSRExamples); 2445 genCSRSubCommand.addName("generateCertificateSigningRequest", true); 2446 genCSRSubCommand.addName("generate-certificate-request", true); 2447 genCSRSubCommand.addName("generateCertificateRequest", true); 2448 genCSRSubCommand.addName("generate-csr", true); 2449 genCSRSubCommand.addName("generateCSR", true); 2450 genCSRSubCommand.addName("certificate-signing-request", true); 2451 genCSRSubCommand.addName("certificateSigningRequest", true); 2452 genCSRSubCommand.addName("csr", true); 2453 genCSRSubCommand.addName("certreq", true); 2454 2455 parser.addSubCommand(genCSRSubCommand); 2456 2457 2458 // Define the "sign-certificate-signing-request" subcommand and all of its 2459 // arguments. 2460 final ArgumentParser signCSRParser = new ArgumentParser( 2461 "sign-certificate-signing-request", 2462 INFO_MANAGE_CERTS_SC_SIGN_CSR_DESC.get()); 2463 2464 final FileArgument signCSRInputFile = new FileArgument(null, 2465 "request-input-file", true, 1, null, 2466 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_INPUT_FILE_DESC.get(), true, true, 2467 true, false); 2468 signCSRInputFile.addLongIdentifier("requestInputFile", true); 2469 signCSRInputFile.addLongIdentifier("certificate-signing-request", true); 2470 signCSRInputFile.addLongIdentifier("certificateSigningRequest", true); 2471 signCSRInputFile.addLongIdentifier("input-file", false); 2472 signCSRInputFile.addLongIdentifier("inputFile", true); 2473 signCSRInputFile.addLongIdentifier("csr", true); 2474 signCSRParser.addArgument(signCSRInputFile); 2475 2476 final FileArgument signCSROutputFile = new FileArgument(null, 2477 "certificate-output-file", false, 1, null, 2478 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_OUTPUT_FILE_DESC.get(), false, true, 2479 true, false); 2480 signCSROutputFile.addLongIdentifier("certificateOutputFile", true); 2481 signCSROutputFile.addLongIdentifier("output-file", false); 2482 signCSROutputFile.addLongIdentifier("outputFile", true); 2483 signCSROutputFile.addLongIdentifier("certificate-file", true); 2484 signCSROutputFile.addLongIdentifier("certificateFile", true); 2485 signCSRParser.addArgument(signCSROutputFile); 2486 2487 final Set<String> signCSROutputFormatAllowedValues = StaticUtils.setOf( 2488 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 2489 final StringArgument signCSROutputFormat = new StringArgument(null, 2490 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 2491 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_FORMAT_DESC.get(), 2492 signCSROutputFormatAllowedValues, "PEM"); 2493 signCSROutputFormat.addLongIdentifier("outputFormat", true); 2494 signCSRParser.addArgument(signCSROutputFormat); 2495 2496 final FileArgument signCSRKeystore = new FileArgument(null, "keystore", 2497 true, 1, null, INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_DESC.get(), true, 2498 true, true, false); 2499 signCSRKeystore.addLongIdentifier("keystore-path", true); 2500 signCSRKeystore.addLongIdentifier("keystorePath", true); 2501 signCSRKeystore.addLongIdentifier("keystore-file", true); 2502 signCSRKeystore.addLongIdentifier("keystoreFile", true); 2503 signCSRParser.addArgument(signCSRKeystore); 2504 2505 final StringArgument signCSRKeystorePassword = new StringArgument(null, 2506 "keystore-password", false, 1, 2507 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2508 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_PW_DESC.get()); 2509 signCSRKeystorePassword.addLongIdentifier("keystorePassword", true); 2510 signCSRKeystorePassword.addLongIdentifier("keystore-passphrase", true); 2511 signCSRKeystorePassword.addLongIdentifier("keystorePassphrase", true); 2512 signCSRKeystorePassword.addLongIdentifier("keystore-pin", true); 2513 signCSRKeystorePassword.addLongIdentifier("keystorePIN", true); 2514 signCSRKeystorePassword.addLongIdentifier("storepass", true); 2515 signCSRKeystorePassword.setSensitive(true); 2516 signCSRParser.addArgument(signCSRKeystorePassword); 2517 2518 final FileArgument signCSRKeystorePasswordFile = new FileArgument(null, 2519 "keystore-password-file", false, 1, null, 2520 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_PW_FILE_DESC.get(), true, true, 2521 true, false); 2522 signCSRKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 2523 true); 2524 signCSRKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 2525 true); 2526 signCSRKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 2527 true); 2528 signCSRKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 2529 true); 2530 signCSRKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 2531 signCSRParser.addArgument(signCSRKeystorePasswordFile); 2532 2533 final BooleanArgument signCSRPromptForKeystorePassword = 2534 new BooleanArgument(null, "prompt-for-keystore-password", 2535 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PROMPT_FOR_KS_PW_DESC.get()); 2536 signCSRPromptForKeystorePassword.addLongIdentifier( 2537 "promptForKeystorePassword", true); 2538 signCSRPromptForKeystorePassword.addLongIdentifier( 2539 "prompt-for-keystore-passphrase", true); 2540 signCSRPromptForKeystorePassword.addLongIdentifier( 2541 "promptForKeystorePassphrase", true); 2542 signCSRPromptForKeystorePassword.addLongIdentifier( 2543 "prompt-for-keystore-pin", true); 2544 signCSRPromptForKeystorePassword.addLongIdentifier( 2545 "promptForKeystorePIN", true); 2546 signCSRParser.addArgument(signCSRPromptForKeystorePassword); 2547 2548 final StringArgument signCSRPKPassword = new StringArgument(null, 2549 "private-key-password", false, 1, 2550 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2551 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PK_PW_DESC.get()); 2552 signCSRPKPassword.addLongIdentifier("privateKeyPassword", true); 2553 signCSRPKPassword.addLongIdentifier("private-key-passphrase", true); 2554 signCSRPKPassword.addLongIdentifier("privateKeyPassphrase", true); 2555 signCSRPKPassword.addLongIdentifier("private-key-pin", true); 2556 signCSRPKPassword.addLongIdentifier("privateKeyPIN", true); 2557 signCSRPKPassword.addLongIdentifier("key-password", true); 2558 signCSRPKPassword.addLongIdentifier("keyPassword", true); 2559 signCSRPKPassword.addLongIdentifier("key-passphrase", true); 2560 signCSRPKPassword.addLongIdentifier("keyPassphrase", true); 2561 signCSRPKPassword.addLongIdentifier("key-pin", true); 2562 signCSRPKPassword.addLongIdentifier("keyPIN", true); 2563 signCSRPKPassword.addLongIdentifier("keypass", true); 2564 signCSRPKPassword.setSensitive(true); 2565 signCSRParser.addArgument(signCSRPKPassword); 2566 2567 final FileArgument signCSRPKPasswordFile = new FileArgument(null, 2568 "private-key-password-file", false, 1, null, 2569 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PK_PW_FILE_DESC.get(), true, true, 2570 true, false); 2571 signCSRPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 2572 signCSRPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 2573 true); 2574 signCSRPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 2575 true); 2576 signCSRPKPasswordFile.addLongIdentifier("private-key-pin-file", 2577 true); 2578 signCSRPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 2579 signCSRPKPasswordFile.addLongIdentifier("key-password-file", true); 2580 signCSRPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 2581 signCSRPKPasswordFile.addLongIdentifier("key-passphrase-file", 2582 true); 2583 signCSRPKPasswordFile.addLongIdentifier("keyPassphraseFile", 2584 true); 2585 signCSRPKPasswordFile.addLongIdentifier("key-pin-file", 2586 true); 2587 signCSRPKPasswordFile.addLongIdentifier("keyPINFile", true); 2588 signCSRParser.addArgument(signCSRPKPasswordFile); 2589 2590 final BooleanArgument signCSRPromptForPKPassword = 2591 new BooleanArgument(null, "prompt-for-private-key-password", 2592 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PROMPT_FOR_PK_PW_DESC.get()); 2593 signCSRPromptForPKPassword.addLongIdentifier( 2594 "promptForPrivateKeyPassword", true); 2595 signCSRPromptForPKPassword.addLongIdentifier( 2596 "prompt-for-private-key-passphrase", true); 2597 signCSRPromptForPKPassword.addLongIdentifier( 2598 "promptForPrivateKeyPassphrase", true); 2599 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 2600 true); 2601 signCSRPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 2602 true); 2603 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 2604 true); 2605 signCSRPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 2606 true); 2607 signCSRPromptForPKPassword.addLongIdentifier( 2608 "prompt-for-key-passphrase", true); 2609 signCSRPromptForPKPassword.addLongIdentifier( 2610 "promptForKeyPassphrase", true); 2611 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 2612 signCSRPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 2613 signCSRParser.addArgument(signCSRPromptForPKPassword); 2614 2615 final StringArgument signCSRKeystoreType = new StringArgument(null, 2616 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 2617 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_TYPE_DESC.get(), 2618 ALLOWED_KEYSTORE_TYPE_VALUES); 2619 signCSRKeystoreType.addLongIdentifier("key-store-type", true); 2620 signCSRKeystoreType.addLongIdentifier("keystoreType", true); 2621 signCSRKeystoreType.addLongIdentifier("keystore-format", true); 2622 signCSRKeystoreType.addLongIdentifier("key-store-format", true); 2623 signCSRKeystoreType.addLongIdentifier("keystoreFormat", true); 2624 signCSRKeystoreType.addLongIdentifier("storetype", true); 2625 signCSRParser.addArgument(signCSRKeystoreType); 2626 2627 final StringArgument signCSRAlias = new StringArgument(null, 2628 "signing-certificate-alias", 2629 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 2630 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_ALIAS_DESC.get()); 2631 signCSRAlias.addLongIdentifier("signingCertificateAlias", true); 2632 signCSRAlias.addLongIdentifier("signing-certificate-nickname", true); 2633 signCSRAlias.addLongIdentifier("signingCertificateNickname", true); 2634 signCSRAlias.addLongIdentifier("alias", true); 2635 signCSRAlias.addLongIdentifier("nickname", true); 2636 signCSRParser.addArgument(signCSRAlias); 2637 2638 final DNArgument signCSRSubjectDN = new DNArgument(null, "subject-dn", 2639 false, 1, null, 2640 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SUBJECT_DN_DESC.get()); 2641 signCSRSubjectDN.addLongIdentifier("subjectDN", true); 2642 signCSRSubjectDN.addLongIdentifier("subject", true); 2643 signCSRSubjectDN.addLongIdentifier("dname", true); 2644 signCSRParser.addArgument(signCSRSubjectDN); 2645 2646 final IntegerArgument signCSRDaysValid = new IntegerArgument(null, 2647 "days-valid", false, 1, null, 2648 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_DAYS_VALID_DESC.get(), 1, 2649 Integer.MAX_VALUE); 2650 signCSRDaysValid.addLongIdentifier("daysValid", true); 2651 signCSRDaysValid.addLongIdentifier("validity", true); 2652 signCSRParser.addArgument(signCSRDaysValid); 2653 2654 final TimestampArgument signCSRNotBefore = new TimestampArgument(null, 2655 "validity-start-time", false, 1, 2656 INFO_MANAGE_CERTS_PLACEHOLDER_TIMESTAMP.get(), 2657 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_VALIDITY_START_TIME_DESC.get( 2658 "20180102123456")); 2659 signCSRNotBefore.addLongIdentifier("validityStartTime", true); 2660 signCSRNotBefore.addLongIdentifier("not-before", true); 2661 signCSRNotBefore.addLongIdentifier("notBefore", true); 2662 signCSRParser.addArgument(signCSRNotBefore); 2663 2664 final StringArgument signCSRSignatureAlgorithm = new StringArgument(null, 2665 "signature-algorithm", false, 1, 2666 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2667 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SIG_ALG_DESC.get()); 2668 signCSRSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 2669 signCSRSignatureAlgorithm.addLongIdentifier("signature-alg", true); 2670 signCSRSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 2671 signCSRSignatureAlgorithm.addLongIdentifier("sig-alg", true); 2672 signCSRSignatureAlgorithm.addLongIdentifier("sigAlg", true); 2673 signCSRParser.addArgument(signCSRSignatureAlgorithm); 2674 2675 final BooleanArgument signCSRIncludeExtensions = new BooleanArgument(null, 2676 "include-requested-extensions", 1, 2677 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_INCLUDE_EXT_DESC.get()); 2678 signCSRIncludeExtensions.addLongIdentifier("includeRequestedExtensions", 2679 true); 2680 signCSRParser.addArgument(signCSRIncludeExtensions); 2681 2682 final StringArgument signCSRSubjectAltDNS = new StringArgument(null, 2683 "subject-alternative-name-dns", false, 0, 2684 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2685 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_DNS_DESC.get()); 2686 signCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 2687 signCSRSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 2688 signCSRSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 2689 signCSRSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 2690 signCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 2691 signCSRSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 2692 signCSRSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 2693 signCSRSubjectAltDNS.addLongIdentifier("san-dns", true); 2694 signCSRSubjectAltDNS.addLongIdentifier("sanDNS", true); 2695 signCSRSubjectAltDNS.addValueValidator( 2696 new IA5StringArgumentValueValidator(false)); 2697 signCSRParser.addArgument(signCSRSubjectAltDNS); 2698 2699 final StringArgument signCSRSubjectAltIP = new StringArgument(null, 2700 "subject-alternative-name-ip-address", false, 0, 2701 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2702 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_IP_DESC.get()); 2703 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 2704 true); 2705 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 2706 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 2707 signCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 2708 signCSRSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 2709 signCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 2710 signCSRSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 2711 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 2712 true); 2713 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 2714 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 2715 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 2716 signCSRSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 2717 signCSRSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 2718 signCSRSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 2719 signCSRSubjectAltIP.addLongIdentifier("subjectAltIP", true); 2720 signCSRSubjectAltIP.addLongIdentifier("san-ip-address", true); 2721 signCSRSubjectAltIP.addLongIdentifier("sanIPAddress", true); 2722 signCSRSubjectAltIP.addLongIdentifier("san-ip", true); 2723 signCSRSubjectAltIP.addLongIdentifier("sanIP", true); 2724 signCSRSubjectAltIP.addValueValidator( 2725 new IPAddressArgumentValueValidator(true, true)); 2726 signCSRParser.addArgument(signCSRSubjectAltIP); 2727 2728 final StringArgument signCSRSubjectAltEmail = new StringArgument(null, 2729 "subject-alternative-name-email-address", false, 0, 2730 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2731 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_EMAIL_DESC.get()); 2732 signCSRSubjectAltEmail.addLongIdentifier( 2733 "subjectAlternativeNameEmailAddress", true); 2734 signCSRSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 2735 true); 2736 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 2737 true); 2738 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 2739 true); 2740 signCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 2741 true); 2742 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 2743 signCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 2744 signCSRSubjectAltEmail.addLongIdentifier( 2745 "subject-alternative-email-address", true); 2746 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 2747 true); 2748 signCSRSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 2749 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 2750 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 2751 signCSRSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 2752 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 2753 signCSRSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 2754 signCSRSubjectAltEmail.addLongIdentifier("san-email-address", true); 2755 signCSRSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 2756 signCSRSubjectAltEmail.addLongIdentifier("san-email", true); 2757 signCSRSubjectAltEmail.addLongIdentifier("sanEmail", true); 2758 signCSRSubjectAltEmail.addValueValidator( 2759 new IA5StringArgumentValueValidator(false)); 2760 signCSRParser.addArgument(signCSRSubjectAltEmail); 2761 2762 final StringArgument signCSRSubjectAltURI = new StringArgument(null, 2763 "subject-alternative-name-uri", false, 0, 2764 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2765 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_URI_DESC.get()); 2766 signCSRSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 2767 signCSRSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 2768 signCSRSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 2769 signCSRSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 2770 signCSRSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 2771 signCSRSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 2772 signCSRSubjectAltURI.addLongIdentifier("subjectAltURI", true); 2773 signCSRSubjectAltURI.addLongIdentifier("san-uri", true); 2774 signCSRSubjectAltURI.addLongIdentifier("sanURI", true); 2775 signCSRParser.addArgument(signCSRSubjectAltURI); 2776 2777 final StringArgument signCSRSubjectAltOID = new StringArgument(null, 2778 "subject-alternative-name-oid", false, 0, 2779 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2780 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_OID_DESC.get()); 2781 signCSRSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 2782 signCSRSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 2783 signCSRSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 2784 signCSRSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 2785 signCSRSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 2786 signCSRSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 2787 signCSRSubjectAltOID.addLongIdentifier("subjectAltOID", true); 2788 signCSRSubjectAltOID.addLongIdentifier("san-oid", true); 2789 signCSRSubjectAltOID.addLongIdentifier("sanOID", true); 2790 signCSRSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2791 signCSRParser.addArgument(signCSRSubjectAltOID); 2792 2793 final StringArgument signCSRIssuerAltDNS = new StringArgument(null, 2794 "issuer-alternative-name-dns", false, 0, 2795 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2796 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_DNS_DESC.get()); 2797 signCSRIssuerAltDNS.addLongIdentifier("issuerAlternativeNameDNS", true); 2798 signCSRIssuerAltDNS.addLongIdentifier("issuer-alt-name-dns", true); 2799 signCSRIssuerAltDNS.addLongIdentifier("issuerAltNameDNS", true); 2800 signCSRIssuerAltDNS.addLongIdentifier("issuer-alternative-dns", true); 2801 signCSRIssuerAltDNS.addLongIdentifier("issuerAlternativeDNS", true); 2802 signCSRIssuerAltDNS.addLongIdentifier("issuer-alt-dns", true); 2803 signCSRIssuerAltDNS.addLongIdentifier("issuerAltDNS", true); 2804 signCSRIssuerAltDNS.addLongIdentifier("ian-dns", true); 2805 signCSRIssuerAltDNS.addLongIdentifier("ianDNS", true); 2806 signCSRIssuerAltDNS.addValueValidator( 2807 new IA5StringArgumentValueValidator(false)); 2808 signCSRParser.addArgument(signCSRIssuerAltDNS); 2809 2810 final StringArgument signCSRIssuerAltIP = new StringArgument(null, 2811 "issuer-alternative-name-ip-address", false, 0, 2812 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2813 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_IP_DESC.get()); 2814 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeNameIPAddress", 2815 true); 2816 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-name-ip", true); 2817 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeNameIP", true); 2818 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-name-ip-address", true); 2819 signCSRIssuerAltIP.addLongIdentifier("issuerAltNameIPAddress", true); 2820 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-name-ip", true); 2821 signCSRIssuerAltIP.addLongIdentifier("issuerAltNameIP", true); 2822 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-ip-address", 2823 true); 2824 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeIPAddress", true); 2825 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-ip", true); 2826 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeIP", true); 2827 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-ip-address", true); 2828 signCSRIssuerAltIP.addLongIdentifier("issuerAltIPAddress", true); 2829 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-ip", true); 2830 signCSRIssuerAltIP.addLongIdentifier("issuerAltIP", true); 2831 signCSRIssuerAltIP.addLongIdentifier("ian-ip-address", true); 2832 signCSRIssuerAltIP.addLongIdentifier("ianIPAddress", true); 2833 signCSRIssuerAltIP.addLongIdentifier("ian-ip", true); 2834 signCSRIssuerAltIP.addLongIdentifier("ianIP", true); 2835 signCSRIssuerAltIP.addValueValidator( 2836 new IPAddressArgumentValueValidator(true, true)); 2837 signCSRParser.addArgument(signCSRIssuerAltIP); 2838 2839 final StringArgument signCSRIssuerAltEmail = new StringArgument(null, 2840 "issuer-alternative-name-email-address", false, 0, 2841 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2842 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_EMAIL_DESC.get()); 2843 signCSRIssuerAltEmail.addLongIdentifier( 2844 "issuerAlternativeNameEmailAddress", true); 2845 signCSRIssuerAltEmail.addLongIdentifier("issuer-alternative-name-email", 2846 true); 2847 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeNameEmail", 2848 true); 2849 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-name-email-address", 2850 true); 2851 signCSRIssuerAltEmail.addLongIdentifier("issuerAltNameEmailAddress", 2852 true); 2853 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-name-email", true); 2854 signCSRIssuerAltEmail.addLongIdentifier("issuerAltNameEmail", true); 2855 signCSRIssuerAltEmail.addLongIdentifier( 2856 "issuer-alternative-email-address", true); 2857 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeEmailAddress", 2858 true); 2859 signCSRIssuerAltEmail.addLongIdentifier("issuer-alternative-email", true); 2860 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeEmail", true); 2861 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-email-address", true); 2862 signCSRIssuerAltEmail.addLongIdentifier("issuerAltEmailAddress", true); 2863 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-email", true); 2864 signCSRIssuerAltEmail.addLongIdentifier("issuerAltEmail", true); 2865 signCSRIssuerAltEmail.addLongIdentifier("ian-email-address", true); 2866 signCSRIssuerAltEmail.addLongIdentifier("ianEmailAddress", true); 2867 signCSRIssuerAltEmail.addLongIdentifier("ian-email", true); 2868 signCSRIssuerAltEmail.addLongIdentifier("ianEmail", true); 2869 signCSRIssuerAltEmail.addValueValidator( 2870 new IA5StringArgumentValueValidator(false)); 2871 signCSRParser.addArgument(signCSRIssuerAltEmail); 2872 2873 final StringArgument signCSRIssuerAltURI = new StringArgument(null, 2874 "issuer-alternative-name-uri", false, 0, 2875 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2876 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_URI_DESC.get()); 2877 signCSRIssuerAltURI.addLongIdentifier("issuerAlternativeNameURI", true); 2878 signCSRIssuerAltURI.addLongIdentifier("issuer-alt-name-uri", true); 2879 signCSRIssuerAltURI.addLongIdentifier("issuerAltNameURI", true); 2880 signCSRIssuerAltURI.addLongIdentifier("issuer-alternative-uri", true); 2881 signCSRIssuerAltURI.addLongIdentifier("issuerAlternativeURI", true); 2882 signCSRIssuerAltURI.addLongIdentifier("issuer-alt-uri", true); 2883 signCSRIssuerAltURI.addLongIdentifier("issuerAltURI", true); 2884 signCSRIssuerAltURI.addLongIdentifier("ian-uri", true); 2885 signCSRIssuerAltURI.addLongIdentifier("ianURI", true); 2886 signCSRParser.addArgument(signCSRIssuerAltURI); 2887 2888 final StringArgument signCSRIssuerAltOID = new StringArgument(null, 2889 "issuer-alternative-name-oid", false, 0, 2890 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2891 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_OID_DESC.get()); 2892 signCSRIssuerAltOID.addLongIdentifier("issuerAlternativeNameOID", true); 2893 signCSRIssuerAltOID.addLongIdentifier("issuer-alt-name-oid", true); 2894 signCSRIssuerAltOID.addLongIdentifier("issuerAltNameOID", true); 2895 signCSRIssuerAltOID.addLongIdentifier("issuer-alternative-oid", true); 2896 signCSRIssuerAltOID.addLongIdentifier("issuerAlternativeOID", true); 2897 signCSRIssuerAltOID.addLongIdentifier("issuer-alt-oid", true); 2898 signCSRIssuerAltOID.addLongIdentifier("issuerAltOID", true); 2899 signCSRIssuerAltOID.addLongIdentifier("ian-oid", true); 2900 signCSRIssuerAltOID.addLongIdentifier("ianOID", true); 2901 signCSRIssuerAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2902 signCSRParser.addArgument(signCSRIssuerAltOID); 2903 2904 final BooleanValueArgument signCSRBasicConstraintsIsCA = 2905 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 2906 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_BC_IS_CA_DESC.get()); 2907 signCSRBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 2908 signCSRBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 2909 signCSRBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 2910 signCSRParser.addArgument(signCSRBasicConstraintsIsCA); 2911 2912 final IntegerArgument signCSRBasicConstraintsPathLength = 2913 new IntegerArgument(null, "basic-constraints-maximum-path-length", 2914 false, 1, null, 2915 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 2916 Integer.MAX_VALUE); 2917 signCSRBasicConstraintsPathLength.addLongIdentifier( 2918 "basicConstraintsMaximumPathLength", true); 2919 signCSRBasicConstraintsPathLength.addLongIdentifier( 2920 "basic-constraints-max-path-length", true); 2921 signCSRBasicConstraintsPathLength.addLongIdentifier( 2922 "basicConstraintsMaxPathLength", true); 2923 signCSRBasicConstraintsPathLength.addLongIdentifier( 2924 "basic-constraints-path-length", true); 2925 signCSRBasicConstraintsPathLength.addLongIdentifier( 2926 "basicConstraintsPathLength", true); 2927 signCSRBasicConstraintsPathLength.addLongIdentifier( 2928 "bc-maximum-path-length", true); 2929 signCSRBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 2930 true); 2931 signCSRBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 2932 true); 2933 signCSRBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 2934 true); 2935 signCSRBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 2936 signCSRBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 2937 signCSRParser.addArgument(signCSRBasicConstraintsPathLength); 2938 2939 final StringArgument signCSRKeyUsage = new StringArgument(null, "key-usage", 2940 false, 0, null, INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KU_DESC.get()); 2941 signCSRKeyUsage.addLongIdentifier("keyUsage", true); 2942 signCSRParser.addArgument(signCSRKeyUsage); 2943 2944 final StringArgument signCSRExtendedKeyUsage = new StringArgument(null, 2945 "extended-key-usage", false, 0, null, 2946 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_EKU_DESC.get()); 2947 signCSRExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 2948 signCSRParser.addArgument(signCSRExtendedKeyUsage); 2949 2950 final StringArgument signCSRExtension = new StringArgument(null, 2951 "extension", false, 0, null, 2952 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_EXT_DESC.get()); 2953 signCSRExtension.addLongIdentifier("ext", true); 2954 signCSRParser.addArgument(signCSRExtension); 2955 2956 final BooleanArgument signCSRNoPrompt = new BooleanArgument(null, 2957 "no-prompt", 1, 2958 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_NO_PROMPT_DESC.get()); 2959 signCSRNoPrompt.addLongIdentifier("noPrompt", true); 2960 signCSRParser.addArgument(signCSRNoPrompt); 2961 2962 final BooleanArgument signCSRDisplayCommand = new BooleanArgument(null, 2963 "display-keytool-command", 1, 2964 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 2965 signCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 2966 signCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 2967 signCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 2968 signCSRParser.addArgument(signCSRDisplayCommand); 2969 2970 signCSRParser.addRequiredArgumentSet(signCSRKeystorePassword, 2971 signCSRKeystorePasswordFile, signCSRPromptForKeystorePassword); 2972 signCSRParser.addExclusiveArgumentSet(signCSRKeystorePassword, 2973 signCSRKeystorePasswordFile, signCSRPromptForKeystorePassword); 2974 signCSRParser.addExclusiveArgumentSet(signCSRPKPassword, 2975 signCSRPKPasswordFile, signCSRPromptForPKPassword); 2976 signCSRParser.addDependentArgumentSet(signCSRBasicConstraintsPathLength, 2977 signCSRBasicConstraintsIsCA); 2978 2979 final LinkedHashMap<String[],String> signCSRExamples = 2980 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 2981 signCSRExamples.put( 2982 new String[] 2983 { 2984 "sign-certificate-signing-request", 2985 "--request-input-file", "server-cert.csr", 2986 "--keystore", getPlatformSpecificPath("config", "keystore"), 2987 "--keystore-password-file", 2988 getPlatformSpecificPath("config", "keystore.pin"), 2989 "--signing-certificate-alias", "ca-cert", 2990 "--include-requested-extensions" 2991 }, 2992 INFO_MANAGE_CERTS_SC_SIGN_CSR_EXAMPLE_1.get( 2993 getPlatformSpecificPath("config", "keystore"))); 2994 signCSRExamples.put( 2995 new String[] 2996 { 2997 "sign-certificate-signing-request", 2998 "--request-input-file", "server-cert.csr", 2999 "--certificate-output-file", "server-cert.der", 3000 "--output-format", "DER", 3001 "--keystore", getPlatformSpecificPath("config", "keystore"), 3002 "--keystore-password-file", 3003 getPlatformSpecificPath("config", "keystore.pin"), 3004 "--signing-certificate-alias", "ca-cert", 3005 "--days-valid", "730", 3006 "--validity-start-time", "20170101000000", 3007 "--include-requested-extensions", 3008 "--issuer-alternative-name-email-address", "ca@example.com", 3009 }, 3010 INFO_MANAGE_CERTS_SC_SIGN_CSR_EXAMPLE_2.get( 3011 getPlatformSpecificPath("config", "keystore"))); 3012 3013 final SubCommand signCSRSubCommand = new SubCommand( 3014 "sign-certificate-signing-request", 3015 INFO_MANAGE_CERTS_SC_SIGN_CSR_DESC.get(), signCSRParser, 3016 signCSRExamples); 3017 signCSRSubCommand.addName("signCertificateSigningRequest", true); 3018 signCSRSubCommand.addName("sign-certificate-request", true); 3019 signCSRSubCommand.addName("signCertificateRequest", true); 3020 signCSRSubCommand.addName("sign-certificate", true); 3021 signCSRSubCommand.addName("signCertificate", true); 3022 signCSRSubCommand.addName("sign-csr", true); 3023 signCSRSubCommand.addName("signCSR", true); 3024 signCSRSubCommand.addName("sign", true); 3025 signCSRSubCommand.addName("gencert", true); 3026 3027 parser.addSubCommand(signCSRSubCommand); 3028 3029 3030 // Define the "change-certificate-alias" subcommand and all of its 3031 // arguments. 3032 final ArgumentParser changeAliasParser = new ArgumentParser( 3033 "change-certificate-alias", 3034 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_DESC.get()); 3035 3036 final FileArgument changeAliasKeystore = new FileArgument(null, "keystore", 3037 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_DESC.get(), 3038 true, true, true, false); 3039 changeAliasKeystore.addLongIdentifier("keystore-path", true); 3040 changeAliasKeystore.addLongIdentifier("keystorePath", true); 3041 changeAliasKeystore.addLongIdentifier("keystore-file", true); 3042 changeAliasKeystore.addLongIdentifier("keystoreFile", true); 3043 changeAliasParser.addArgument(changeAliasKeystore); 3044 3045 final StringArgument changeAliasKeystorePassword = new StringArgument(null, 3046 "keystore-password", false, 1, 3047 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3048 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_PW_DESC.get()); 3049 changeAliasKeystorePassword.addLongIdentifier("keystorePassword", true); 3050 changeAliasKeystorePassword.addLongIdentifier("keystore-passphrase", true); 3051 changeAliasKeystorePassword.addLongIdentifier("keystorePassphrase", true); 3052 changeAliasKeystorePassword.addLongIdentifier("keystore-pin", true); 3053 changeAliasKeystorePassword.addLongIdentifier("keystorePIN", true); 3054 changeAliasKeystorePassword.addLongIdentifier("storepass", true); 3055 changeAliasKeystorePassword.setSensitive(true); 3056 changeAliasParser.addArgument(changeAliasKeystorePassword); 3057 3058 final FileArgument changeAliasKeystorePasswordFile = new FileArgument(null, 3059 "keystore-password-file", false, 1, null, 3060 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_PW_FILE_DESC.get(), true, 3061 true, true, false); 3062 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 3063 true); 3064 changeAliasKeystorePasswordFile.addLongIdentifier( 3065 "keystore-passphrase-file", true); 3066 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 3067 true); 3068 changeAliasKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 3069 true); 3070 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 3071 changeAliasParser.addArgument(changeAliasKeystorePasswordFile); 3072 3073 final BooleanArgument changeAliasPromptForKeystorePassword = 3074 new BooleanArgument(null, "prompt-for-keystore-password", 3075 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PROMPT_FOR_KS_PW_DESC.get()); 3076 changeAliasPromptForKeystorePassword.addLongIdentifier( 3077 "promptForKeystorePassword", true); 3078 changeAliasPromptForKeystorePassword.addLongIdentifier( 3079 "prompt-for-keystore-passphrase", true); 3080 changeAliasPromptForKeystorePassword.addLongIdentifier( 3081 "promptForKeystorePassphrase", true); 3082 changeAliasPromptForKeystorePassword.addLongIdentifier( 3083 "prompt-for-keystore-pin", true); 3084 changeAliasPromptForKeystorePassword.addLongIdentifier( 3085 "promptForKeystorePIN", true); 3086 changeAliasParser.addArgument(changeAliasPromptForKeystorePassword); 3087 3088 final StringArgument changeAliasPKPassword = new StringArgument(null, 3089 "private-key-password", false, 1, 3090 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3091 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PK_PW_DESC.get()); 3092 changeAliasPKPassword.addLongIdentifier("privateKeyPassword", true); 3093 changeAliasPKPassword.addLongIdentifier("private-key-passphrase", true); 3094 changeAliasPKPassword.addLongIdentifier("privateKeyPassphrase", true); 3095 changeAliasPKPassword.addLongIdentifier("private-key-pin", true); 3096 changeAliasPKPassword.addLongIdentifier("privateKeyPIN", true); 3097 changeAliasPKPassword.addLongIdentifier("key-password", true); 3098 changeAliasPKPassword.addLongIdentifier("keyPassword", true); 3099 changeAliasPKPassword.addLongIdentifier("key-passphrase", true); 3100 changeAliasPKPassword.addLongIdentifier("keyPassphrase", true); 3101 changeAliasPKPassword.addLongIdentifier("key-pin", true); 3102 changeAliasPKPassword.addLongIdentifier("keyPIN", true); 3103 changeAliasPKPassword.addLongIdentifier("keypass", true); 3104 changeAliasPKPassword.setSensitive(true); 3105 changeAliasParser.addArgument(changeAliasPKPassword); 3106 3107 final FileArgument changeAliasPKPasswordFile = new FileArgument(null, 3108 "private-key-password-file", false, 1, null, 3109 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PK_PW_FILE_DESC.get(), true, 3110 true, true, false); 3111 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 3112 changeAliasPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 3113 true); 3114 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 3115 true); 3116 changeAliasPKPasswordFile.addLongIdentifier("private-key-pin-file", 3117 true); 3118 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 3119 changeAliasPKPasswordFile.addLongIdentifier("key-password-file", true); 3120 changeAliasPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 3121 changeAliasPKPasswordFile.addLongIdentifier("key-passphrase-file", 3122 true); 3123 changeAliasPKPasswordFile.addLongIdentifier("keyPassphraseFile", 3124 true); 3125 changeAliasPKPasswordFile.addLongIdentifier("key-pin-file", 3126 true); 3127 changeAliasPKPasswordFile.addLongIdentifier("keyPINFile", true); 3128 changeAliasParser.addArgument(changeAliasPKPasswordFile); 3129 3130 final BooleanArgument changeAliasPromptForPKPassword = 3131 new BooleanArgument(null, "prompt-for-private-key-password", 3132 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PROMPT_FOR_PK_PW_DESC.get()); 3133 changeAliasPromptForPKPassword.addLongIdentifier( 3134 "promptForPrivateKeyPassword", true); 3135 changeAliasPromptForPKPassword.addLongIdentifier( 3136 "prompt-for-private-key-passphrase", true); 3137 changeAliasPromptForPKPassword.addLongIdentifier( 3138 "promptForPrivateKeyPassphrase", true); 3139 changeAliasPromptForPKPassword.addLongIdentifier( 3140 "prompt-for-private-key-pin", true); 3141 changeAliasPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 3142 true); 3143 changeAliasPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 3144 true); 3145 changeAliasPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 3146 true); 3147 changeAliasPromptForPKPassword.addLongIdentifier( 3148 "prompt-for-key-passphrase", true); 3149 changeAliasPromptForPKPassword.addLongIdentifier( 3150 "promptForKeyPassphrase", true); 3151 changeAliasPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", 3152 true); 3153 changeAliasPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 3154 changeAliasParser.addArgument(changeAliasPromptForPKPassword); 3155 3156 final StringArgument changeAliasKeystoreType = new StringArgument(null, 3157 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3158 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_TYPE_DESC.get(), 3159 ALLOWED_KEYSTORE_TYPE_VALUES); 3160 changeAliasKeystoreType.addLongIdentifier("key-store-type", true); 3161 changeAliasKeystoreType.addLongIdentifier("keystoreType", true); 3162 changeAliasKeystoreType.addLongIdentifier("keystore-format", true); 3163 changeAliasKeystoreType.addLongIdentifier("key-store-format", true); 3164 changeAliasKeystoreType.addLongIdentifier("keystoreFormat", true); 3165 changeAliasKeystoreType.addLongIdentifier("storetype", true); 3166 changeAliasParser.addArgument(changeAliasKeystoreType); 3167 3168 final StringArgument changeAliasCurrentAlias = new StringArgument(null, 3169 "current-alias", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3170 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_CURRENT_ALIAS_DESC.get()); 3171 changeAliasCurrentAlias.addLongIdentifier("currentAlias", true); 3172 changeAliasCurrentAlias.addLongIdentifier("old-alias", true); 3173 changeAliasCurrentAlias.addLongIdentifier("oldAlias", true); 3174 changeAliasCurrentAlias.addLongIdentifier("source-alias", true); 3175 changeAliasCurrentAlias.addLongIdentifier("sourceAlias", true); 3176 changeAliasCurrentAlias.addLongIdentifier("alias", true); 3177 changeAliasCurrentAlias.addLongIdentifier("current-nickname", true); 3178 changeAliasCurrentAlias.addLongIdentifier("currentNickname", true); 3179 changeAliasCurrentAlias.addLongIdentifier("old-nickname", true); 3180 changeAliasCurrentAlias.addLongIdentifier("oldNickname", true); 3181 changeAliasCurrentAlias.addLongIdentifier("source-nickname", true); 3182 changeAliasCurrentAlias.addLongIdentifier("sourceNickname", true); 3183 changeAliasCurrentAlias.addLongIdentifier("nickname", true); 3184 changeAliasCurrentAlias.addLongIdentifier("from", false); 3185 changeAliasParser.addArgument(changeAliasCurrentAlias); 3186 3187 final StringArgument changeAliasNewAlias = new StringArgument(null, 3188 "new-alias", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3189 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_NEW_ALIAS_DESC.get()); 3190 changeAliasNewAlias.addLongIdentifier("newAlias", true); 3191 changeAliasNewAlias.addLongIdentifier("destination-alias", true); 3192 changeAliasNewAlias.addLongIdentifier("destinationAlias", true); 3193 changeAliasNewAlias.addLongIdentifier("new-nickname", true); 3194 changeAliasNewAlias.addLongIdentifier("newNickname", true); 3195 changeAliasNewAlias.addLongIdentifier("destination-nickname", true); 3196 changeAliasNewAlias.addLongIdentifier("destinationNickname", true); 3197 changeAliasNewAlias.addLongIdentifier("to", false); 3198 changeAliasParser.addArgument(changeAliasNewAlias); 3199 3200 final BooleanArgument changeAliasDisplayCommand = new BooleanArgument(null, 3201 "display-keytool-command", 1, 3202 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_DISPLAY_COMMAND_DESC.get()); 3203 changeAliasDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3204 changeAliasDisplayCommand.addLongIdentifier("show-keytool-command", true); 3205 changeAliasDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3206 changeAliasParser.addArgument(changeAliasDisplayCommand); 3207 3208 changeAliasParser.addRequiredArgumentSet(changeAliasKeystorePassword, 3209 changeAliasKeystorePasswordFile, changeAliasPromptForKeystorePassword); 3210 changeAliasParser.addExclusiveArgumentSet(changeAliasKeystorePassword, 3211 changeAliasKeystorePasswordFile, changeAliasPromptForKeystorePassword); 3212 changeAliasParser.addExclusiveArgumentSet(changeAliasPKPassword, 3213 changeAliasPKPasswordFile, changeAliasPromptForPKPassword); 3214 3215 final LinkedHashMap<String[],String> changeAliasExamples = 3216 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3217 changeAliasExamples.put( 3218 new String[] 3219 { 3220 "change-certificate-alias", 3221 "--keystore", getPlatformSpecificPath("config", "keystore"), 3222 "--keystore-password-file", 3223 getPlatformSpecificPath("config", "keystore.pin"), 3224 "--current-alias", "server-cert", 3225 "--new-alias", "server-certificate", 3226 "--display-keytool-command" 3227 }, 3228 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_EXAMPLE_1.get()); 3229 3230 final SubCommand changeAliasSubCommand = new SubCommand( 3231 "change-certificate-alias", 3232 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_DESC.get(), changeAliasParser, 3233 changeAliasExamples); 3234 changeAliasSubCommand.addName("changeCertificateAlias", true); 3235 changeAliasSubCommand.addName("change-alias", true); 3236 changeAliasSubCommand.addName("changeAlias", true); 3237 changeAliasSubCommand.addName("rename-certificate", true); 3238 changeAliasSubCommand.addName("renameCertificate", true); 3239 changeAliasSubCommand.addName("rename", true); 3240 3241 parser.addSubCommand(changeAliasSubCommand); 3242 3243 3244 // Define the "change-keystore-password" subcommand and all of its 3245 // arguments. 3246 final ArgumentParser changeKSPWParser = new ArgumentParser( 3247 "change-keystore-password", 3248 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_DESC.get()); 3249 3250 final FileArgument changeKSPWKeystore = new FileArgument(null, "keystore", 3251 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_KS_DESC.get(), 3252 true, true, true, false); 3253 changeKSPWKeystore.addLongIdentifier("keystore-path", true); 3254 changeKSPWKeystore.addLongIdentifier("keystorePath", true); 3255 changeKSPWKeystore.addLongIdentifier("keystore-file", true); 3256 changeKSPWKeystore.addLongIdentifier("keystoreFile", true); 3257 changeKSPWParser.addArgument(changeKSPWKeystore); 3258 3259 final StringArgument changeKSPWCurrentPassword = new StringArgument(null, 3260 "current-keystore-password", false, 1, 3261 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3262 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_CURRENT_PW_DESC.get()); 3263 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePassword", 3264 true); 3265 changeKSPWCurrentPassword.addLongIdentifier("current-keystore-passphrase", 3266 true); 3267 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePassphrase", 3268 true); 3269 changeKSPWCurrentPassword.addLongIdentifier("current-keystore-pin", true); 3270 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePIN", true); 3271 changeKSPWCurrentPassword.addLongIdentifier("storepass", true); 3272 changeKSPWCurrentPassword.setSensitive(true); 3273 changeKSPWParser.addArgument(changeKSPWCurrentPassword); 3274 3275 final FileArgument changeKSPWCurrentPasswordFile = new FileArgument(null, 3276 "current-keystore-password-file", false, 1, null, 3277 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_CURRENT_PW_FILE_DESC.get(), true, 3278 true, true, false); 3279 changeKSPWCurrentPasswordFile.addLongIdentifier( 3280 "currentKeystorePasswordFile", true); 3281 changeKSPWCurrentPasswordFile.addLongIdentifier( 3282 "current-keystore-passphrase-file", true); 3283 changeKSPWCurrentPasswordFile.addLongIdentifier( 3284 "currentKeystorePassphraseFile", true); 3285 changeKSPWCurrentPasswordFile.addLongIdentifier("current-keystore-pin-file", 3286 true); 3287 changeKSPWCurrentPasswordFile.addLongIdentifier("currentKeystorePINFile", 3288 true); 3289 changeKSPWParser.addArgument(changeKSPWCurrentPasswordFile); 3290 3291 final BooleanArgument changeKSPWPromptForCurrentPassword = 3292 new BooleanArgument(null, "prompt-for-current-keystore-password", 3293 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_PROMPT_FOR_CURRENT_PW_DESC.get()); 3294 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3295 "promptForCurrentKeystorePassword", true); 3296 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3297 "prompt-for-current-keystore-passphrase", true); 3298 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3299 "promptForCurrentKeystorePassphrase", true); 3300 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3301 "prompt-for-current-keystore-pin", true); 3302 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3303 "promptForCurrentKeystorePIN", true); 3304 changeKSPWParser.addArgument(changeKSPWPromptForCurrentPassword); 3305 3306 final StringArgument changeKSPWNewPassword = new StringArgument(null, 3307 "new-keystore-password", false, 1, 3308 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3309 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_NEW_PW_DESC.get()); 3310 changeKSPWNewPassword.addLongIdentifier("newKeystorePassword", 3311 true); 3312 changeKSPWNewPassword.addLongIdentifier("new-keystore-passphrase", 3313 true); 3314 changeKSPWNewPassword.addLongIdentifier("newKeystorePassphrase", 3315 true); 3316 changeKSPWNewPassword.addLongIdentifier("new-keystore-pin", true); 3317 changeKSPWNewPassword.addLongIdentifier("newKeystorePIN", true); 3318 changeKSPWNewPassword.addLongIdentifier("new", true); 3319 changeKSPWNewPassword.setSensitive(true); 3320 changeKSPWParser.addArgument(changeKSPWNewPassword); 3321 3322 final FileArgument changeKSPWNewPasswordFile = new FileArgument(null, 3323 "new-keystore-password-file", false, 1, null, 3324 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_NEW_PW_FILE_DESC.get(), true, 3325 true, true, false); 3326 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePasswordFile", 3327 true); 3328 changeKSPWNewPasswordFile.addLongIdentifier("new-keystore-passphrase-file", 3329 true); 3330 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePassphraseFile", 3331 true); 3332 changeKSPWNewPasswordFile.addLongIdentifier("new-keystore-pin-file", true); 3333 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePINFile", true); 3334 changeKSPWParser.addArgument(changeKSPWNewPasswordFile); 3335 3336 final BooleanArgument changeKSPWPromptForNewPassword = 3337 new BooleanArgument(null, "prompt-for-new-keystore-password", 3338 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_PROMPT_FOR_NEW_PW_DESC.get()); 3339 changeKSPWPromptForNewPassword.addLongIdentifier( 3340 "promptForNewKeystorePassword", true); 3341 changeKSPWPromptForNewPassword.addLongIdentifier( 3342 "prompt-for-new-keystore-passphrase", true); 3343 changeKSPWPromptForNewPassword.addLongIdentifier( 3344 "promptForNewKeystorePassphrase", true); 3345 changeKSPWPromptForNewPassword.addLongIdentifier( 3346 "prompt-for-new-keystore-pin", true); 3347 changeKSPWPromptForNewPassword.addLongIdentifier( 3348 "promptForNewKeystorePIN", true); 3349 changeKSPWParser.addArgument(changeKSPWPromptForNewPassword); 3350 3351 final BooleanArgument changeKSPWDisplayCommand = new BooleanArgument(null, 3352 "display-keytool-command", 1, 3353 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_DISPLAY_COMMAND_DESC.get()); 3354 changeKSPWDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3355 changeKSPWDisplayCommand.addLongIdentifier("show-keytool-command", true); 3356 changeKSPWDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3357 changeKSPWParser.addArgument(changeKSPWDisplayCommand); 3358 3359 changeKSPWParser.addRequiredArgumentSet(changeKSPWCurrentPassword, 3360 changeKSPWCurrentPasswordFile, changeKSPWPromptForCurrentPassword); 3361 changeKSPWParser.addExclusiveArgumentSet(changeKSPWCurrentPassword, 3362 changeKSPWCurrentPasswordFile, changeKSPWPromptForCurrentPassword); 3363 changeKSPWParser.addRequiredArgumentSet(changeKSPWNewPassword, 3364 changeKSPWNewPasswordFile, changeKSPWPromptForNewPassword); 3365 changeKSPWParser.addExclusiveArgumentSet(changeKSPWNewPassword, 3366 changeKSPWNewPasswordFile, changeKSPWPromptForNewPassword); 3367 3368 final LinkedHashMap<String[],String> changeKSPWExamples = 3369 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3370 changeKSPWExamples.put( 3371 new String[] 3372 { 3373 "change-keystore-password", 3374 "--keystore", getPlatformSpecificPath("config", "keystore"), 3375 "--current-keystore-password-file", 3376 getPlatformSpecificPath("config", "current.pin"), 3377 "--new-keystore-password-file", 3378 getPlatformSpecificPath("config", "new.pin"), 3379 "--display-keytool-command" 3380 }, 3381 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_EXAMPLE_1.get( 3382 getPlatformSpecificPath("config", "keystore"), 3383 getPlatformSpecificPath("config", "current.pin"), 3384 getPlatformSpecificPath("config", "new.pin"))); 3385 3386 final SubCommand changeKSPWSubCommand = new SubCommand( 3387 "change-keystore-password", 3388 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_DESC.get(), changeKSPWParser, 3389 changeKSPWExamples); 3390 changeKSPWSubCommand.addName("changeKeystorePassword", true); 3391 changeKSPWSubCommand.addName("change-keystore-passphrase", true); 3392 changeKSPWSubCommand.addName("changeKeystorePassphrase", true); 3393 changeKSPWSubCommand.addName("change-keystore-pin", true); 3394 changeKSPWSubCommand.addName("changeKeystorePIN", true); 3395 changeKSPWSubCommand.addName("storepasswd", true); 3396 3397 parser.addSubCommand(changeKSPWSubCommand); 3398 3399 3400 // Define the "change-private-key-password" subcommand and all of its 3401 // arguments. 3402 final ArgumentParser changePKPWParser = new ArgumentParser( 3403 "change-private-key-password", 3404 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_DESC.get()); 3405 3406 final FileArgument changePKPWKeystore = new FileArgument(null, "keystore", 3407 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_DESC.get(), 3408 true, true, true, false); 3409 changePKPWKeystore.addLongIdentifier("keystore-path", true); 3410 changePKPWKeystore.addLongIdentifier("keystorePath", true); 3411 changePKPWKeystore.addLongIdentifier("keystore-file", true); 3412 changePKPWKeystore.addLongIdentifier("keystoreFile", true); 3413 changePKPWParser.addArgument(changePKPWKeystore); 3414 3415 final StringArgument changePKPWKeystorePassword = new StringArgument(null, 3416 "keystore-password", false, 1, 3417 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3418 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_PW_DESC.get()); 3419 changePKPWKeystorePassword.addLongIdentifier("keystorePassword", true); 3420 changePKPWKeystorePassword.addLongIdentifier("keystore-passphrase", true); 3421 changePKPWKeystorePassword.addLongIdentifier("keystorePassphrase", true); 3422 changePKPWKeystorePassword.addLongIdentifier("keystore-pin", true); 3423 changePKPWKeystorePassword.addLongIdentifier("keystorePIN", true); 3424 changePKPWKeystorePassword.addLongIdentifier("storepass", true); 3425 changePKPWKeystorePassword.setSensitive(true); 3426 changePKPWParser.addArgument(changePKPWKeystorePassword); 3427 3428 final FileArgument changePKPWKeystorePasswordFile = new FileArgument(null, 3429 "keystore-password-file", false, 1, null, 3430 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_PW_FILE_DESC.get(), true, 3431 true, true, false); 3432 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 3433 true); 3434 changePKPWKeystorePasswordFile.addLongIdentifier( 3435 "keystore-passphrase-file", true); 3436 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 3437 true); 3438 changePKPWKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 3439 true); 3440 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 3441 changePKPWParser.addArgument(changePKPWKeystorePasswordFile); 3442 3443 final BooleanArgument changePKPWPromptForKeystorePassword = 3444 new BooleanArgument(null, "prompt-for-keystore-password", 3445 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_KS_PW_DESC.get()); 3446 changePKPWPromptForKeystorePassword.addLongIdentifier( 3447 "promptForKeystorePassword", true); 3448 changePKPWPromptForKeystorePassword.addLongIdentifier( 3449 "prompt-for-keystore-passphrase", true); 3450 changePKPWPromptForKeystorePassword.addLongIdentifier( 3451 "promptForKeystorePassphrase", true); 3452 changePKPWPromptForKeystorePassword.addLongIdentifier( 3453 "prompt-for-keystore-pin", true); 3454 changePKPWPromptForKeystorePassword.addLongIdentifier( 3455 "promptForKeystorePIN", true); 3456 changePKPWParser.addArgument(changePKPWPromptForKeystorePassword); 3457 3458 final StringArgument changePKPWKeystoreType = new StringArgument(null, 3459 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3460 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_TYPE_DESC.get(), 3461 ALLOWED_KEYSTORE_TYPE_VALUES); 3462 changePKPWKeystoreType.addLongIdentifier("key-store-type", true); 3463 changePKPWKeystoreType.addLongIdentifier("keystoreType", true); 3464 changePKPWKeystoreType.addLongIdentifier("keystore-format", true); 3465 changePKPWKeystoreType.addLongIdentifier("key-store-format", true); 3466 changePKPWKeystoreType.addLongIdentifier("keystoreFormat", true); 3467 changePKPWKeystoreType.addLongIdentifier("storetype", true); 3468 changePKPWParser.addArgument(changePKPWKeystoreType); 3469 3470 final StringArgument changePKPWAlias = new StringArgument(null, "alias", 3471 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3472 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_ALIAS_DESC.get()); 3473 changePKPWAlias.addLongIdentifier("nickname", true); 3474 changePKPWParser.addArgument(changePKPWAlias); 3475 3476 final StringArgument changePKPWCurrentPassword = new StringArgument(null, 3477 "current-private-key-password", false, 1, 3478 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3479 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_CURRENT_PW_DESC.get()); 3480 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPassword", 3481 true); 3482 changePKPWCurrentPassword.addLongIdentifier( 3483 "current-private-key-passphrase", true); 3484 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPassphrase", 3485 true); 3486 changePKPWCurrentPassword.addLongIdentifier("current-private-key-pin", 3487 true); 3488 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPIN", true); 3489 changePKPWCurrentPassword.addLongIdentifier("keypass", true); 3490 changePKPWCurrentPassword.setSensitive(true); 3491 changePKPWParser.addArgument(changePKPWCurrentPassword); 3492 3493 final FileArgument changePKPWCurrentPasswordFile = new FileArgument(null, 3494 "current-private-key-password-file", false, 1, null, 3495 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_CURRENT_PW_FILE_DESC.get(), true, 3496 true, true, false); 3497 changePKPWCurrentPasswordFile.addLongIdentifier( 3498 "currentPrivateKeyPasswordFile", true); 3499 changePKPWCurrentPasswordFile.addLongIdentifier( 3500 "current-private-key-passphrase-file", true); 3501 changePKPWCurrentPasswordFile.addLongIdentifier( 3502 "currentPrivateKeyPassphraseFile", true); 3503 changePKPWCurrentPasswordFile.addLongIdentifier( 3504 "current-private-key-pin-file", true); 3505 changePKPWCurrentPasswordFile.addLongIdentifier("currentPrivateKeyPINFile", 3506 true); 3507 changePKPWParser.addArgument(changePKPWCurrentPasswordFile); 3508 3509 final BooleanArgument changePKPWPromptForCurrentPassword = 3510 new BooleanArgument(null, "prompt-for-current-private-key-password", 3511 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_CURRENT_PW_DESC.get()); 3512 changePKPWPromptForCurrentPassword.addLongIdentifier( 3513 "promptForCurrentPrivateKeyPassword", true); 3514 changePKPWPromptForCurrentPassword.addLongIdentifier( 3515 "prompt-for-current-private-key-passphrase", true); 3516 changePKPWPromptForCurrentPassword.addLongIdentifier( 3517 "promptForCurrentPrivateKeyPassphrase", true); 3518 changePKPWPromptForCurrentPassword.addLongIdentifier( 3519 "prompt-for-current-private-key-pin", true); 3520 changePKPWPromptForCurrentPassword.addLongIdentifier( 3521 "promptForCurrentPrivateKeyPIN", true); 3522 changePKPWParser.addArgument(changePKPWPromptForCurrentPassword); 3523 3524 final StringArgument changePKPWNewPassword = new StringArgument(null, 3525 "new-private-key-password", false, 1, 3526 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3527 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_NEW_PW_DESC.get()); 3528 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPassword", 3529 true); 3530 changePKPWNewPassword.addLongIdentifier("new-private-key-passphrase", true); 3531 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPassphrase", true); 3532 changePKPWNewPassword.addLongIdentifier("new-private-key-pin", true); 3533 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPIN", true); 3534 changePKPWNewPassword.addLongIdentifier("new", true); 3535 changePKPWNewPassword.setSensitive(true); 3536 changePKPWParser.addArgument(changePKPWNewPassword); 3537 3538 final FileArgument changePKPWNewPasswordFile = new FileArgument(null, 3539 "new-private-key-password-file", false, 1, null, 3540 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_NEW_PW_FILE_DESC.get(), true, 3541 true, true, false); 3542 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPasswordFile", 3543 true); 3544 changePKPWNewPasswordFile.addLongIdentifier( 3545 "new-private-key-passphrase-file", true); 3546 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPassphraseFile", 3547 true); 3548 changePKPWNewPasswordFile.addLongIdentifier("new-private-key-pin-file", 3549 true); 3550 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPINFile", true); 3551 changePKPWParser.addArgument(changePKPWNewPasswordFile); 3552 3553 final BooleanArgument changePKPWPromptForNewPassword = 3554 new BooleanArgument(null, "prompt-for-new-private-key-password", 3555 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_NEW_PW_DESC.get()); 3556 changePKPWPromptForNewPassword.addLongIdentifier( 3557 "promptForNewPrivateKeyPassword", true); 3558 changePKPWPromptForNewPassword.addLongIdentifier( 3559 "prompt-for-new-private-key-passphrase", true); 3560 changePKPWPromptForNewPassword.addLongIdentifier( 3561 "promptForNewPrivateKeyPassphrase", true); 3562 changePKPWPromptForNewPassword.addLongIdentifier( 3563 "prompt-for-new-private-key-pin", true); 3564 changePKPWPromptForNewPassword.addLongIdentifier( 3565 "promptForNewPrivateKeyPIN", true); 3566 changePKPWParser.addArgument(changePKPWPromptForNewPassword); 3567 3568 final BooleanArgument changePKPWDisplayCommand = new BooleanArgument(null, 3569 "display-keytool-command", 1, 3570 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_DISPLAY_COMMAND_DESC.get()); 3571 changePKPWDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3572 changePKPWDisplayCommand.addLongIdentifier("show-keytool-command", true); 3573 changePKPWDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3574 changePKPWParser.addArgument(changePKPWDisplayCommand); 3575 3576 changePKPWParser.addRequiredArgumentSet(changePKPWKeystorePassword, 3577 changePKPWKeystorePasswordFile, changePKPWPromptForKeystorePassword); 3578 changePKPWParser.addExclusiveArgumentSet(changePKPWKeystorePassword, 3579 changePKPWKeystorePasswordFile, changePKPWPromptForKeystorePassword); 3580 changePKPWParser.addRequiredArgumentSet(changePKPWCurrentPassword, 3581 changePKPWCurrentPasswordFile, changePKPWPromptForCurrentPassword); 3582 changePKPWParser.addExclusiveArgumentSet(changePKPWCurrentPassword, 3583 changePKPWCurrentPasswordFile, changePKPWPromptForCurrentPassword); 3584 changePKPWParser.addRequiredArgumentSet(changePKPWNewPassword, 3585 changePKPWNewPasswordFile, changePKPWPromptForNewPassword); 3586 changePKPWParser.addExclusiveArgumentSet(changePKPWNewPassword, 3587 changePKPWNewPasswordFile, changePKPWPromptForNewPassword); 3588 3589 final LinkedHashMap<String[],String> changePKPWExamples = 3590 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3591 changePKPWExamples.put( 3592 new String[] 3593 { 3594 "change-private-key-password", 3595 "--keystore", getPlatformSpecificPath("config", "keystore"), 3596 "--keystore-password-file", 3597 getPlatformSpecificPath("config", "keystore.pin"), 3598 "--alias", "server-cert", 3599 "--current-private-key-password-file", 3600 getPlatformSpecificPath("config", "current.pin"), 3601 "--new-private-key-password-file", 3602 getPlatformSpecificPath("config", "new.pin"), 3603 "--display-keytool-command" 3604 }, 3605 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_EXAMPLE_1.get( 3606 getPlatformSpecificPath("config", "keystore"), 3607 getPlatformSpecificPath("config", "current.pin"), 3608 getPlatformSpecificPath("config", "new.pin"))); 3609 3610 final SubCommand changePKPWSubCommand = new SubCommand( 3611 "change-private-key-password", 3612 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_DESC.get(), changePKPWParser, 3613 changePKPWExamples); 3614 changePKPWSubCommand.addName("changePrivateKeyPassword", true); 3615 changePKPWSubCommand.addName("change-private-key-passphrase", true); 3616 changePKPWSubCommand.addName("changePrivateKeyPassphrase", true); 3617 changePKPWSubCommand.addName("change-private-key-pin", true); 3618 changePKPWSubCommand.addName("changePrivateKeyPIN", true); 3619 changePKPWSubCommand.addName("change-key-password", true); 3620 changePKPWSubCommand.addName("changeKeyPassword", true); 3621 changePKPWSubCommand.addName("change-key-passphrase", true); 3622 changePKPWSubCommand.addName("changeKeyPassphrase", true); 3623 changePKPWSubCommand.addName("change-key-pin", true); 3624 changePKPWSubCommand.addName("changeKeyPIN", true); 3625 changePKPWSubCommand.addName("keypasswd", true); 3626 3627 parser.addSubCommand(changePKPWSubCommand); 3628 3629 3630 // Define the "copy-keystore" subcommand and all of its arguments. 3631 final ArgumentParser copyKSParser = new ArgumentParser("copy-keystore", 3632 INFO_MANAGE_CERTS_SC_COPY_KS_DESC.get()); 3633 3634 final FileArgument copyKSSourceKeystore = new FileArgument(null, 3635 "source-keystore", true, 1, null, 3636 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_DESC.get(), true, true, true, 3637 false); 3638 copyKSSourceKeystore.addLongIdentifier("sourceKeystore", true); 3639 copyKSSourceKeystore.addLongIdentifier("source-keystore-path", true); 3640 copyKSSourceKeystore.addLongIdentifier("sourceKeystorePath", true); 3641 copyKSSourceKeystore.addLongIdentifier("source-keystore-file", true); 3642 copyKSSourceKeystore.addLongIdentifier("sourceKeystoreFile", true); 3643 copyKSParser.addArgument(copyKSSourceKeystore); 3644 3645 final StringArgument copyKSSourceKeystorePassword = new StringArgument(null, 3646 "source-keystore-password", false, 1, 3647 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3648 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_PW_DESC.get()); 3649 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePassword", 3650 true); 3651 copyKSSourceKeystorePassword.addLongIdentifier("source-keystore-passphrase", 3652 true); 3653 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePassphrase", 3654 true); 3655 copyKSSourceKeystorePassword.addLongIdentifier("source-keystore-pin", true); 3656 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePIN", true); 3657 copyKSParser.addArgument(copyKSSourceKeystorePassword); 3658 3659 final FileArgument copyKSSourceKeystorePasswordFile = new FileArgument(null, 3660 "source-keystore-password-file", false, 1, null, 3661 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_PW_FILE_DESC.get(), true, true, 3662 true, false); 3663 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3664 "sourceKeystorePasswordFile", true); 3665 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3666 "source-keystore-passphrase-file", true); 3667 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3668 "sourceKeystorePassphraseFile", true); 3669 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3670 "source-keystore-pin-file", true); 3671 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3672 "sourceKeystorePINFile", true); 3673 copyKSParser.addArgument(copyKSSourceKeystorePasswordFile); 3674 3675 final BooleanArgument copyKSPromptForSourceKeystorePassword = 3676 new BooleanArgument(null, "prompt-for-source-keystore-password", 1, 3677 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_SRC_KS_PW.get()); 3678 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3679 "promptForSourceKeystorePassword", true); 3680 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3681 "prompt-for-source-keystore-passphrase", true); 3682 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3683 "promptForSourceKeystorePassphrase", true); 3684 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3685 "prompt-for-source-keystore-pin", true); 3686 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3687 "promptForSourceKeystorePIN", true); 3688 copyKSParser.addArgument(copyKSPromptForSourceKeystorePassword); 3689 3690 final StringArgument copyKSSourcePKPassword = new StringArgument(null, 3691 "source-private-key-password", false, 1, 3692 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3693 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_PK_PW_DESC.get()); 3694 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPassword", true); 3695 copyKSSourcePKPassword.addLongIdentifier("source-private-key-passphrase", 3696 true); 3697 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPassphrase", 3698 true); 3699 copyKSSourcePKPassword.addLongIdentifier("source-private-key-pin", true); 3700 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPIN", true); 3701 copyKSParser.addArgument(copyKSSourcePKPassword); 3702 3703 final FileArgument copyKSSourcePKPasswordFile = new FileArgument(null, 3704 "source-private-key-password-file", false, 1, null, 3705 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_PK_PW_FILE_DESC.get(), true, true, 3706 true, false); 3707 copyKSSourcePKPasswordFile.addLongIdentifier( 3708 "sourcePrivateKeyPasswordFile", true); 3709 copyKSSourcePKPasswordFile.addLongIdentifier( 3710 "source-private-key-passphrase-file", true); 3711 copyKSSourcePKPasswordFile.addLongIdentifier( 3712 "sourcePrivateKeyPassphraseFile", true); 3713 copyKSSourcePKPasswordFile.addLongIdentifier( 3714 "source-private-key-pin-file", true); 3715 copyKSSourcePKPasswordFile.addLongIdentifier( 3716 "sourcePrivateKeyPINFile", true); 3717 copyKSParser.addArgument(copyKSSourcePKPasswordFile); 3718 3719 final BooleanArgument copyKSPromptForSourcePKPassword = 3720 new BooleanArgument(null, "prompt-for-source-private-key-password", 1, 3721 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_SRC_PK_PW.get()); 3722 copyKSPromptForSourcePKPassword.addLongIdentifier( 3723 "promptForSourcePrivateKeyPassword", true); 3724 copyKSPromptForSourcePKPassword.addLongIdentifier( 3725 "prompt-for-source-private-key-passphrase", true); 3726 copyKSPromptForSourcePKPassword.addLongIdentifier( 3727 "promptForSourcePrivateKeyPassphrase", true); 3728 copyKSPromptForSourcePKPassword.addLongIdentifier( 3729 "prompt-for-source-private-key-pin", true); 3730 copyKSPromptForSourcePKPassword.addLongIdentifier( 3731 "promptForSourcePrivateKeyPIN", true); 3732 copyKSParser.addArgument(copyKSPromptForSourcePKPassword); 3733 3734 final StringArgument copyKSSourceKeystoreType = new StringArgument(null, 3735 "source-keystore-type", false, 1, 3736 INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3737 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_TYPE.get(), 3738 ALLOWED_KEYSTORE_TYPE_VALUES); 3739 copyKSSourceKeystoreType.addLongIdentifier("source-key-store-type", true); 3740 copyKSSourceKeystoreType.addLongIdentifier("sourceKeystoreType", true); 3741 copyKSSourceKeystoreType.addLongIdentifier("source-keystore-format", true); 3742 copyKSSourceKeystoreType.addLongIdentifier("source-key-store-format", true); 3743 copyKSSourceKeystoreType.addLongIdentifier("sourceKeystoreFormat", true); 3744 copyKSParser.addArgument(copyKSSourceKeystoreType); 3745 3746 final FileArgument copyKSDestKeystore = new FileArgument(null, 3747 "destination-keystore", true, 1, null, 3748 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_DESC.get(), false, true, true, 3749 false); 3750 copyKSDestKeystore.addLongIdentifier("destinationKeystore", true); 3751 copyKSDestKeystore.addLongIdentifier("destination-keystore-path", true); 3752 copyKSDestKeystore.addLongIdentifier("destinationKeystorePath", true); 3753 copyKSDestKeystore.addLongIdentifier("destination-keystore-file", true); 3754 copyKSDestKeystore.addLongIdentifier("destinationKeystoreFile", true); 3755 copyKSDestKeystore.addLongIdentifier("target-keystore", true); 3756 copyKSDestKeystore.addLongIdentifier("targetKeystore", true); 3757 copyKSDestKeystore.addLongIdentifier("target-keystore-path", true); 3758 copyKSDestKeystore.addLongIdentifier("targetKeystorePath", true); 3759 copyKSDestKeystore.addLongIdentifier("target-keystore-file", true); 3760 copyKSDestKeystore.addLongIdentifier("targetKeystoreFile", true); 3761 copyKSParser.addArgument(copyKSDestKeystore); 3762 3763 final StringArgument copyKSDestKeystorePassword = new StringArgument(null, 3764 "destination-keystore-password", false, 1, 3765 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3766 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_PW_DESC.get()); 3767 copyKSDestKeystorePassword.addLongIdentifier("destinationKeystorePassword", 3768 true); 3769 copyKSDestKeystorePassword.addLongIdentifier( 3770 "destination-keystore-passphrase", true); 3771 copyKSDestKeystorePassword.addLongIdentifier( 3772 "destinationKeystorePassphrase", true); 3773 copyKSDestKeystorePassword.addLongIdentifier("destination-keystore-pin", 3774 true); 3775 copyKSDestKeystorePassword.addLongIdentifier("destinationKeystorePIN", 3776 true); 3777 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-password", 3778 true); 3779 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePassword", 3780 true); 3781 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-passphrase", 3782 true); 3783 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePassphrase", 3784 true); 3785 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-pin", true); 3786 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePIN", true); 3787 copyKSParser.addArgument(copyKSDestKeystorePassword); 3788 3789 final FileArgument copyKSDestKeystorePasswordFile = new FileArgument(null, 3790 "destination-keystore-password-file", false, 1, null, 3791 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_PW_FILE_DESC.get(), true, true, 3792 true, false); 3793 copyKSDestKeystorePasswordFile.addLongIdentifier( 3794 "destinationKeystorePasswordFile", true); 3795 copyKSDestKeystorePasswordFile.addLongIdentifier( 3796 "destination-keystore-passphrase-file", true); 3797 copyKSDestKeystorePasswordFile.addLongIdentifier( 3798 "destinationKeystorePassphraseFile", true); 3799 copyKSDestKeystorePasswordFile.addLongIdentifier( 3800 "destination-keystore-pin-file", true); 3801 copyKSDestKeystorePasswordFile.addLongIdentifier( 3802 "destinationKeystorePINFile", true); 3803 copyKSDestKeystorePasswordFile.addLongIdentifier( 3804 "target-keystore-password-file", true); 3805 copyKSDestKeystorePasswordFile.addLongIdentifier( 3806 "targetKeystorePasswordFile", true); 3807 copyKSDestKeystorePasswordFile.addLongIdentifier( 3808 "target-keystore-passphrase-file", true); 3809 copyKSDestKeystorePasswordFile.addLongIdentifier( 3810 "targetKeystorePassphraseFile", true); 3811 copyKSDestKeystorePasswordFile.addLongIdentifier("target-keystore-pin-file", 3812 true); 3813 copyKSDestKeystorePasswordFile.addLongIdentifier("targetKeystorePINFile", 3814 true); 3815 copyKSParser.addArgument(copyKSDestKeystorePasswordFile); 3816 3817 final BooleanArgument copyKSPromptForDestKeystorePassword = 3818 new BooleanArgument(null, "prompt-for-destination-keystore-password", 3819 1, INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_DST_KS_PW.get()); 3820 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3821 "promptForDestinationKeystorePassword", true); 3822 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3823 "prompt-for-Destination-keystore-passphrase", true); 3824 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3825 "promptForDestinationKeystorePassphrase", true); 3826 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3827 "prompt-for-Destination-keystore-pin", true); 3828 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3829 "promptForDestinationKeystorePIN", true); 3830 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3831 "prompt-for-target-keystore-password", true); 3832 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3833 "promptForTargetKeystorePassword", true); 3834 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3835 "prompt-for-Target-keystore-passphrase", true); 3836 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3837 "promptForTargetKeystorePassphrase", true); 3838 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3839 "prompt-for-Target-keystore-pin", true); 3840 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3841 "promptForTargetKeystorePIN", true); 3842 copyKSParser.addArgument(copyKSPromptForDestKeystorePassword); 3843 3844 final StringArgument copyKSDestPKPassword = new StringArgument(null, 3845 "destination-private-key-password", false, 1, 3846 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3847 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_PK_PW_DESC.get()); 3848 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPassword", 3849 true); 3850 copyKSDestPKPassword.addLongIdentifier("destination-private-key-passphrase", 3851 true); 3852 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPassphrase", 3853 true); 3854 copyKSDestPKPassword.addLongIdentifier("destination-private-key-pin", true); 3855 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPIN", true); 3856 copyKSDestPKPassword.addLongIdentifier("target-private-key-password", 3857 true); 3858 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPassword", 3859 true); 3860 copyKSDestPKPassword.addLongIdentifier("target-private-key-passphrase", 3861 true); 3862 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPassphrase", 3863 true); 3864 copyKSDestPKPassword.addLongIdentifier("target-private-key-pin", true); 3865 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPIN", true); 3866 copyKSParser.addArgument(copyKSDestPKPassword); 3867 3868 final FileArgument copyKSDestPKPasswordFile = new FileArgument(null, 3869 "destination-private-key-password-file", false, 1, null, 3870 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_PK_PW_FILE_DESC.get(), true, true, 3871 true, false); 3872 copyKSDestPKPasswordFile.addLongIdentifier( 3873 "destinationPrivateKeyPasswordFile", true); 3874 copyKSDestPKPasswordFile.addLongIdentifier( 3875 "destination-private-key-passphrase-file", true); 3876 copyKSDestPKPasswordFile.addLongIdentifier( 3877 "destinationPrivateKeyPassphraseFile", true); 3878 copyKSDestPKPasswordFile.addLongIdentifier( 3879 "destination-private-key-pin-file", true); 3880 copyKSDestPKPasswordFile.addLongIdentifier( 3881 "destinationPrivateKeyPINFile", true); 3882 copyKSDestPKPasswordFile.addLongIdentifier( 3883 "target-private-key-password-file", true); 3884 copyKSDestPKPasswordFile.addLongIdentifier( 3885 "targetPrivateKeyPasswordFile", true); 3886 copyKSDestPKPasswordFile.addLongIdentifier( 3887 "target-private-key-passphrase-file", true); 3888 copyKSDestPKPasswordFile.addLongIdentifier( 3889 "targetPrivateKeyPassphraseFile", true); 3890 copyKSDestPKPasswordFile.addLongIdentifier( 3891 "target-private-key-pin-file", true); 3892 copyKSDestPKPasswordFile.addLongIdentifier( 3893 "targetPrivateKeyPINFile", true); 3894 copyKSParser.addArgument(copyKSDestPKPasswordFile); 3895 3896 final BooleanArgument copyKSPromptForDestPKPassword = 3897 new BooleanArgument(null, 3898 "prompt-for-destination-private-key-password", 1, 3899 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_DST_PK_PW.get()); 3900 copyKSPromptForDestPKPassword.addLongIdentifier( 3901 "promptForDestinationPrivateKeyPassword", true); 3902 copyKSPromptForDestPKPassword.addLongIdentifier( 3903 "prompt-for-Destination-private-key-passphrase", true); 3904 copyKSPromptForDestPKPassword.addLongIdentifier( 3905 "promptForDestinationPrivateKeyPassphrase", true); 3906 copyKSPromptForDestPKPassword.addLongIdentifier( 3907 "prompt-for-Destination-private-key-pin", true); 3908 copyKSPromptForDestPKPassword.addLongIdentifier( 3909 "promptForDestinationPrivateKeyPIN", true); 3910 copyKSPromptForDestPKPassword.addLongIdentifier( 3911 "prompt-for-target-private-key-password", true); 3912 copyKSPromptForDestPKPassword.addLongIdentifier( 3913 "promptForTargetPrivateKeyPassword", true); 3914 copyKSPromptForDestPKPassword.addLongIdentifier( 3915 "prompt-for-Target-private-key-passphrase", true); 3916 copyKSPromptForDestPKPassword.addLongIdentifier( 3917 "promptForTargetPrivateKeyPassphrase", true); 3918 copyKSPromptForDestPKPassword.addLongIdentifier( 3919 "prompt-for-Target-private-key-pin", true); 3920 copyKSPromptForDestPKPassword.addLongIdentifier( 3921 "promptForTargetPrivateKeyPIN", true); 3922 copyKSParser.addArgument(copyKSPromptForDestPKPassword); 3923 3924 final StringArgument copyKSDestKeystoreType = new StringArgument(null, 3925 "destination-keystore-type", false, 1, 3926 INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3927 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_TYPE.get(), 3928 ALLOWED_KEYSTORE_TYPE_VALUES); 3929 copyKSDestKeystoreType.addLongIdentifier("destination-key-store-type", 3930 true); 3931 copyKSDestKeystoreType.addLongIdentifier("destinationKeystoreType", true); 3932 copyKSDestKeystoreType.addLongIdentifier("destination-keystore-format", 3933 true); 3934 copyKSDestKeystoreType.addLongIdentifier("destination-key-store-format", 3935 true); 3936 copyKSDestKeystoreType.addLongIdentifier("destinationKeystoreFormat", true); 3937 copyKSDestKeystoreType.addLongIdentifier("target-key-store-type", true); 3938 copyKSDestKeystoreType.addLongIdentifier("targetKeystoreType", true); 3939 copyKSDestKeystoreType.addLongIdentifier("target-keystore-format", true); 3940 copyKSDestKeystoreType.addLongIdentifier("target-key-store-format", true); 3941 copyKSDestKeystoreType.addLongIdentifier("targetKeystoreFormat", true); 3942 copyKSParser.addArgument(copyKSDestKeystoreType); 3943 3944 final StringArgument copyKSAlias = new StringArgument(null, "alias", false, 3945 0, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3946 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_ALIAS.get()); 3947 copyKSAlias.addLongIdentifier("nickname", true); 3948 copyKSParser.addArgument(copyKSAlias); 3949 3950 copyKSParser.addRequiredArgumentSet(copyKSSourceKeystorePassword, 3951 copyKSSourceKeystorePasswordFile, 3952 copyKSPromptForSourceKeystorePassword); 3953 copyKSParser.addExclusiveArgumentSet(copyKSSourceKeystorePassword, 3954 copyKSSourceKeystorePasswordFile, 3955 copyKSPromptForSourceKeystorePassword); 3956 copyKSParser.addExclusiveArgumentSet(copyKSSourcePKPassword, 3957 copyKSSourcePKPasswordFile, copyKSPromptForDestPKPassword); 3958 copyKSParser.addExclusiveArgumentSet(copyKSDestKeystorePassword, 3959 copyKSDestKeystorePasswordFile, copyKSPromptForDestKeystorePassword); 3960 copyKSParser.addExclusiveArgumentSet(copyKSDestPKPassword, 3961 copyKSDestPKPasswordFile, copyKSPromptForDestPKPassword); 3962 3963 final LinkedHashMap<String[],String> copyKeyStoreExamples = 3964 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3965 copyKeyStoreExamples.put( 3966 new String[] 3967 { 3968 "copy-keystore", 3969 "--source-keystore", 3970 getPlatformSpecificPath("config", "keystore.jks"), 3971 "--source-keystore-password-file", 3972 getPlatformSpecificPath("config", "keystore.pin"), 3973 "--source-keystore-type", "JKS", 3974 "--destination-keystore", 3975 getPlatformSpecificPath("config", "keystore.p12"), 3976 "--destination-keystore-password-file", 3977 getPlatformSpecificPath("config", "keystore.pin"), 3978 "--destination-keystore-type", "PKCS12" 3979 }, 3980 INFO_MANAGE_CERTS_SC_COPY_KS_EXAMPLE_1.get("keystore.jks", 3981 "keystore.p12")); 3982 3983 final SubCommand copyKeyStoreSubCommand = new SubCommand("copy-keystore", 3984 INFO_MANAGE_CERTS_SC_COPY_KS_DESC.get(), copyKSParser, 3985 copyKeyStoreExamples); 3986 copyKeyStoreSubCommand.addName("copy-key-store", true); 3987 copyKeyStoreSubCommand.addName("copyKeyStore", true); 3988 copyKeyStoreSubCommand.addName("import-keystore", true); 3989 copyKeyStoreSubCommand.addName("import-key-store", true); 3990 copyKeyStoreSubCommand.addName("importKeyStore", true); 3991 copyKeyStoreSubCommand.addName("convert-keystore", true); 3992 copyKeyStoreSubCommand.addName("convert-key-store", true); 3993 copyKeyStoreSubCommand.addName("convertKeyStore", true); 3994 3995 parser.addSubCommand(copyKeyStoreSubCommand); 3996 3997 // Define the "retrieve-server-certificate" subcommand and all of its 3998 // arguments. 3999 final ArgumentParser retrieveCertParser = new ArgumentParser( 4000 "retrieve-server-certificate", 4001 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_DESC.get()); 4002 4003 final StringArgument retrieveCertHostname = new StringArgument('h', 4004 "hostname", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_HOST.get(), 4005 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_HOSTNAME_DESC.get()); 4006 retrieveCertHostname.addLongIdentifier("server-address", true); 4007 retrieveCertHostname.addLongIdentifier("serverAddress", true); 4008 retrieveCertHostname.addLongIdentifier("address", true); 4009 retrieveCertParser.addArgument(retrieveCertHostname); 4010 4011 final IntegerArgument retrieveCertPort = new IntegerArgument('p', 4012 "port", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_PORT.get(), 4013 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_PORT_DESC.get(), 1, 65_535); 4014 retrieveCertPort.addLongIdentifier("server-port", true); 4015 retrieveCertPort.addLongIdentifier("serverPort", true); 4016 retrieveCertParser.addArgument(retrieveCertPort); 4017 4018 final BooleanArgument retrieveCertUseStartTLS = new BooleanArgument('q', 4019 "use-ldap-start-tls", 1, 4020 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_USE_START_TLS_DESC.get()); 4021 retrieveCertUseStartTLS.addLongIdentifier("use-ldap-starttls", true); 4022 retrieveCertUseStartTLS.addLongIdentifier("useLDAPStartTLS", true); 4023 retrieveCertUseStartTLS.addLongIdentifier("use-start-tls", true); 4024 retrieveCertUseStartTLS.addLongIdentifier("use-starttls", true); 4025 retrieveCertUseStartTLS.addLongIdentifier("useStartTLS", true); 4026 retrieveCertParser.addArgument(retrieveCertUseStartTLS); 4027 4028 final FileArgument retrieveCertOutputFile = new FileArgument(null, 4029 "output-file", false, 1, null, 4030 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_FILE_DESC.get(), false, true, 4031 true, false); 4032 retrieveCertOutputFile.addLongIdentifier("outputFile", true); 4033 retrieveCertOutputFile.addLongIdentifier("export-file", true); 4034 retrieveCertOutputFile.addLongIdentifier("exportFile", true); 4035 retrieveCertOutputFile.addLongIdentifier("certificate-file", true); 4036 retrieveCertOutputFile.addLongIdentifier("certificateFile", true); 4037 retrieveCertOutputFile.addLongIdentifier("file", true); 4038 retrieveCertOutputFile.addLongIdentifier("filename", true); 4039 retrieveCertParser.addArgument(retrieveCertOutputFile); 4040 4041 final Set<String> retrieveCertOutputFormatAllowedValues = StaticUtils.setOf( 4042 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 4043 final StringArgument retrieveCertOutputFormat = new StringArgument(null, 4044 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 4045 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_FORMAT_DESC.get(), 4046 retrieveCertOutputFormatAllowedValues, "PEM"); 4047 retrieveCertOutputFormat.addLongIdentifier("outputFormat", true); 4048 retrieveCertParser.addArgument(retrieveCertOutputFormat); 4049 4050 final BooleanArgument retrieveCertOnlyPeer = new BooleanArgument(null, 4051 "only-peer-certificate", 1, 4052 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_ONLY_PEER_DESC.get()); 4053 retrieveCertOnlyPeer.addLongIdentifier("onlyPeerCertificate", true); 4054 retrieveCertOnlyPeer.addLongIdentifier("only-peer", true); 4055 retrieveCertOnlyPeer.addLongIdentifier("onlyPeer", true); 4056 retrieveCertOnlyPeer.addLongIdentifier("peer-certificate-only", true); 4057 retrieveCertOnlyPeer.addLongIdentifier("peerCertificateOnly", true); 4058 retrieveCertOnlyPeer.addLongIdentifier("peer-only", true); 4059 retrieveCertOnlyPeer.addLongIdentifier("peerOnly", true); 4060 retrieveCertParser.addArgument(retrieveCertOnlyPeer); 4061 4062 final BooleanArgument retrieveCertEnableSSLDebugging = new BooleanArgument( 4063 null, "enableSSLDebugging", 1, 4064 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_ENABLE_SSL_DEBUGGING_DESC. 4065 get()); 4066 retrieveCertEnableSSLDebugging.addLongIdentifier("enableTLSDebugging", 4067 true); 4068 retrieveCertEnableSSLDebugging.addLongIdentifier("enableStartTLSDebugging", 4069 true); 4070 retrieveCertEnableSSLDebugging.addLongIdentifier("enable-ssl-debugging", 4071 true); 4072 retrieveCertEnableSSLDebugging.addLongIdentifier("enable-tls-debugging", 4073 true); 4074 retrieveCertEnableSSLDebugging.addLongIdentifier( 4075 "enable-starttls-debugging", true); 4076 retrieveCertEnableSSLDebugging.addLongIdentifier( 4077 "enable-start-tls-debugging", true); 4078 retrieveCertParser.addArgument(retrieveCertEnableSSLDebugging); 4079 addEnableSSLDebuggingArgument(retrieveCertEnableSSLDebugging); 4080 4081 final BooleanArgument retrieveCertVerbose = new BooleanArgument(null, 4082 "verbose", 1, 4083 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_VERBOSE_DESC.get()); 4084 retrieveCertParser.addArgument(retrieveCertVerbose); 4085 4086 retrieveCertParser.addDependentArgumentSet(retrieveCertOutputFormat, 4087 retrieveCertOutputFile); 4088 4089 final LinkedHashMap<String[],String> retrieveCertExamples = 4090 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4091 retrieveCertExamples.put( 4092 new String[] 4093 { 4094 "retrieve-server-certificate", 4095 "--hostname", "ds.example.com", 4096 "--port", "636" 4097 }, 4098 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_1.get( 4099 getPlatformSpecificPath("config", "truststore"))); 4100 retrieveCertExamples.put( 4101 new String[] 4102 { 4103 "retrieve-server-certificate", 4104 "--hostname", "ds.example.com", 4105 "--port", "389", 4106 "--use-ldap-start-tls", 4107 "--only-peer-certificate", 4108 "--output-file", "ds-cert.pem", 4109 "--output-format", "PEM", 4110 "--verbose" 4111 }, 4112 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_2.get( 4113 getPlatformSpecificPath("config", "truststore"))); 4114 4115 final SubCommand retrieveCertSubCommand = new SubCommand( 4116 "retrieve-server-certificate", 4117 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_DESC.get(), retrieveCertParser, 4118 retrieveCertExamples); 4119 retrieveCertSubCommand.addName("retrieveServerCertificate", true); 4120 retrieveCertSubCommand.addName("retrieve-certificate", true); 4121 retrieveCertSubCommand.addName("retrieveCertificate", true); 4122 retrieveCertSubCommand.addName("get-server-certificate", true); 4123 retrieveCertSubCommand.addName("getServerCertificate", true); 4124 retrieveCertSubCommand.addName("get-certificate", true); 4125 retrieveCertSubCommand.addName("getCertificate", true); 4126 retrieveCertSubCommand.addName("display-server-certificate", true); 4127 retrieveCertSubCommand.addName("displayServerCertificate", true); 4128 4129 parser.addSubCommand(retrieveCertSubCommand); 4130 4131 4132 // Define the "trust-server-certificate" subcommand and all of its 4133 // arguments. 4134 final ArgumentParser trustServerParser = new ArgumentParser( 4135 "trust-server-certificate", 4136 INFO_MANAGE_CERTS_SC_TRUST_SERVER_DESC.get()); 4137 4138 final StringArgument trustServerHostname = new StringArgument('h', 4139 "hostname", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_HOST.get(), 4140 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_HOSTNAME_DESC.get()); 4141 trustServerHostname.addLongIdentifier("server-address", true); 4142 trustServerHostname.addLongIdentifier("serverAddress", true); 4143 trustServerHostname.addLongIdentifier("address", true); 4144 trustServerParser.addArgument(trustServerHostname); 4145 4146 final IntegerArgument trustServerPort = new IntegerArgument('p', 4147 "port", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_PORT.get(), 4148 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_PORT_DESC.get(), 1, 65_535); 4149 trustServerPort.addLongIdentifier("server-port", true); 4150 trustServerPort.addLongIdentifier("serverPort", true); 4151 trustServerParser.addArgument(trustServerPort); 4152 4153 final BooleanArgument trustServerUseStartTLS = new BooleanArgument('q', 4154 "use-ldap-start-tls", 1, 4155 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_USE_START_TLS_DESC.get()); 4156 trustServerUseStartTLS.addLongIdentifier("use-ldap-starttls", true); 4157 trustServerUseStartTLS.addLongIdentifier("useLDAPStartTLS", true); 4158 trustServerUseStartTLS.addLongIdentifier("use-start-tls", true); 4159 trustServerUseStartTLS.addLongIdentifier("use-starttls", true); 4160 trustServerUseStartTLS.addLongIdentifier("useStartTLS", true); 4161 trustServerParser.addArgument(trustServerUseStartTLS); 4162 4163 final FileArgument trustServerKeystore = new FileArgument(null, "keystore", 4164 true, 1, null, INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_DESC.get(), 4165 false, true, true, false); 4166 trustServerKeystore.addLongIdentifier("keystore-path", true); 4167 trustServerKeystore.addLongIdentifier("keystorePath", true); 4168 trustServerKeystore.addLongIdentifier("keystore-file", true); 4169 trustServerKeystore.addLongIdentifier("keystoreFile", true); 4170 trustServerParser.addArgument(trustServerKeystore); 4171 4172 final StringArgument trustServerKeystorePassword = new StringArgument(null, 4173 "keystore-password", false, 1, 4174 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 4175 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_PW_DESC.get()); 4176 trustServerKeystorePassword.addLongIdentifier("keystorePassword", true); 4177 trustServerKeystorePassword.addLongIdentifier("keystore-passphrase", true); 4178 trustServerKeystorePassword.addLongIdentifier("keystorePassphrase", true); 4179 trustServerKeystorePassword.addLongIdentifier("keystore-pin", true); 4180 trustServerKeystorePassword.addLongIdentifier("keystorePIN", true); 4181 trustServerKeystorePassword.addLongIdentifier("storepass", true); 4182 trustServerKeystorePassword.setSensitive(true); 4183 trustServerParser.addArgument(trustServerKeystorePassword); 4184 4185 final FileArgument trustServerKeystorePasswordFile = new FileArgument(null, 4186 "keystore-password-file", false, 1, null, 4187 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_PW_FILE_DESC.get(), true, 4188 true, true, false); 4189 trustServerKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 4190 true); 4191 trustServerKeystorePasswordFile.addLongIdentifier( 4192 "keystore-passphrase-file", true); 4193 trustServerKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 4194 true); 4195 trustServerKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 4196 true); 4197 trustServerKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 4198 trustServerParser.addArgument(trustServerKeystorePasswordFile); 4199 4200 final BooleanArgument trustServerPromptForKeystorePassword = 4201 new BooleanArgument(null, "prompt-for-keystore-password", 4202 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_PROMPT_FOR_KS_PW_DESC.get()); 4203 trustServerPromptForKeystorePassword.addLongIdentifier( 4204 "promptForKeystorePassword", true); 4205 trustServerPromptForKeystorePassword.addLongIdentifier( 4206 "prompt-for-keystore-passphrase", true); 4207 trustServerPromptForKeystorePassword.addLongIdentifier( 4208 "promptForKeystorePassphrase", true); 4209 trustServerPromptForKeystorePassword.addLongIdentifier( 4210 "prompt-for-keystore-pin", true); 4211 trustServerPromptForKeystorePassword.addLongIdentifier( 4212 "promptForKeystorePIN", true); 4213 trustServerParser.addArgument(trustServerPromptForKeystorePassword); 4214 4215 final StringArgument trustServerKeystoreType = new StringArgument(null, 4216 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 4217 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_TYPE_DESC.get(), 4218 ALLOWED_KEYSTORE_TYPE_VALUES); 4219 trustServerKeystoreType.addLongIdentifier("key-store-type", true); 4220 trustServerKeystoreType.addLongIdentifier("keystoreType", true); 4221 trustServerKeystoreType.addLongIdentifier("keystore-format", true); 4222 trustServerKeystoreType.addLongIdentifier("key-store-format", true); 4223 trustServerKeystoreType.addLongIdentifier("keystoreFormat", true); 4224 trustServerKeystoreType.addLongIdentifier("storetype", true); 4225 trustServerParser.addArgument(trustServerKeystoreType); 4226 4227 final StringArgument trustServerAlias = new StringArgument(null, 4228 "alias", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 4229 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ALIAS_DESC.get()); 4230 trustServerAlias.addLongIdentifier("nickname", true); 4231 trustServerParser.addArgument(trustServerAlias); 4232 4233 final BooleanArgument trustServerIssuersOnly = new BooleanArgument(null, 4234 "issuers-only", 1, 4235 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ISSUERS_ONLY_DESC.get()); 4236 trustServerIssuersOnly.addLongIdentifier("issuersOnly", true); 4237 trustServerIssuersOnly.addLongIdentifier("issuer-certificates-only", true); 4238 trustServerIssuersOnly.addLongIdentifier("issuerCertificatesOnly", true); 4239 trustServerIssuersOnly.addLongIdentifier("only-issuers", true); 4240 trustServerIssuersOnly.addLongIdentifier("onlyIssuers", true); 4241 trustServerIssuersOnly.addLongIdentifier("only-issuer-certificates", true); 4242 trustServerIssuersOnly.addLongIdentifier("onlyIssuerCertificates", true); 4243 trustServerParser.addArgument(trustServerIssuersOnly); 4244 4245 final BooleanArgument trustServerEnableSSLDebugging = new BooleanArgument( 4246 null, "enableSSLDebugging", 1, 4247 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ENABLE_SSL_DEBUGGING_DESC.get()); 4248 trustServerEnableSSLDebugging.addLongIdentifier("enableTLSDebugging", true); 4249 trustServerEnableSSLDebugging.addLongIdentifier("enableStartTLSDebugging", 4250 true); 4251 trustServerEnableSSLDebugging.addLongIdentifier("enable-ssl-debugging", 4252 true); 4253 trustServerEnableSSLDebugging.addLongIdentifier("enable-tls-debugging", 4254 true); 4255 trustServerEnableSSLDebugging.addLongIdentifier("enable-starttls-debugging", 4256 true); 4257 trustServerEnableSSLDebugging.addLongIdentifier( 4258 "enable-start-tls-debugging", true); 4259 trustServerParser.addArgument(trustServerEnableSSLDebugging); 4260 addEnableSSLDebuggingArgument(trustServerEnableSSLDebugging); 4261 4262 final BooleanArgument trustServerVerbose = new BooleanArgument(null, 4263 "verbose", 1, 4264 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_VERBOSE_DESC.get()); 4265 trustServerParser.addArgument(trustServerVerbose); 4266 4267 final BooleanArgument trustServerNoPrompt = new BooleanArgument(null, 4268 "no-prompt", 1, 4269 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_NO_PROMPT_DESC.get()); 4270 trustServerNoPrompt.addLongIdentifier("noPrompt", true); 4271 trustServerParser.addArgument(trustServerNoPrompt); 4272 4273 trustServerParser.addRequiredArgumentSet(trustServerKeystorePassword, 4274 trustServerKeystorePasswordFile, trustServerPromptForKeystorePassword); 4275 trustServerParser.addExclusiveArgumentSet(trustServerKeystorePassword, 4276 trustServerKeystorePasswordFile, trustServerPromptForKeystorePassword); 4277 4278 final LinkedHashMap<String[],String> trustServerExamples = 4279 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4280 trustServerExamples.put( 4281 new String[] 4282 { 4283 "trust-server-certificate", 4284 "--hostname", "ds.example.com", 4285 "--port", "636", 4286 "--keystore", getPlatformSpecificPath("config", "truststore"), 4287 "--keystore-password-file", 4288 getPlatformSpecificPath("config", "truststore.pin"), 4289 "--verbose" 4290 }, 4291 INFO_MANAGE_CERTS_SC_TRUST_SERVER_EXAMPLE_1.get( 4292 getPlatformSpecificPath("config", "truststore"))); 4293 trustServerExamples.put( 4294 new String[] 4295 { 4296 "trust-server-certificate", 4297 "--hostname", "ds.example.com", 4298 "--port", "389", 4299 "--use-ldap-start-tls", 4300 "--keystore", getPlatformSpecificPath("config", "truststore"), 4301 "--keystore-password-file", 4302 getPlatformSpecificPath("config", "truststore.pin"), 4303 "--issuers-only", 4304 "--alias", "ds-start-tls-cert", 4305 "--no-prompt" 4306 }, 4307 INFO_MANAGE_CERTS_SC_TRUST_SERVER_EXAMPLE_2.get( 4308 getPlatformSpecificPath("config", "truststore"))); 4309 4310 final SubCommand trustServerSubCommand = new SubCommand( 4311 "trust-server-certificate", 4312 INFO_MANAGE_CERTS_SC_TRUST_SERVER_DESC.get(), trustServerParser, 4313 trustServerExamples); 4314 trustServerSubCommand.addName("trustServerCertificate", true); 4315 trustServerSubCommand.addName("trust-server", true); 4316 trustServerSubCommand.addName("trustServer", true); 4317 4318 parser.addSubCommand(trustServerSubCommand); 4319 4320 4321 // Define the "check-certificate-usability" subcommand and all of its 4322 // arguments. 4323 final ArgumentParser checkUsabilityParser = new ArgumentParser( 4324 "check-certificate-usability", 4325 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_DESC.get()); 4326 4327 final FileArgument checkUsabilityKeystore = new FileArgument(null, 4328 "keystore", true, 1, null, 4329 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_DESC.get(), 4330 true, true, true, false); 4331 checkUsabilityKeystore.addLongIdentifier("keystore-path", true); 4332 checkUsabilityKeystore.addLongIdentifier("keystorePath", true); 4333 checkUsabilityKeystore.addLongIdentifier("keystore-file", true); 4334 checkUsabilityKeystore.addLongIdentifier("keystoreFile", true); 4335 checkUsabilityParser.addArgument(checkUsabilityKeystore); 4336 4337 final StringArgument checkUsabilityKeystorePassword = new StringArgument( 4338 null, "keystore-password", false, 1, 4339 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 4340 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_PW_DESC.get()); 4341 checkUsabilityKeystorePassword.addLongIdentifier("keystorePassword", true); 4342 checkUsabilityKeystorePassword.addLongIdentifier("keystore-passphrase", 4343 true); 4344 checkUsabilityKeystorePassword.addLongIdentifier("keystorePassphrase", 4345 true); 4346 checkUsabilityKeystorePassword.addLongIdentifier("keystore-pin", true); 4347 checkUsabilityKeystorePassword.addLongIdentifier("keystorePIN", true); 4348 checkUsabilityKeystorePassword.addLongIdentifier("storepass", true); 4349 checkUsabilityKeystorePassword.setSensitive(true); 4350 checkUsabilityParser.addArgument(checkUsabilityKeystorePassword); 4351 4352 final FileArgument checkUsabilityKeystorePasswordFile = new FileArgument( 4353 null, "keystore-password-file", false, 1, null, 4354 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_PW_FILE_DESC.get(), true, 4355 true, true, false); 4356 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 4357 true); 4358 checkUsabilityKeystorePasswordFile.addLongIdentifier( 4359 "keystore-passphrase-file", true); 4360 checkUsabilityKeystorePasswordFile.addLongIdentifier( 4361 "keystorePassphraseFile", true); 4362 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 4363 true); 4364 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystorePINFile", 4365 true); 4366 checkUsabilityParser.addArgument(checkUsabilityKeystorePasswordFile); 4367 4368 final BooleanArgument checkUsabilityPromptForKeystorePassword = 4369 new BooleanArgument(null, "prompt-for-keystore-password", 4370 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_PROMPT_FOR_KS_PW_DESC.get()); 4371 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4372 "promptForKeystorePassword", true); 4373 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4374 "prompt-for-keystore-passphrase", true); 4375 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4376 "promptForKeystorePassphrase", true); 4377 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4378 "prompt-for-keystore-pin", true); 4379 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4380 "promptForKeystorePIN", true); 4381 checkUsabilityParser.addArgument(checkUsabilityPromptForKeystorePassword); 4382 4383 final StringArgument checkUsabilityKeystoreType = new StringArgument(null, 4384 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 4385 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_TYPE_DESC.get(), 4386 ALLOWED_KEYSTORE_TYPE_VALUES); 4387 checkUsabilityKeystoreType.addLongIdentifier("key-store-type", true); 4388 checkUsabilityKeystoreType.addLongIdentifier("keystoreType", true); 4389 checkUsabilityKeystoreType.addLongIdentifier("keystore-format", true); 4390 checkUsabilityKeystoreType.addLongIdentifier("key-store-format", true); 4391 checkUsabilityKeystoreType.addLongIdentifier("keystoreFormat", true); 4392 checkUsabilityKeystoreType.addLongIdentifier("storetype", true); 4393 checkUsabilityParser.addArgument(checkUsabilityKeystoreType); 4394 4395 final StringArgument checkUsabilityAlias = new StringArgument(null, "alias", 4396 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 4397 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_ALIAS_DESC.get()); 4398 checkUsabilityAlias.addLongIdentifier("nickname", true); 4399 checkUsabilityParser.addArgument(checkUsabilityAlias); 4400 4401 final BooleanArgument checkUsabilityIgnoreSHA1Signature = 4402 new BooleanArgument(null, 4403 "allow-sha-1-signature-for-issuer-certificates", 1, 4404 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_IGNORE_SHA1_WARNING_DESC. 4405 get()); 4406 checkUsabilityIgnoreSHA1Signature.addLongIdentifier( 4407 "allow-sha1-signature-for-issuer-certificates", true); 4408 checkUsabilityIgnoreSHA1Signature.addLongIdentifier( 4409 "allowSHA1SignatureForIssuerCertificates", true); 4410 checkUsabilityParser.addArgument(checkUsabilityIgnoreSHA1Signature); 4411 4412 checkUsabilityParser.addRequiredArgumentSet(checkUsabilityKeystorePassword, 4413 checkUsabilityKeystorePasswordFile, 4414 checkUsabilityPromptForKeystorePassword); 4415 checkUsabilityParser.addExclusiveArgumentSet(checkUsabilityKeystorePassword, 4416 checkUsabilityKeystorePasswordFile, 4417 checkUsabilityPromptForKeystorePassword); 4418 4419 final LinkedHashMap<String[],String> checkUsabilityExamples = 4420 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4421 checkUsabilityExamples.put( 4422 new String[] 4423 { 4424 "check-certificate-usability", 4425 "--keystore", getPlatformSpecificPath("config", "keystore"), 4426 "--keystore-password-file", 4427 getPlatformSpecificPath("config", "keystore.pin"), 4428 "--alias", "server-cert" 4429 }, 4430 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_EXAMPLE_1.get( 4431 getPlatformSpecificPath("config", "keystore"))); 4432 4433 final SubCommand checkUsabilitySubCommand = new SubCommand( 4434 "check-certificate-usability", 4435 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_DESC.get(), checkUsabilityParser, 4436 checkUsabilityExamples); 4437 checkUsabilitySubCommand.addName("checkCertificateUsability", true); 4438 checkUsabilitySubCommand.addName("check-usability", true); 4439 checkUsabilitySubCommand.addName("checkUsability", true); 4440 4441 parser.addSubCommand(checkUsabilitySubCommand); 4442 4443 4444 // Define the "display-certificate-file" subcommand and all of its 4445 // arguments. 4446 final ArgumentParser displayCertParser = new ArgumentParser( 4447 "display-certificate-file", 4448 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_DESC.get()); 4449 4450 final FileArgument displayCertFile = new FileArgument(null, 4451 "certificate-file", true, 1, null, 4452 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_FILE_DESC.get(), true, true, 4453 true, false); 4454 displayCertFile.addLongIdentifier("certificateFile", true); 4455 displayCertFile.addLongIdentifier("input-file", true); 4456 displayCertFile.addLongIdentifier("inputFile", true); 4457 displayCertFile.addLongIdentifier("file", true); 4458 displayCertFile.addLongIdentifier("filename", true); 4459 displayCertParser.addArgument(displayCertFile); 4460 4461 final BooleanArgument displayCertVerbose = new BooleanArgument(null, 4462 "verbose", 1, 4463 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_VERBOSE_DESC.get()); 4464 displayCertParser.addArgument(displayCertVerbose); 4465 4466 final BooleanArgument displayCertDisplayCommand = new BooleanArgument(null, 4467 "display-keytool-command", 1, 4468 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 4469 displayCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 4470 displayCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 4471 displayCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 4472 displayCertParser.addArgument(displayCertDisplayCommand); 4473 4474 final LinkedHashMap<String[],String> displayCertExamples = 4475 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4476 displayCertExamples.put( 4477 new String[] 4478 { 4479 "display-certificate-file", 4480 "--certificate-file", "certificate.pem", 4481 }, 4482 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_EXAMPLE_1.get("certificate.pem")); 4483 displayCertExamples.put( 4484 new String[] 4485 { 4486 "display-certificate-file", 4487 "--certificate-file", "certificate.pem", 4488 "--verbose", 4489 "--display-keytool-command" 4490 }, 4491 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_EXAMPLE_2.get("certificate.pem")); 4492 4493 final SubCommand displayCertSubCommand = new SubCommand( 4494 "display-certificate-file", 4495 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_DESC.get(), displayCertParser, 4496 displayCertExamples); 4497 displayCertSubCommand.addName("displayCertificateFile", true); 4498 displayCertSubCommand.addName("display-certificate", true); 4499 displayCertSubCommand.addName("displayCertificate", true); 4500 displayCertSubCommand.addName("display-certificates", true); 4501 displayCertSubCommand.addName("displayCertificates", true); 4502 displayCertSubCommand.addName("show-certificate", true); 4503 displayCertSubCommand.addName("showCertificate", true); 4504 displayCertSubCommand.addName("show-certificate-file", true); 4505 displayCertSubCommand.addName("showCertificateFile", true); 4506 displayCertSubCommand.addName("show-certificates", true); 4507 displayCertSubCommand.addName("showCertificates", true); 4508 displayCertSubCommand.addName("print-certificate-file", true); 4509 displayCertSubCommand.addName("printCertificateFile", true); 4510 displayCertSubCommand.addName("print-certificate", true); 4511 displayCertSubCommand.addName("printCertificate", true); 4512 displayCertSubCommand.addName("print-certificates", true); 4513 displayCertSubCommand.addName("printCertificates", true); 4514 displayCertSubCommand.addName("printcert", true); 4515 4516 parser.addSubCommand(displayCertSubCommand); 4517 4518 4519 // Define the "display-certificate-signing-request-file" subcommand and all 4520 // of its arguments. 4521 final ArgumentParser displayCSRParser = new ArgumentParser( 4522 "display-certificate-signing-request-file", 4523 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_DESC.get()); 4524 4525 final FileArgument displayCSRFile = new FileArgument(null, 4526 "certificate-signing-request-file", true, 1, null, 4527 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_FILE_DESC.get(), true, true, 4528 true, false); 4529 displayCSRFile.addLongIdentifier("certificateSigningRequestFile", true); 4530 displayCSRFile.addLongIdentifier("request-file", true); 4531 displayCSRFile.addLongIdentifier("requestFile", true); 4532 displayCSRFile.addLongIdentifier("input-file", true); 4533 displayCSRFile.addLongIdentifier("inputFile", true); 4534 displayCSRFile.addLongIdentifier("file", true); 4535 displayCSRFile.addLongIdentifier("filename", true); 4536 displayCSRParser.addArgument(displayCSRFile); 4537 4538 final BooleanArgument displayCSRVerbose = new BooleanArgument(null, 4539 "verbose", 1, 4540 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_VERBOSE_DESC.get()); 4541 displayCSRParser.addArgument(displayCSRVerbose); 4542 4543 final BooleanArgument displayCSRDisplayCommand = new BooleanArgument(null, 4544 "display-keytool-command", 1, 4545 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 4546 displayCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 4547 displayCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 4548 displayCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 4549 displayCSRParser.addArgument(displayCSRDisplayCommand); 4550 4551 final LinkedHashMap<String[],String> displayCSRExamples = 4552 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 4553 displayCSRExamples.put( 4554 new String[] 4555 { 4556 "display-certificate-signing-request-file", 4557 "--certificate-signing-request-file", "server-cert.csr", 4558 "--display-keytool-command" 4559 }, 4560 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_EXAMPLE_1.get("server-cert.csr")); 4561 4562 final SubCommand displayCSRSubCommand = new SubCommand( 4563 "display-certificate-signing-request-file", 4564 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_DESC.get(), displayCSRParser, 4565 displayCSRExamples); 4566 displayCSRSubCommand.addName("displayCertificateSigningRequestFile", true); 4567 displayCSRSubCommand.addName("display-certificate-signing-request", true); 4568 displayCSRSubCommand.addName("displayCertificateSigningRequest", true); 4569 displayCSRSubCommand.addName("display-certificate-request-file", true); 4570 displayCSRSubCommand.addName("displayCertificateRequestFile", true); 4571 displayCSRSubCommand.addName("display-certificate-request", true); 4572 displayCSRSubCommand.addName("displayCertificateRequest", true); 4573 displayCSRSubCommand.addName("display-csr-file", true); 4574 displayCSRSubCommand.addName("displayCSRFile", true); 4575 displayCSRSubCommand.addName("display-csr", true); 4576 displayCSRSubCommand.addName("displayCSR", true); 4577 displayCSRSubCommand.addName("show-certificate-signing-request-file", true); 4578 displayCSRSubCommand.addName("showCertificateSigningRequestFile", true); 4579 displayCSRSubCommand.addName("show-certificate-signing-request", true); 4580 displayCSRSubCommand.addName("showCertificateSigningRequest", true); 4581 displayCSRSubCommand.addName("show-certificate-request-file", true); 4582 displayCSRSubCommand.addName("showCertificateRequestFile", true); 4583 displayCSRSubCommand.addName("show-certificate-request", true); 4584 displayCSRSubCommand.addName("showCertificateRequest", true); 4585 displayCSRSubCommand.addName("show-csr-file", true); 4586 displayCSRSubCommand.addName("showCSRFile", true); 4587 displayCSRSubCommand.addName("show-csr", true); 4588 displayCSRSubCommand.addName("showCSR", true); 4589 displayCSRSubCommand.addName("print-certificate-signing-request-file", 4590 true); 4591 displayCSRSubCommand.addName("printCertificateSigningRequestFile", true); 4592 displayCSRSubCommand.addName("print-certificate-signing-request", true); 4593 displayCSRSubCommand.addName("printCertificateSigningRequest", true); 4594 displayCSRSubCommand.addName("print-certificate-request-file", true); 4595 displayCSRSubCommand.addName("printCertificateRequestFile", true); 4596 displayCSRSubCommand.addName("print-certificate-request", true); 4597 displayCSRSubCommand.addName("printCertificateRequest", true); 4598 displayCSRSubCommand.addName("print-csr-file", true); 4599 displayCSRSubCommand.addName("printCSRFile", true); 4600 displayCSRSubCommand.addName("print-csr", true); 4601 displayCSRSubCommand.addName("printCSR", true); 4602 displayCSRSubCommand.addName("printcertreq", true); 4603 4604 parser.addSubCommand(displayCSRSubCommand); 4605 } 4606 4607 4608 4609 /** 4610 * Constructs a platform-specific relative path from the provided elements. 4611 * 4612 * @param pathElements The elements of the path to construct. It must not 4613 * be {@code null} or empty. 4614 * 4615 * @return The constructed path. 4616 */ 4617 @NotNull() 4618 private static String getPlatformSpecificPath( 4619 @NotNull final String... pathElements) 4620 { 4621 final StringBuilder buffer = new StringBuilder(); 4622 for (int i=0; i < pathElements.length; i++) 4623 { 4624 if (i > 0) 4625 { 4626 buffer.append(File.separatorChar); 4627 } 4628 4629 buffer.append(pathElements[i]); 4630 } 4631 4632 return buffer.toString(); 4633 } 4634 4635 4636 4637 /** 4638 * Performs the core set of processing for this tool. 4639 * 4640 * @return A result code that indicates whether the processing completed 4641 * successfully. 4642 */ 4643 @Override() 4644 @NotNull() 4645 public ResultCode doToolProcessing() 4646 { 4647 final SubCommand selectedSubCommand = globalParser.getSelectedSubCommand(); 4648 if (selectedSubCommand == null) 4649 { 4650 // This should never happen. 4651 wrapErr(0, WRAP_COLUMN, ERR_MANAGE_CERTS_NO_SUBCOMMAND.get()); 4652 return ResultCode.PARAM_ERROR; 4653 } 4654 4655 subCommandParser = selectedSubCommand.getArgumentParser(); 4656 4657 if (selectedSubCommand.hasName("list-certificates")) 4658 { 4659 return doListCertificates(); 4660 } 4661 else if (selectedSubCommand.hasName("export-certificate")) 4662 { 4663 return doExportCertificate(); 4664 } 4665 else if (selectedSubCommand.hasName("export-private-key")) 4666 { 4667 return doExportPrivateKey(); 4668 } 4669 else if (selectedSubCommand.hasName("import-certificate")) 4670 { 4671 return doImportCertificate(); 4672 } 4673 else if (selectedSubCommand.hasName("delete-certificate")) 4674 { 4675 return doDeleteCertificate(); 4676 } 4677 else if (selectedSubCommand.hasName("generate-self-signed-certificate")) 4678 { 4679 return doGenerateOrSignCertificateOrCSR(); 4680 } 4681 else if (selectedSubCommand.hasName("generate-certificate-signing-request")) 4682 { 4683 return doGenerateOrSignCertificateOrCSR(); 4684 } 4685 else if (selectedSubCommand.hasName("sign-certificate-signing-request")) 4686 { 4687 return doGenerateOrSignCertificateOrCSR(); 4688 } 4689 else if (selectedSubCommand.hasName("change-certificate-alias")) 4690 { 4691 return doChangeCertificateAlias(); 4692 } 4693 else if (selectedSubCommand.hasName("change-keystore-password")) 4694 { 4695 return doChangeKeystorePassword(); 4696 } 4697 else if (selectedSubCommand.hasName("change-private-key-password")) 4698 { 4699 return doChangePrivateKeyPassword(); 4700 } 4701 else if (selectedSubCommand.hasName("copy-keystore")) 4702 { 4703 return doCopyKeystore(); 4704 } 4705 else if (selectedSubCommand.hasName("retrieve-server-certificate")) 4706 { 4707 return doRetrieveServerCertificate(); 4708 } 4709 else if (selectedSubCommand.hasName("trust-server-certificate")) 4710 { 4711 return doTrustServerCertificate(); 4712 } 4713 else if (selectedSubCommand.hasName("check-certificate-usability")) 4714 { 4715 return doCheckCertificateUsability(); 4716 } 4717 else if (selectedSubCommand.hasName("display-certificate-file")) 4718 { 4719 return doDisplayCertificateFile(); 4720 } 4721 else if (selectedSubCommand.hasName( 4722 "display-certificate-signing-request-file")) 4723 { 4724 return doDisplayCertificateSigningRequestFile(); 4725 } 4726 else 4727 { 4728 // This should never happen. 4729 wrapErr(0, WRAP_COLUMN, 4730 ERR_MANAGE_CERTS_UNKNOWN_SUBCOMMAND.get( 4731 selectedSubCommand.getPrimaryName())); 4732 return ResultCode.PARAM_ERROR; 4733 } 4734 } 4735 4736 4737 4738 /** 4739 * Performs the necessary processing for the list-certificates subcommand. 4740 * 4741 * @return A result code that indicates whether the processing completed 4742 * successfully. 4743 */ 4744 @NotNull() 4745 private ResultCode doListCertificates() 4746 { 4747 // Get the values of a number of configured arguments. 4748 final BooleanArgument displayPEMArgument = 4749 subCommandParser.getBooleanArgument("display-pem-certificate"); 4750 final boolean displayPEM = 4751 ((displayPEMArgument != null) && displayPEMArgument.isPresent()); 4752 4753 final BooleanArgument verboseArgument = 4754 subCommandParser.getBooleanArgument("verbose"); 4755 final boolean verbose = 4756 ((verboseArgument != null) && verboseArgument.isPresent()); 4757 4758 final Map<String,String> missingAliases; 4759 final Set<String> aliases; 4760 final StringArgument aliasArgument = 4761 subCommandParser.getStringArgument("alias"); 4762 if ((aliasArgument == null) || (! aliasArgument.isPresent())) 4763 { 4764 aliases = Collections.emptySet(); 4765 missingAliases = Collections.emptyMap(); 4766 } 4767 else 4768 { 4769 final List<String> values = aliasArgument.getValues(); 4770 aliases = new LinkedHashSet<>(StaticUtils.computeMapCapacity( 4771 values.size())); 4772 missingAliases = 4773 new LinkedHashMap<>(StaticUtils.computeMapCapacity(values.size())); 4774 for (final String alias : values) 4775 { 4776 final String lowerAlias = StaticUtils.toLowerCase(alias); 4777 aliases.add(StaticUtils.toLowerCase(lowerAlias)); 4778 missingAliases.put(lowerAlias, alias); 4779 } 4780 } 4781 4782 final String keystoreType; 4783 final File keystorePath = getKeystorePath(); 4784 try 4785 { 4786 keystoreType = inferKeystoreType(keystorePath); 4787 } 4788 catch (final LDAPException le) 4789 { 4790 Debug.debugException(le); 4791 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4792 return le.getResultCode(); 4793 } 4794 4795 final char[] keystorePassword; 4796 try 4797 { 4798 keystorePassword = getKeystorePassword(keystorePath); 4799 } 4800 catch (final LDAPException le) 4801 { 4802 Debug.debugException(le); 4803 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4804 return le.getResultCode(); 4805 } 4806 4807 final BooleanArgument displayKeytoolCommandArgument = 4808 subCommandParser.getBooleanArgument("display-keytool-command"); 4809 if ((displayKeytoolCommandArgument != null) && 4810 displayKeytoolCommandArgument.isPresent()) 4811 { 4812 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 4813 keytoolArgs.add("-list"); 4814 4815 keytoolArgs.add("-keystore"); 4816 keytoolArgs.add(keystorePath.getAbsolutePath()); 4817 keytoolArgs.add("-storetype"); 4818 keytoolArgs.add(keystoreType); 4819 4820 if (keystorePassword != null) 4821 { 4822 keytoolArgs.add("-storepass"); 4823 keytoolArgs.add("*****REDACTED*****"); 4824 } 4825 4826 for (final String alias : missingAliases.values()) 4827 { 4828 keytoolArgs.add("-alias"); 4829 keytoolArgs.add(alias); 4830 } 4831 4832 if (displayPEM) 4833 { 4834 keytoolArgs.add("-rfc"); 4835 } 4836 4837 if (verbose) 4838 { 4839 keytoolArgs.add("-v"); 4840 } 4841 4842 displayKeytoolCommand(keytoolArgs); 4843 } 4844 4845 4846 // Get the keystore. 4847 final KeyStore keystore; 4848 try 4849 { 4850 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 4851 } 4852 catch (final LDAPException le) 4853 { 4854 Debug.debugException(le); 4855 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4856 return le.getResultCode(); 4857 } 4858 4859 4860 // Display a message with the keystore type. 4861 wrapOut(0, WRAP_COLUMN, 4862 INFO_MANAGE_CERTS_LIST_KEYSTORE_TYPE.get(keystoreType)); 4863 4864 4865 // Iterate through the keystore and display the appropriate certificates. 4866 final Enumeration<String> aliasEnumeration; 4867 try 4868 { 4869 aliasEnumeration = keystore.aliases(); 4870 } 4871 catch (final Exception e) 4872 { 4873 Debug.debugException(e); 4874 err(); 4875 wrapErr(0, WRAP_COLUMN, 4876 ERR_MANAGE_CERTS_LIST_CERTS_CANNOT_GET_ALIASES.get( 4877 keystorePath.getAbsolutePath())); 4878 e.printStackTrace(getErr()); 4879 return ResultCode.LOCAL_ERROR; 4880 } 4881 4882 int listedCount = 0; 4883 ResultCode resultCode = ResultCode.SUCCESS; 4884 while (aliasEnumeration.hasMoreElements()) 4885 { 4886 final String alias = aliasEnumeration.nextElement(); 4887 final String lowerAlias = StaticUtils.toLowerCase(alias); 4888 if ((!aliases.isEmpty()) && (missingAliases.remove(lowerAlias) == null)) 4889 { 4890 // We don't care about this alias. 4891 continue; 4892 } 4893 4894 final X509Certificate[] certificateChain; 4895 try 4896 { 4897 // NOTE: Keystore entries that have private keys may have a certificate 4898 // chain associated with them (the end certificate plus all of the 4899 // issuer certificates). In that case all of those certificates in the 4900 // chain will be stored under the same alias, and the only way we can 4901 // access them is to call the getCertificateChain method. However, if 4902 // the keystore only has a certificate for the alias but no private key, 4903 // then the entry will not have a chain, and the call to 4904 // getCertificateChain will return null for that alias. We want to be 4905 // able to handle both of these cases, so we will first try 4906 // getCertificateChain to see if we can get a complete chain, but if 4907 // that returns null, then use getCertificate to see if we can get a 4908 // single certificate. That call to getCertificate can also return null 4909 // because the entry with this alias might be some other type of entry, 4910 // like a secret key entry. 4911 Certificate[] chain = keystore.getCertificateChain(alias); 4912 if ((chain == null) || (chain.length == 0)) 4913 { 4914 final Certificate cert = keystore.getCertificate(alias); 4915 if (cert == null) 4916 { 4917 continue; 4918 } 4919 else 4920 { 4921 chain = new Certificate[] { cert }; 4922 } 4923 } 4924 4925 certificateChain = new X509Certificate[chain.length]; 4926 for (int i = 0; i < chain.length; i++) 4927 { 4928 certificateChain[i] = new X509Certificate(chain[i].getEncoded()); 4929 } 4930 } 4931 catch (final Exception e) 4932 { 4933 Debug.debugException(e); 4934 err(); 4935 wrapErr(0, WRAP_COLUMN, 4936 ERR_MANAGE_CERTS_LIST_CERTS_ERROR_GETTING_CERT.get(alias, 4937 StaticUtils.getExceptionMessage(e))); 4938 resultCode = ResultCode.LOCAL_ERROR; 4939 continue; 4940 } 4941 4942 listedCount++; 4943 for (int i = 0; i < certificateChain.length; i++) 4944 { 4945 out(); 4946 if (certificateChain.length == 1) 4947 { 4948 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_ALIAS_WITHOUT_CHAIN.get( 4949 alias)); 4950 } 4951 else 4952 { 4953 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_ALIAS_WITH_CHAIN.get(alias, 4954 (i + 1), certificateChain.length)); 4955 } 4956 4957 printCertificate(certificateChain[i], "", verbose); 4958 4959 if (i == 0) 4960 { 4961 if (hasKeyAlias(keystore, alias)) 4962 { 4963 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_HAS_PK_YES.get()); 4964 } 4965 else 4966 { 4967 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_HAS_PK_NO.get()); 4968 } 4969 } 4970 4971 CertException signatureVerificationException = null; 4972 if (certificateChain[i].isSelfSigned()) 4973 { 4974 try 4975 { 4976 certificateChain[i].verifySignature(null); 4977 } 4978 catch (final CertException ce) 4979 { 4980 Debug.debugException(ce); 4981 signatureVerificationException = ce; 4982 } 4983 } 4984 else 4985 { 4986 X509Certificate issuerCertificate = null; 4987 try 4988 { 4989 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 4990 new AtomicReference<>(); 4991 final AtomicReference<DN> missingIssuerRef = 4992 new AtomicReference<>(); 4993 issuerCertificate = getIssuerCertificate(certificateChain[i], 4994 keystore, jvmDefaultTrustStoreRef, missingIssuerRef); 4995 } 4996 catch (final Exception e) 4997 { 4998 Debug.debugException(e); 4999 } 5000 5001 if (issuerCertificate == null) 5002 { 5003 signatureVerificationException = new CertException( 5004 ERR_MANAGE_CERTS_LIST_CERTS_VERIFY_SIGNATURE_NO_ISSUER.get( 5005 certificateChain[i].getIssuerDN())); 5006 } 5007 else 5008 { 5009 try 5010 { 5011 certificateChain[i].verifySignature(issuerCertificate); 5012 } 5013 catch (final CertException ce) 5014 { 5015 Debug.debugException(ce); 5016 signatureVerificationException = ce; 5017 } 5018 } 5019 } 5020 5021 if (signatureVerificationException == null) 5022 { 5023 wrapOut(0, WRAP_COLUMN, 5024 INFO_MANAGE_CERTS_LIST_CERTS_SIGNATURE_VALID.get()); 5025 } 5026 else 5027 { 5028 wrapErr(0, WRAP_COLUMN, 5029 signatureVerificationException.getMessage()); 5030 } 5031 5032 if (displayPEM) 5033 { 5034 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_PEM.get()); 5035 writePEMCertificate(getOut(), 5036 certificateChain[i].getX509CertificateBytes()); 5037 } 5038 } 5039 } 5040 5041 if (! missingAliases.isEmpty()) 5042 { 5043 err(); 5044 for (final String missingAlias : missingAliases.values()) 5045 { 5046 wrapErr(0, WRAP_COLUMN, 5047 WARN_MANAGE_CERTS_LIST_CERTS_ALIAS_NOT_IN_KS.get(missingAlias, 5048 keystorePath.getAbsolutePath())); 5049 resultCode = ResultCode.PARAM_ERROR; 5050 } 5051 } 5052 else if (listedCount == 0) 5053 { 5054 out(); 5055 if (keystorePassword == null) 5056 { 5057 wrapOut(0, WRAP_COLUMN, 5058 INFO_MANAGE_CERTS_LIST_CERTS_NO_CERTS_OR_KEYS_WITHOUT_PW.get()); 5059 } 5060 else 5061 { 5062 wrapOut(0, WRAP_COLUMN, 5063 INFO_MANAGE_CERTS_LIST_CERTS_NO_CERTS_OR_KEYS_WITH_PW.get()); 5064 } 5065 } 5066 5067 return resultCode; 5068 } 5069 5070 5071 5072 /** 5073 * Performs the necessary processing for the export-certificate subcommand. 5074 * 5075 * @return A result code that indicates whether the processing completed 5076 * successfully. 5077 */ 5078 @NotNull() 5079 private ResultCode doExportCertificate() 5080 { 5081 // Get the values of a number of configured arguments. 5082 final StringArgument aliasArgument = 5083 subCommandParser.getStringArgument("alias"); 5084 final String alias = aliasArgument.getValue(); 5085 5086 final BooleanArgument exportChainArgument = 5087 subCommandParser.getBooleanArgument("export-certificate-chain"); 5088 final boolean exportChain = 5089 ((exportChainArgument != null) && exportChainArgument.isPresent()); 5090 5091 final BooleanArgument separateFilePerCertificateArgument = 5092 subCommandParser.getBooleanArgument("separate-file-per-certificate"); 5093 final boolean separateFilePerCertificate = 5094 ((separateFilePerCertificateArgument != null) && 5095 separateFilePerCertificateArgument.isPresent()); 5096 5097 boolean exportPEM = true; 5098 final StringArgument outputFormatArgument = 5099 subCommandParser.getStringArgument("output-format"); 5100 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 5101 { 5102 final String format = outputFormatArgument.getValue().toLowerCase(); 5103 if (format.equals("der") || format.equals("binary") || 5104 format.equals("bin")) 5105 { 5106 exportPEM = false; 5107 } 5108 } 5109 5110 File outputFile = null; 5111 final FileArgument outputFileArgument = 5112 subCommandParser.getFileArgument("output-file"); 5113 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 5114 { 5115 outputFile = outputFileArgument.getValue(); 5116 } 5117 5118 if ((outputFile == null) && (! exportPEM)) 5119 { 5120 wrapErr(0, WRAP_COLUMN, 5121 ERR_MANAGE_CERTS_EXPORT_CERT_NO_FILE_WITH_DER.get()); 5122 return ResultCode.PARAM_ERROR; 5123 } 5124 5125 final String keystoreType; 5126 final File keystorePath = getKeystorePath(); 5127 try 5128 { 5129 keystoreType = inferKeystoreType(keystorePath); 5130 } 5131 catch (final LDAPException le) 5132 { 5133 Debug.debugException(le); 5134 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5135 return le.getResultCode(); 5136 } 5137 5138 final char[] keystorePassword; 5139 try 5140 { 5141 keystorePassword = getKeystorePassword(keystorePath); 5142 } 5143 catch (final LDAPException le) 5144 { 5145 Debug.debugException(le); 5146 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5147 return le.getResultCode(); 5148 } 5149 5150 final BooleanArgument displayKeytoolCommandArgument = 5151 subCommandParser.getBooleanArgument("display-keytool-command"); 5152 if ((displayKeytoolCommandArgument != null) && 5153 displayKeytoolCommandArgument.isPresent()) 5154 { 5155 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 5156 keytoolArgs.add("-list"); 5157 5158 keytoolArgs.add("-keystore"); 5159 keytoolArgs.add(keystorePath.getAbsolutePath()); 5160 keytoolArgs.add("-storetype"); 5161 keytoolArgs.add(keystoreType); 5162 5163 if (keystorePassword != null) 5164 { 5165 keytoolArgs.add("-storepass"); 5166 keytoolArgs.add("*****REDACTED*****"); 5167 } 5168 5169 keytoolArgs.add("-alias"); 5170 keytoolArgs.add(alias); 5171 5172 if (exportPEM) 5173 { 5174 keytoolArgs.add("-rfc"); 5175 } 5176 5177 if (outputFile != null) 5178 { 5179 keytoolArgs.add("-file"); 5180 keytoolArgs.add(outputFile.getAbsolutePath()); 5181 } 5182 5183 displayKeytoolCommand(keytoolArgs); 5184 } 5185 5186 5187 // Get the keystore. 5188 final KeyStore keystore; 5189 try 5190 { 5191 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5192 } 5193 catch (final LDAPException le) 5194 { 5195 Debug.debugException(le); 5196 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5197 return le.getResultCode(); 5198 } 5199 5200 5201 // Get the certificates to export. If the --export-certificate-chain 5202 // argument was provided, this can be multiple certificates. Otherwise, it 5203 // there will only be one. 5204 DN missingIssuerDN = null; 5205 final X509Certificate[] certificatesToExport; 5206 if (exportChain) 5207 { 5208 try 5209 { 5210 final AtomicReference<DN> missingIssuerRef = new AtomicReference<>(); 5211 certificatesToExport = 5212 getCertificateChain(alias, keystore, missingIssuerRef); 5213 missingIssuerDN = missingIssuerRef.get(); 5214 } 5215 catch (final LDAPException le) 5216 { 5217 Debug.debugException(le); 5218 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5219 return le.getResultCode(); 5220 } 5221 } 5222 else 5223 { 5224 try 5225 { 5226 final Certificate cert = keystore.getCertificate(alias); 5227 if (cert == null) 5228 { 5229 certificatesToExport = new X509Certificate[0]; 5230 } 5231 else 5232 { 5233 certificatesToExport = new X509Certificate[] 5234 { 5235 new X509Certificate(cert.getEncoded()) 5236 }; 5237 } 5238 } 5239 catch (final Exception e) 5240 { 5241 Debug.debugException(e); 5242 wrapErr(0, WRAP_COLUMN, 5243 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_GETTING_CERT.get(alias, 5244 keystorePath.getAbsolutePath())); 5245 e.printStackTrace(getErr()); 5246 return ResultCode.LOCAL_ERROR; 5247 } 5248 } 5249 5250 if (certificatesToExport.length == 0) 5251 { 5252 wrapErr(0, WRAP_COLUMN, 5253 ERR_MANAGE_CERTS_EXPORT_CERT_NO_CERT_WITH_ALIAS.get(alias, 5254 keystorePath.getAbsolutePath())); 5255 return ResultCode.PARAM_ERROR; 5256 } 5257 5258 5259 // Get a PrintStream to use for the output. 5260 int fileCounter = 1; 5261 String filename = null; 5262 PrintStream printStream; 5263 if (outputFile == null) 5264 { 5265 printStream = getOut(); 5266 } 5267 else 5268 { 5269 try 5270 { 5271 if ((certificatesToExport.length > 1) && separateFilePerCertificate) 5272 { 5273 filename = outputFile.getAbsolutePath() + '.' + fileCounter; 5274 } 5275 else 5276 { 5277 filename = outputFile.getAbsolutePath(); 5278 } 5279 printStream = new PrintStream(filename); 5280 } 5281 catch (final Exception e) 5282 { 5283 Debug.debugException(e); 5284 wrapErr(0, WRAP_COLUMN, 5285 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_OPENING_OUTPUT.get( 5286 outputFile.getAbsolutePath())); 5287 e.printStackTrace(getErr()); 5288 return ResultCode.LOCAL_ERROR; 5289 } 5290 } 5291 5292 try 5293 { 5294 for (final X509Certificate certificate : certificatesToExport) 5295 { 5296 try 5297 { 5298 if (separateFilePerCertificate && (certificatesToExport.length > 1)) 5299 { 5300 if (fileCounter > 1) 5301 { 5302 printStream.close(); 5303 filename = outputFile.getAbsolutePath() + '.' + fileCounter; 5304 printStream = new PrintStream(filename); 5305 } 5306 5307 fileCounter++; 5308 } 5309 5310 if (exportPEM) 5311 { 5312 writePEMCertificate(printStream, 5313 certificate.getX509CertificateBytes()); 5314 } 5315 else 5316 { 5317 printStream.write(certificate.getX509CertificateBytes()); 5318 } 5319 } 5320 catch (final Exception e) 5321 { 5322 Debug.debugException(e); 5323 wrapErr(0, WRAP_COLUMN, 5324 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_WRITING_CERT.get(alias, 5325 certificate.getSubjectDN())); 5326 e.printStackTrace(getErr()); 5327 return ResultCode.LOCAL_ERROR; 5328 } 5329 5330 if (outputFile != null) 5331 { 5332 out(); 5333 wrapOut(0, WRAP_COLUMN, 5334 INFO_MANAGE_CERTS_EXPORT_CERT_EXPORT_SUCCESSFUL.get(filename)); 5335 printCertificate(certificate, "", false); 5336 } 5337 } 5338 } 5339 finally 5340 { 5341 printStream.flush(); 5342 if (outputFile != null) 5343 { 5344 printStream.close(); 5345 } 5346 } 5347 5348 if (missingIssuerDN != null) 5349 { 5350 err(); 5351 wrapErr(0, WRAP_COLUMN, 5352 WARN_MANAGE_CERTS_EXPORT_CERT_MISSING_CERT_IN_CHAIN.get( 5353 missingIssuerDN, keystorePath.getAbsolutePath())); 5354 return ResultCode.NO_SUCH_OBJECT; 5355 } 5356 5357 return ResultCode.SUCCESS; 5358 } 5359 5360 5361 5362 /** 5363 * Performs the necessary processing for the export-private-key subcommand. 5364 * 5365 * @return A result code that indicates whether the processing completed 5366 * successfully. 5367 */ 5368 @NotNull() 5369 private ResultCode doExportPrivateKey() 5370 { 5371 // Get the values of a number of configured arguments. 5372 final StringArgument aliasArgument = 5373 subCommandParser.getStringArgument("alias"); 5374 final String alias = aliasArgument.getValue(); 5375 5376 boolean exportPEM = true; 5377 final StringArgument outputFormatArgument = 5378 subCommandParser.getStringArgument("output-format"); 5379 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 5380 { 5381 final String format = outputFormatArgument.getValue().toLowerCase(); 5382 if (format.equals("der") || format.equals("binary") || 5383 format.equals("bin")) 5384 { 5385 exportPEM = false; 5386 } 5387 } 5388 5389 File outputFile = null; 5390 final FileArgument outputFileArgument = 5391 subCommandParser.getFileArgument("output-file"); 5392 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 5393 { 5394 outputFile = outputFileArgument.getValue(); 5395 } 5396 5397 if ((outputFile == null) && (! exportPEM)) 5398 { 5399 wrapErr(0, WRAP_COLUMN, 5400 ERR_MANAGE_CERTS_EXPORT_KEY_NO_FILE_WITH_DER.get()); 5401 return ResultCode.PARAM_ERROR; 5402 } 5403 5404 final String keystoreType; 5405 final File keystorePath = getKeystorePath(); 5406 try 5407 { 5408 keystoreType = inferKeystoreType(keystorePath); 5409 } 5410 catch (final LDAPException le) 5411 { 5412 Debug.debugException(le); 5413 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5414 return le.getResultCode(); 5415 } 5416 5417 final char[] keystorePassword; 5418 try 5419 { 5420 keystorePassword = getKeystorePassword(keystorePath); 5421 } 5422 catch (final LDAPException le) 5423 { 5424 Debug.debugException(le); 5425 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5426 return le.getResultCode(); 5427 } 5428 5429 5430 // Get the keystore. 5431 final KeyStore keystore; 5432 try 5433 { 5434 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5435 } 5436 catch (final LDAPException le) 5437 { 5438 Debug.debugException(le); 5439 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5440 return le.getResultCode(); 5441 } 5442 5443 5444 // See if we need to use a private key password that is different from the 5445 // keystore password. 5446 final char[] privateKeyPassword; 5447 try 5448 { 5449 privateKeyPassword = 5450 getPrivateKeyPassword(keystore, alias, keystorePassword); 5451 } 5452 catch (final LDAPException le) 5453 { 5454 Debug.debugException(le); 5455 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5456 return le.getResultCode(); 5457 } 5458 5459 5460 // Get the password to use to encrypt the private key when it is exported. 5461 final char[] encryptionPassword; 5462 try 5463 { 5464 encryptionPassword = getPrivateKeyEncryptionPassword(false); 5465 } 5466 catch (final LDAPException le) 5467 { 5468 Debug.debugException(le); 5469 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5470 return le.getResultCode(); 5471 } 5472 5473 5474 // Get the private key to export. 5475 final PrivateKey privateKey; 5476 try 5477 { 5478 final Key key = keystore.getKey(alias, privateKeyPassword); 5479 if (key == null) 5480 { 5481 wrapErr(0, WRAP_COLUMN, 5482 ERR_MANAGE_CERTS_EXPORT_KEY_NO_KEY_WITH_ALIAS.get(alias, 5483 keystorePath.getAbsolutePath())); 5484 return ResultCode.PARAM_ERROR; 5485 } 5486 5487 privateKey = (PrivateKey) key; 5488 } 5489 catch (final UnrecoverableKeyException e) 5490 { 5491 Debug.debugException(e); 5492 wrapErr(0, WRAP_COLUMN, 5493 ERR_MANAGE_CERTS_EXPORT_KEY_WRONG_KEY_PW.get(alias, 5494 keystorePath.getAbsolutePath())); 5495 return ResultCode.PARAM_ERROR; 5496 } 5497 catch (final Exception e) 5498 { 5499 Debug.debugException(e); 5500 wrapErr(0, WRAP_COLUMN, 5501 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_GETTING_KEY.get(alias, 5502 keystorePath.getAbsolutePath())); 5503 e.printStackTrace(getErr()); 5504 return ResultCode.LOCAL_ERROR; 5505 } 5506 5507 5508 // Get a PrintStream to use for the output. 5509 final PrintStream printStream; 5510 if (outputFile == null) 5511 { 5512 printStream = getOut(); 5513 } 5514 else 5515 { 5516 try 5517 { 5518 printStream = new PrintStream(outputFile); 5519 } 5520 catch (final Exception e) 5521 { 5522 Debug.debugException(e); 5523 wrapErr(0, WRAP_COLUMN, 5524 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_OPENING_OUTPUT.get( 5525 outputFile.getAbsolutePath())); 5526 e.printStackTrace(getErr()); 5527 return ResultCode.LOCAL_ERROR; 5528 } 5529 } 5530 5531 try 5532 { 5533 try 5534 { 5535 if (exportPEM) 5536 { 5537 writePEMPrivateKey(printStream, privateKey.getEncoded(), 5538 encryptionPassword); 5539 } 5540 else 5541 { 5542 if (encryptionPassword == null) 5543 { 5544 printStream.write(privateKey.getEncoded()); 5545 } 5546 else 5547 { 5548 final byte[] encryptedPrivateKey = 5549 PKCS8EncryptionHandler.encryptPrivateKey( 5550 privateKey.getEncoded(), encryptionPassword, 5551 new PKCS8EncryptionProperties()); 5552 printStream.write(encryptedPrivateKey); 5553 } 5554 } 5555 } 5556 catch (final Exception e) 5557 { 5558 Debug.debugException(e); 5559 wrapErr(0, WRAP_COLUMN, 5560 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_WRITING_KEY.get(alias)); 5561 e.printStackTrace(getErr()); 5562 return ResultCode.LOCAL_ERROR; 5563 } 5564 5565 if (outputFile != null) 5566 { 5567 out(); 5568 wrapOut(0, WRAP_COLUMN, 5569 INFO_MANAGE_CERTS_EXPORT_KEY_EXPORT_SUCCESSFUL.get()); 5570 } 5571 } 5572 finally 5573 { 5574 printStream.flush(); 5575 if (outputFile != null) 5576 { 5577 printStream.close(); 5578 } 5579 } 5580 5581 return ResultCode.SUCCESS; 5582 } 5583 5584 5585 5586 /** 5587 * Performs the necessary processing for the import-certificate subcommand. 5588 * 5589 * @return A result code that indicates whether the processing completed 5590 * successfully. 5591 */ 5592 @NotNull() 5593 private ResultCode doImportCertificate() 5594 { 5595 // Get the values of a number of configured arguments. 5596 final StringArgument aliasArgument = 5597 subCommandParser.getStringArgument("alias"); 5598 final String alias = aliasArgument.getValue(); 5599 5600 final FileArgument certificateFileArgument = 5601 subCommandParser.getFileArgument("certificate-file"); 5602 final List<File> certFiles = certificateFileArgument.getValues(); 5603 5604 final File privateKeyFile; 5605 final FileArgument privateKeyFileArgument = 5606 subCommandParser.getFileArgument("private-key-file"); 5607 if ((privateKeyFileArgument != null) && privateKeyFileArgument.isPresent()) 5608 { 5609 privateKeyFile = privateKeyFileArgument.getValue(); 5610 } 5611 else 5612 { 5613 privateKeyFile = null; 5614 } 5615 5616 final BooleanArgument noPromptArgument = 5617 subCommandParser.getBooleanArgument("no-prompt"); 5618 final boolean noPrompt = 5619 ((noPromptArgument != null) && noPromptArgument.isPresent()); 5620 5621 final BooleanArgument skipValidationArgument = 5622 subCommandParser.getBooleanArgument("skip-validation"); 5623 final boolean skipValidation = ((skipValidationArgument != null) && 5624 skipValidationArgument.isPresent()); 5625 5626 final String keystoreType; 5627 final File keystorePath = getKeystorePath(); 5628 final boolean isNewKeystore = (! keystorePath.exists()); 5629 try 5630 { 5631 keystoreType = inferKeystoreType(keystorePath); 5632 } 5633 catch (final LDAPException le) 5634 { 5635 Debug.debugException(le); 5636 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5637 return le.getResultCode(); 5638 } 5639 5640 5641 final char[] keystorePassword; 5642 try 5643 { 5644 keystorePassword = getKeystorePassword(keystorePath); 5645 } 5646 catch (final LDAPException le) 5647 { 5648 Debug.debugException(le); 5649 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5650 return le.getResultCode(); 5651 } 5652 5653 5654 // Read the contents of the certificate files. 5655 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 5656 for (final File certFile : certFiles) 5657 { 5658 try 5659 { 5660 final List<X509Certificate> certs = readCertificatesFromFile(certFile); 5661 if (certs.isEmpty()) 5662 { 5663 wrapErr(0, WRAP_COLUMN, 5664 ERR_MANAGE_CERTS_IMPORT_CERT_NO_CERTS_IN_FILE.get( 5665 certFile.getAbsolutePath())); 5666 return ResultCode.PARAM_ERROR; 5667 } 5668 5669 certList.addAll(certs); 5670 } 5671 catch (final LDAPException le) 5672 { 5673 Debug.debugException(le); 5674 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5675 return le.getResultCode(); 5676 } 5677 } 5678 5679 5680 // See if there is a password to use to decrypt the private key that is 5681 // being imported. 5682 final char[] encryptionPassword; 5683 try 5684 { 5685 encryptionPassword = getPrivateKeyEncryptionPassword(true); 5686 } 5687 catch (final LDAPException le) 5688 { 5689 Debug.debugException(le); 5690 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5691 return le.getResultCode(); 5692 } 5693 5694 5695 // If a private key file was specified, then read the private key. 5696 final PKCS8PrivateKey privateKey; 5697 if (privateKeyFile == null) 5698 { 5699 privateKey = null; 5700 } 5701 else 5702 { 5703 try 5704 { 5705 privateKey = readPrivateKeyFromFile(privateKeyFile, encryptionPassword); 5706 } 5707 catch (final LDAPException le) 5708 { 5709 Debug.debugException(le); 5710 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5711 return le.getResultCode(); 5712 } 5713 } 5714 5715 5716 // Get the keystore. 5717 final KeyStore keystore; 5718 try 5719 { 5720 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5721 } 5722 catch (final LDAPException le) 5723 { 5724 Debug.debugException(le); 5725 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5726 return le.getResultCode(); 5727 } 5728 5729 5730 // If there is a private key, then see if we need to use a private key 5731 // password that is different from the keystore password. 5732 final char[] privateKeyPassword; 5733 try 5734 { 5735 privateKeyPassword = 5736 getPrivateKeyPassword(keystore, alias, keystorePassword); 5737 } 5738 catch (final LDAPException le) 5739 { 5740 Debug.debugException(le); 5741 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5742 return le.getResultCode(); 5743 } 5744 5745 5746 // If we should display an equivalent keytool command, then do that now. 5747 final BooleanArgument displayKeytoolCommandArgument = 5748 subCommandParser.getBooleanArgument("display-keytool-command"); 5749 if ((displayKeytoolCommandArgument != null) && 5750 displayKeytoolCommandArgument.isPresent()) 5751 { 5752 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 5753 keytoolArgs.add("-import"); 5754 5755 keytoolArgs.add("-keystore"); 5756 keytoolArgs.add(keystorePath.getAbsolutePath()); 5757 keytoolArgs.add("-storetype"); 5758 keytoolArgs.add(keystoreType); 5759 keytoolArgs.add("-storepass"); 5760 keytoolArgs.add("*****REDACTED*****"); 5761 keytoolArgs.add("-keypass"); 5762 keytoolArgs.add("*****REDACTED*****"); 5763 keytoolArgs.add("-alias"); 5764 keytoolArgs.add(alias); 5765 keytoolArgs.add("-file"); 5766 keytoolArgs.add(certFiles.get(0).getAbsolutePath()); 5767 keytoolArgs.add("-trustcacerts"); 5768 5769 displayKeytoolCommand(keytoolArgs); 5770 } 5771 5772 5773 if (! skipValidation) 5774 { 5775 // Look at all the certificates to be imported. Make sure that every 5776 // subsequent certificate in the chain is the issuer for the previous. 5777 final Iterator<X509Certificate> certIterator = certList.iterator(); 5778 X509Certificate subjectCert = certIterator.next(); 5779 while (true) 5780 { 5781 if (subjectCert.isSelfSigned()) 5782 { 5783 if (certIterator.hasNext()) 5784 { 5785 wrapErr(0, WRAP_COLUMN, 5786 ERR_MANAGE_CERTS_IMPORT_CERT_SELF_SIGNED_NOT_LAST.get( 5787 subjectCert.getSubjectDN())); 5788 return ResultCode.PARAM_ERROR; 5789 } 5790 } 5791 5792 if (! certIterator.hasNext()) 5793 { 5794 break; 5795 } 5796 5797 final X509Certificate issuerCert = certIterator.next(); 5798 final StringBuilder notIssuerReason = new StringBuilder(); 5799 if (! issuerCert.isIssuerFor(subjectCert, notIssuerReason)) 5800 { 5801 // In some cases, the process of signing a certificate can put two 5802 // certificates in the output file (both the signed certificate and 5803 // its issuer. If the same certificate is in the chain twice, then 5804 // we'll silently ignore it. 5805 if (Arrays.equals(issuerCert.getX509CertificateBytes(), 5806 subjectCert.getX509CertificateBytes())) 5807 { 5808 certIterator.remove(); 5809 } 5810 else 5811 { 5812 wrapErr(0, WRAP_COLUMN, 5813 ERR_MANAGE_CERTS_IMPORT_CERT_NEXT_NOT_ISSUER_OF_PREV.get( 5814 notIssuerReason.toString())); 5815 return ResultCode.PARAM_ERROR; 5816 } 5817 } 5818 5819 subjectCert = issuerCert; 5820 } 5821 } 5822 5823 5824 // If the last certificate in the chain is not self-signed, then make sure 5825 // that we can complete the chain using other certificates in the keystore 5826 // or in the JVM's set of default trusted issuers. If we can't complete 5827 // the chain, then that's an error, although we'll go ahead and proceed 5828 // anyway with the import if we're not also importing a private key. 5829 final ArrayList<X509Certificate> chain; 5830 if (certList.get(certList.size() - 1).isSelfSigned()) 5831 { 5832 chain = certList; 5833 } 5834 else 5835 { 5836 chain = new ArrayList<>(certList.size() + 5); 5837 chain.addAll(certList); 5838 5839 if (! skipValidation) 5840 { 5841 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 5842 new AtomicReference<>(); 5843 final AtomicReference<DN> missingIssuerRef = new AtomicReference<>(); 5844 5845 X509Certificate c = certList.get(certList.size() - 1); 5846 while (! c.isSelfSigned()) 5847 { 5848 final X509Certificate issuer; 5849 try 5850 { 5851 issuer = getIssuerCertificate(c, keystore, jvmDefaultTrustStoreRef, 5852 missingIssuerRef); 5853 } 5854 catch (final Exception e) 5855 { 5856 Debug.debugException(e); 5857 wrapErr(0, WRAP_COLUMN, 5858 ERR_MANAGE_CERTS_IMPORT_CERT_CANNOT_GET_ISSUER.get( 5859 c.getIssuerDN())); 5860 e.printStackTrace(getErr()); 5861 return ResultCode.LOCAL_ERROR; 5862 } 5863 5864 if (issuer == null) 5865 { 5866 final byte[] authorityKeyIdentifier = getAuthorityKeyIdentifier(c); 5867 5868 // We couldn't find the issuer certificate. If we're importing a 5869 // private key, or if the keystore already has a key entry with the 5870 // same alias that we're going to use, then this is definitely an 5871 // error because we can only write a key entry if we have a complete 5872 // certificate chain. 5873 // 5874 // If we weren't explicitly provided with a private key, then it's 5875 // still an undesirable thing to import a certificate without having 5876 // the complete set of issuers, but we'll go ahead and let it slide 5877 // with just a warning. 5878 if ((privateKey != null) || hasKeyAlias(keystore, alias)) 5879 { 5880 if (authorityKeyIdentifier == null) 5881 { 5882 err(); 5883 wrapErr(0, WRAP_COLUMN, 5884 ERR_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_NO_AKI.get( 5885 c.getIssuerDN())); 5886 } 5887 else 5888 { 5889 err(); 5890 wrapErr(0, WRAP_COLUMN, 5891 ERR_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_WITH_AKI.get( 5892 c.getIssuerDN(), 5893 toColonDelimitedHex(authorityKeyIdentifier))); 5894 } 5895 5896 return ResultCode.PARAM_ERROR; 5897 } 5898 else 5899 { 5900 if (authorityKeyIdentifier == null) 5901 { 5902 err(); 5903 wrapErr(0, WRAP_COLUMN, 5904 WARN_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_NO_AKI.get( 5905 c.getIssuerDN())); 5906 } 5907 else 5908 { 5909 err(); 5910 wrapErr(0, WRAP_COLUMN, 5911 WARN_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_WITH_AKI.get( 5912 c.getIssuerDN(), 5913 toColonDelimitedHex(authorityKeyIdentifier))); 5914 } 5915 5916 break; 5917 } 5918 } 5919 else 5920 { 5921 chain.add(issuer); 5922 c = issuer; 5923 } 5924 } 5925 } 5926 } 5927 5928 5929 // If we're going to import a private key with a certificate chain, then 5930 // perform the necessary validation and do the import. 5931 if (privateKey != null) 5932 { 5933 if (! skipValidation) 5934 { 5935 // Make sure that the keystore doesn't already have a key or certificate 5936 // with the specified alias. 5937 if (hasKeyAlias(keystore, alias)) 5938 { 5939 wrapErr(0, WRAP_COLUMN, 5940 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_PK_KEY_ALIAS_CONFLICT.get( 5941 alias)); 5942 return ResultCode.PARAM_ERROR; 5943 } 5944 else if (hasCertificateAlias(keystore, alias)) 5945 { 5946 wrapErr(0, WRAP_COLUMN, 5947 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_PK_CERT_ALIAS_CONFLICT.get( 5948 alias)); 5949 return ResultCode.PARAM_ERROR; 5950 } 5951 } 5952 5953 5954 // Make sure that the private key has a key algorithm of either RSA or EC, 5955 // and convert it into a Java PrivateKey object. 5956 final PrivateKey javaPrivateKey; 5957 try 5958 { 5959 javaPrivateKey = privateKey.toPrivateKey(); 5960 } 5961 catch (final Exception e) 5962 { 5963 Debug.debugException(e); 5964 wrapErr(0, WRAP_COLUMN, 5965 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_KEY.get( 5966 privateKeyFile.getAbsolutePath())); 5967 e.printStackTrace(getErr()); 5968 return ResultCode.LOCAL_ERROR; 5969 } 5970 5971 5972 // Convert the certificate chain into a Java Certificate[]. 5973 final Certificate[] javaCertificateChain = new Certificate[chain.size()]; 5974 for (int i=0; i < javaCertificateChain.length; i++) 5975 { 5976 final X509Certificate c = chain.get(i); 5977 try 5978 { 5979 javaCertificateChain[i] = c.toCertificate(); 5980 } 5981 catch (final Exception e) 5982 { 5983 Debug.debugException(e); 5984 wrapErr(0, WRAP_COLUMN, 5985 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 5986 c.getSubjectDN())); 5987 e.printStackTrace(getErr()); 5988 return ResultCode.LOCAL_ERROR; 5989 } 5990 } 5991 5992 5993 // Prompt the user to confirm the import, if appropriate. 5994 if (! noPrompt) 5995 { 5996 out(); 5997 wrapOut(0, WRAP_COLUMN, 5998 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_NEW_KEY.get( 5999 alias)); 6000 6001 for (final X509Certificate c : chain) 6002 { 6003 out(); 6004 printCertificate(c, "", false); 6005 } 6006 6007 out(); 6008 6009 try 6010 { 6011 if (! promptForYesNo( 6012 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 6013 { 6014 wrapErr(0, WRAP_COLUMN, 6015 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 6016 return ResultCode.USER_CANCELED; 6017 } 6018 } 6019 catch (final LDAPException le) 6020 { 6021 Debug.debugException(le); 6022 err(); 6023 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6024 return le.getResultCode(); 6025 } 6026 } 6027 6028 6029 // Set the private key entry in the keystore. 6030 try 6031 { 6032 keystore.setKeyEntry(alias, javaPrivateKey, privateKeyPassword, 6033 javaCertificateChain); 6034 } 6035 catch (final Exception e) 6036 { 6037 Debug.debugException(e); 6038 wrapErr(0, WRAP_COLUMN, 6039 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CHAIN.get( 6040 alias)); 6041 e.printStackTrace(getErr()); 6042 return ResultCode.LOCAL_ERROR; 6043 } 6044 6045 6046 // Write the updated keystore to disk. 6047 try 6048 { 6049 writeKeystore(keystore, keystorePath, keystorePassword); 6050 } 6051 catch (final LDAPException le) 6052 { 6053 Debug.debugException(le); 6054 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6055 return le.getResultCode(); 6056 } 6057 6058 if (isNewKeystore) 6059 { 6060 out(); 6061 wrapOut(0, WRAP_COLUMN, 6062 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6063 getUserFriendlyKeystoreType(keystoreType))); 6064 } 6065 6066 out(); 6067 wrapOut(0, WRAP_COLUMN, 6068 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITH_PK.get()); 6069 return ResultCode.SUCCESS; 6070 } 6071 6072 6073 // If we've gotten here, then we were given one or more certificates but no 6074 // private key. See if the keystore already has a certificate entry with 6075 // the specified alias. If so, then that's always an error. 6076 if (hasCertificateAlias(keystore, alias)) 6077 { 6078 wrapErr(0, WRAP_COLUMN, 6079 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_CONFLICTING_CERT_ALIAS.get(alias)); 6080 return ResultCode.PARAM_ERROR; 6081 } 6082 6083 6084 // See if the keystore already has a key entry with the specified alias. 6085 // If so, then it may or may not be an error. This can happen if we 6086 // generated a certificate signing request from an existing key pair, and 6087 // now want to import the signed certificate. If that is the case, then we 6088 // will replace the existing key entry with a new one that contains the full 6089 // new certificate chain and the existing private key, but only if the 6090 // new certificate uses the same public key as the certificate at the head 6091 // of the existing chain in that alias. 6092 if (hasKeyAlias(keystore, alias)) 6093 { 6094 // Make sure that the existing key pair uses the same public key as the 6095 // new certificate we are importing. 6096 final PrivateKey existingPrivateKey; 6097 final Certificate[] existingChain; 6098 final X509Certificate existingEndCertificate; 6099 try 6100 { 6101 existingPrivateKey = 6102 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 6103 existingChain = keystore.getCertificateChain(alias); 6104 existingEndCertificate = 6105 new X509Certificate(existingChain[0].getEncoded()); 6106 } 6107 catch (final Exception e) 6108 { 6109 Debug.debugException(e); 6110 wrapErr(0, WRAP_COLUMN, 6111 ERR_MANAGE_CERTS_IMPORT_CERT_INTO_KEY_ALIAS_CANNOT_GET_KEY.get( 6112 alias)); 6113 e.printStackTrace(getErr()); 6114 return ResultCode.LOCAL_ERROR; 6115 } 6116 6117 final boolean[] existingPublicKeyBits = 6118 existingEndCertificate.getEncodedPublicKey().getBits(); 6119 final boolean[] newPublicKeyBits = 6120 chain.get(0).getEncodedPublicKey().getBits(); 6121 if (! Arrays.equals(existingPublicKeyBits, newPublicKeyBits)) 6122 { 6123 wrapErr(0, WRAP_COLUMN, 6124 ERR_MANAGE_CERTS_IMPORT_CERT_INTO_KEY_ALIAS_KEY_MISMATCH.get( 6125 alias)); 6126 return ResultCode.PARAM_ERROR; 6127 } 6128 6129 6130 // Prepare the new certificate chain to store in the alias. 6131 final Certificate[] newChain = new Certificate[chain.size()]; 6132 for (int i=0; i < chain.size(); i++) 6133 { 6134 final X509Certificate c = chain.get(i); 6135 try 6136 { 6137 newChain[i] = c.toCertificate(); 6138 } 6139 catch (final Exception e) 6140 { 6141 Debug.debugException(e); 6142 wrapErr(0, WRAP_COLUMN, 6143 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 6144 c.getSubjectDN())); 6145 e.printStackTrace(getErr()); 6146 return ResultCode.LOCAL_ERROR; 6147 } 6148 } 6149 6150 6151 // Prompt the user to confirm the import, if appropriate. 6152 if (! noPrompt) 6153 { 6154 out(); 6155 wrapOut(0, WRAP_COLUMN, 6156 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_EXISTING_KEY. 6157 get(alias)); 6158 6159 for (final X509Certificate c : chain) 6160 { 6161 out(); 6162 printCertificate(c, "", false); 6163 } 6164 6165 out(); 6166 6167 try 6168 { 6169 if (! promptForYesNo( 6170 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 6171 { 6172 wrapErr(0, WRAP_COLUMN, 6173 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 6174 return ResultCode.USER_CANCELED; 6175 } 6176 } 6177 catch (final LDAPException le) 6178 { 6179 Debug.debugException(le); 6180 err(); 6181 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6182 return le.getResultCode(); 6183 } 6184 } 6185 6186 6187 // Set the private key entry in the keystore. 6188 try 6189 { 6190 keystore.setKeyEntry(alias, existingPrivateKey, privateKeyPassword, 6191 newChain); 6192 } 6193 catch (final Exception e) 6194 { 6195 Debug.debugException(e); 6196 wrapErr(0, WRAP_COLUMN, 6197 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CHAIN.get( 6198 alias)); 6199 e.printStackTrace(getErr()); 6200 return ResultCode.LOCAL_ERROR; 6201 } 6202 6203 6204 // Write the updated keystore to disk. 6205 try 6206 { 6207 writeKeystore(keystore, keystorePath, keystorePassword); 6208 } 6209 catch (final LDAPException le) 6210 { 6211 Debug.debugException(le); 6212 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6213 return le.getResultCode(); 6214 } 6215 6216 out(); 6217 6218 if (isNewKeystore) 6219 { 6220 wrapOut(0, WRAP_COLUMN, 6221 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6222 getUserFriendlyKeystoreType(keystoreType))); 6223 } 6224 6225 wrapOut(0, WRAP_COLUMN, 6226 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITHOUT_PK.get()); 6227 return ResultCode.SUCCESS; 6228 } 6229 6230 6231 // If we've gotten here, then we know that we're just going to add 6232 // certificate entries to the keystore. Iterate through the certificates 6233 // and add them to the keystore under the appropriate aliases, first making 6234 // sure that the alias isn't already in use. 6235 final LinkedHashMap<String,X509Certificate> certMap = 6236 new LinkedHashMap<>(StaticUtils.computeMapCapacity(certList.size())); 6237 for (int i=0; i < certList.size(); i++) 6238 { 6239 final X509Certificate x509Certificate = certList.get(i); 6240 final Certificate javaCertificate; 6241 try 6242 { 6243 javaCertificate = x509Certificate.toCertificate(); 6244 } 6245 catch (final Exception e) 6246 { 6247 Debug.debugException(e); 6248 wrapErr(0, WRAP_COLUMN, 6249 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 6250 x509Certificate.getSubjectDN())); 6251 e.printStackTrace(getErr()); 6252 return ResultCode.LOCAL_ERROR; 6253 } 6254 6255 final String certAlias; 6256 if (i == 0) 6257 { 6258 certAlias = alias; 6259 } 6260 else if (certList.size() > 2) 6261 { 6262 certAlias = alias + "-issuer-" + i; 6263 } 6264 else 6265 { 6266 certAlias = alias + "-issuer"; 6267 } 6268 6269 certMap.put(certAlias, x509Certificate); 6270 6271 if (hasKeyAlias(keystore, certAlias) || 6272 hasCertificateAlias(keystore, certAlias)) 6273 { 6274 wrapErr(0, WRAP_COLUMN, 6275 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_CONFLICTING_ISSUER_ALIAS.get( 6276 x509Certificate.getSubjectDN(), certAlias)); 6277 return ResultCode.PARAM_ERROR; 6278 } 6279 6280 try 6281 { 6282 keystore.setCertificateEntry(certAlias, javaCertificate); 6283 } 6284 catch (final Exception e) 6285 { 6286 Debug.debugException(e); 6287 wrapErr(0, WRAP_COLUMN, 6288 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CERT.get( 6289 x509Certificate.getSubjectDN(), alias)); 6290 e.printStackTrace(getErr()); 6291 return ResultCode.LOCAL_ERROR; 6292 } 6293 } 6294 6295 6296 // Prompt about whether to perform the import, if appropriate. 6297 if (! noPrompt) 6298 { 6299 out(); 6300 wrapOut(0, WRAP_COLUMN, 6301 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_NO_KEY. 6302 get(alias)); 6303 6304 for (final Map.Entry<String,X509Certificate> e : certMap.entrySet()) 6305 { 6306 out(); 6307 wrapOut(0, WRAP_COLUMN, 6308 INFO_MANAGE_CERTS_IMPORT_CERT_LABEL_ALIAS.get(e.getKey())); 6309 printCertificate(e.getValue(), "", false); 6310 } 6311 6312 out(); 6313 6314 try 6315 { 6316 if (! promptForYesNo( 6317 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 6318 { 6319 wrapErr(0, WRAP_COLUMN, 6320 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 6321 return ResultCode.USER_CANCELED; 6322 } 6323 } 6324 catch (final LDAPException le) 6325 { 6326 Debug.debugException(le); 6327 err(); 6328 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6329 return le.getResultCode(); 6330 } 6331 } 6332 6333 6334 // Write the updated keystore to disk. 6335 try 6336 { 6337 writeKeystore(keystore, keystorePath, keystorePassword); 6338 } 6339 catch (final LDAPException le) 6340 { 6341 Debug.debugException(le); 6342 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6343 return le.getResultCode(); 6344 } 6345 6346 out(); 6347 6348 if (isNewKeystore) 6349 { 6350 wrapOut(0, WRAP_COLUMN, 6351 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6352 getUserFriendlyKeystoreType(keystoreType))); 6353 } 6354 6355 wrapOut(0, WRAP_COLUMN, 6356 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITHOUT_PK.get()); 6357 return ResultCode.SUCCESS; 6358 } 6359 6360 6361 6362 /** 6363 * Performs the necessary processing for the delete-certificate subcommand. 6364 * 6365 * @return A result code that indicates whether the processing completed 6366 * successfully. 6367 */ 6368 @NotNull() 6369 private ResultCode doDeleteCertificate() 6370 { 6371 // Get the values of a number of configured arguments. 6372 final StringArgument aliasArgument = 6373 subCommandParser.getStringArgument("alias"); 6374 final String alias = aliasArgument.getValue(); 6375 6376 final BooleanArgument noPromptArgument = 6377 subCommandParser.getBooleanArgument("no-prompt"); 6378 final boolean noPrompt = 6379 ((noPromptArgument != null) && noPromptArgument.isPresent()); 6380 6381 final String keystoreType; 6382 final File keystorePath = getKeystorePath(); 6383 try 6384 { 6385 keystoreType = inferKeystoreType(keystorePath); 6386 } 6387 catch (final LDAPException le) 6388 { 6389 Debug.debugException(le); 6390 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6391 return le.getResultCode(); 6392 } 6393 6394 final char[] keystorePassword; 6395 try 6396 { 6397 keystorePassword = getKeystorePassword(keystorePath); 6398 } 6399 catch (final LDAPException le) 6400 { 6401 Debug.debugException(le); 6402 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6403 return le.getResultCode(); 6404 } 6405 6406 final BooleanArgument displayKeytoolCommandArgument = 6407 subCommandParser.getBooleanArgument("display-keytool-command"); 6408 if ((displayKeytoolCommandArgument != null) && 6409 displayKeytoolCommandArgument.isPresent()) 6410 { 6411 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 6412 keytoolArgs.add("-delete"); 6413 6414 keytoolArgs.add("-keystore"); 6415 keytoolArgs.add(keystorePath.getAbsolutePath()); 6416 keytoolArgs.add("-storetype"); 6417 keytoolArgs.add(keystoreType); 6418 keytoolArgs.add("-storepass"); 6419 keytoolArgs.add("*****REDACTED*****"); 6420 keytoolArgs.add("-alias"); 6421 keytoolArgs.add(alias); 6422 6423 displayKeytoolCommand(keytoolArgs); 6424 } 6425 6426 6427 // Get the keystore. 6428 final KeyStore keystore; 6429 try 6430 { 6431 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 6432 } 6433 catch (final LDAPException le) 6434 { 6435 Debug.debugException(le); 6436 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6437 return le.getResultCode(); 6438 } 6439 6440 6441 // Get the entry for the specified alias. 6442 final boolean hasPrivateKey; 6443 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 6444 if (hasCertificateAlias(keystore, alias)) 6445 { 6446 try 6447 { 6448 hasPrivateKey = false; 6449 certList.add( 6450 new X509Certificate(keystore.getCertificate(alias).getEncoded())); 6451 } 6452 catch (final Exception e) 6453 { 6454 Debug.debugException(e); 6455 wrapErr(0, WRAP_COLUMN, 6456 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_GETTING_CERT.get(alias)); 6457 e.printStackTrace(getErr()); 6458 return ResultCode.LOCAL_ERROR; 6459 } 6460 } 6461 else if (hasKeyAlias(keystore, alias)) 6462 { 6463 try 6464 { 6465 hasPrivateKey = true; 6466 for (final Certificate c : keystore.getCertificateChain(alias)) 6467 { 6468 certList.add(new X509Certificate(c.getEncoded())); 6469 } 6470 } 6471 catch (final Exception e) 6472 { 6473 Debug.debugException(e); 6474 wrapErr(0, WRAP_COLUMN, 6475 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_GETTING_CHAIN.get(alias)); 6476 e.printStackTrace(getErr()); 6477 return ResultCode.LOCAL_ERROR; 6478 } 6479 } 6480 else 6481 { 6482 wrapErr(0, WRAP_COLUMN, 6483 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_ALIAS_NOT_CERT_OR_KEY.get(alias)); 6484 return ResultCode.PARAM_ERROR; 6485 } 6486 6487 6488 // Prompt about whether to perform the delete, if appropriate. 6489 if (! noPrompt) 6490 { 6491 out(); 6492 if (! hasPrivateKey) 6493 { 6494 wrapOut(0, WRAP_COLUMN, 6495 INFO_MANAGE_CERTS_DELETE_CERT_CONFIRM_DELETE_CERT.get()); 6496 } 6497 else 6498 { 6499 wrapOut(0, WRAP_COLUMN, 6500 INFO_MANAGE_CERTS_DELETE_CERT_CONFIRM_DELETE_CHAIN.get()); 6501 } 6502 6503 for (final X509Certificate c : certList) 6504 { 6505 out(); 6506 printCertificate(c, "", false); 6507 } 6508 6509 out(); 6510 6511 try 6512 { 6513 if (! promptForYesNo( 6514 INFO_MANAGE_CERTS_DELETE_CERT_PROMPT_DELETE.get())) 6515 { 6516 wrapErr(0, WRAP_COLUMN, 6517 ERR_MANAGE_CERTS_DELETE_CERT_CANCELED.get()); 6518 return ResultCode.USER_CANCELED; 6519 } 6520 } 6521 catch (final LDAPException le) 6522 { 6523 Debug.debugException(le); 6524 err(); 6525 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6526 return le.getResultCode(); 6527 } 6528 } 6529 6530 6531 // Delete the entry from the keystore. 6532 try 6533 { 6534 keystore.deleteEntry(alias); 6535 } 6536 catch (final Exception e) 6537 { 6538 Debug.debugException(e); 6539 wrapErr(0, WRAP_COLUMN, 6540 ERR_MANAGE_CERTS_DELETE_CERT_DELETE_ERROR.get(alias)); 6541 e.printStackTrace(getErr()); 6542 return ResultCode.LOCAL_ERROR; 6543 } 6544 6545 6546 // Write the updated keystore to disk. 6547 try 6548 { 6549 writeKeystore(keystore, keystorePath, keystorePassword); 6550 } 6551 catch (final LDAPException le) 6552 { 6553 Debug.debugException(le); 6554 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6555 return le.getResultCode(); 6556 } 6557 6558 if (certList.size() == 1) 6559 { 6560 out(); 6561 wrapOut(0, WRAP_COLUMN, 6562 INFO_MANAGE_CERTS_DELETE_CERT_DELETED_CERT.get()); 6563 } 6564 else 6565 { 6566 out(); 6567 wrapOut(0, WRAP_COLUMN, 6568 INFO_MANAGE_CERTS_DELETE_CERT_DELETED_CHAIN.get()); 6569 } 6570 6571 return ResultCode.SUCCESS; 6572 } 6573 6574 6575 6576 /** 6577 * Performs the necessary processing for the generate-self-signed-certificate, 6578 * generate-certificate-signing-request, and sign-certificate-signing-request 6579 * subcommands. 6580 * 6581 * @return A result code that indicates whether the processing completed 6582 * successfully. 6583 */ 6584 @NotNull() 6585 private ResultCode doGenerateOrSignCertificateOrCSR() 6586 { 6587 // Figure out which subcommand we're processing. 6588 final boolean isGenerateCertificate; 6589 final boolean isGenerateCSR; 6590 final boolean isSignCSR; 6591 final SubCommand selectedSubCommand = globalParser.getSelectedSubCommand(); 6592 if (selectedSubCommand.hasName("generate-self-signed-certificate")) 6593 { 6594 isGenerateCertificate = true; 6595 isGenerateCSR = false; 6596 isSignCSR = false; 6597 } 6598 else if (selectedSubCommand.hasName("generate-certificate-signing-request")) 6599 { 6600 isGenerateCertificate = false; 6601 isGenerateCSR = true; 6602 isSignCSR = false; 6603 } 6604 else 6605 { 6606 Validator.ensureTrue( 6607 selectedSubCommand.hasName("sign-certificate-signing-request")); 6608 isGenerateCertificate = false; 6609 isGenerateCSR = false; 6610 isSignCSR = true; 6611 } 6612 6613 6614 // Get the values of a number of configured arguments. 6615 final StringArgument aliasArgument = 6616 subCommandParser.getStringArgument("alias"); 6617 final String alias = aliasArgument.getValue(); 6618 6619 final File keystorePath = getKeystorePath(); 6620 final boolean isNewKeystore = (! keystorePath.exists()); 6621 6622 DN subjectDN = null; 6623 final DNArgument subjectDNArgument = 6624 subCommandParser.getDNArgument("subject-dn"); 6625 if ((subjectDNArgument != null) && subjectDNArgument.isPresent()) 6626 { 6627 subjectDN = subjectDNArgument.getValue(); 6628 } 6629 6630 File inputFile = null; 6631 final FileArgument inputFileArgument = 6632 subCommandParser.getFileArgument("input-file"); 6633 if ((inputFileArgument != null) && inputFileArgument.isPresent()) 6634 { 6635 inputFile = inputFileArgument.getValue(); 6636 } 6637 6638 File outputFile = null; 6639 final FileArgument outputFileArgument = 6640 subCommandParser.getFileArgument("output-file"); 6641 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 6642 { 6643 outputFile = outputFileArgument.getValue(); 6644 } 6645 6646 boolean outputPEM = true; 6647 final StringArgument outputFormatArgument = 6648 subCommandParser.getStringArgument("output-format"); 6649 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 6650 { 6651 final String format = outputFormatArgument.getValue().toLowerCase(); 6652 if (format.equals("der") || format.equals("binary") || 6653 format.equals("bin")) 6654 { 6655 outputPEM = false; 6656 } 6657 } 6658 6659 if ((! outputPEM) && (outputFile == null)) 6660 { 6661 wrapErr(0, WRAP_COLUMN, 6662 ERR_MANAGE_CERTS_GEN_CERT_NO_FILE_WITH_DER.get()); 6663 return ResultCode.PARAM_ERROR; 6664 } 6665 6666 final BooleanArgument useExistingKeyPairArgument = 6667 subCommandParser.getBooleanArgument("use-existing-key-pair"); 6668 final boolean useExistingKeyPair = 6669 ((useExistingKeyPairArgument != null) && 6670 useExistingKeyPairArgument.isPresent()); 6671 if (useExistingKeyPair && (! keystorePath.exists())) 6672 { 6673 wrapErr(0, WRAP_COLUMN, 6674 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_WITHOUT_KS.get()); 6675 return ResultCode.PARAM_ERROR; 6676 } 6677 6678 final BooleanArgument inheritExtensionsArgument = 6679 subCommandParser.getBooleanArgument("inherit-extensions"); 6680 final boolean inheritExtensions = 6681 ((inheritExtensionsArgument != null) && 6682 inheritExtensionsArgument.isPresent()); 6683 6684 final BooleanArgument includeRequestedExtensionsArgument = 6685 subCommandParser.getBooleanArgument("include-requested-extensions"); 6686 final boolean includeRequestedExtensions = 6687 ((includeRequestedExtensionsArgument != null) && 6688 includeRequestedExtensionsArgument.isPresent()); 6689 6690 final BooleanArgument noPromptArgument = 6691 subCommandParser.getBooleanArgument("no-prompt"); 6692 final boolean noPrompt = 6693 ((noPromptArgument != null) && noPromptArgument.isPresent()); 6694 6695 final BooleanArgument displayKeytoolCommandArgument = 6696 subCommandParser.getBooleanArgument("display-keytool-command"); 6697 final boolean displayKeytoolCommand = 6698 ((displayKeytoolCommandArgument != null) && 6699 displayKeytoolCommandArgument.isPresent()); 6700 6701 int daysValid = 365; 6702 final IntegerArgument daysValidArgument = 6703 subCommandParser.getIntegerArgument("days-valid"); 6704 if ((daysValidArgument != null) && daysValidArgument.isPresent()) 6705 { 6706 daysValid = daysValidArgument.getValue(); 6707 } 6708 6709 Date validityStartTime = null; 6710 final TimestampArgument validityStartTimeArgument = 6711 subCommandParser.getTimestampArgument("validity-start-time"); 6712 if ((validityStartTimeArgument != null) && 6713 validityStartTimeArgument.isPresent()) 6714 { 6715 validityStartTime = validityStartTimeArgument.getValue(); 6716 } 6717 6718 PublicKeyAlgorithmIdentifier keyAlgorithmIdentifier = null; 6719 String keyAlgorithmName = null; 6720 final StringArgument keyAlgorithmArgument = 6721 subCommandParser.getStringArgument("key-algorithm"); 6722 if ((keyAlgorithmArgument != null) && keyAlgorithmArgument.isPresent()) 6723 { 6724 final String name = keyAlgorithmArgument.getValue(); 6725 keyAlgorithmIdentifier = PublicKeyAlgorithmIdentifier.forName(name); 6726 if (keyAlgorithmIdentifier == null) 6727 { 6728 wrapErr(0, WRAP_COLUMN, 6729 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_KEY_ALG.get(name)); 6730 return ResultCode.PARAM_ERROR; 6731 } 6732 else 6733 { 6734 keyAlgorithmName = keyAlgorithmIdentifier.getName(); 6735 } 6736 } 6737 6738 Integer keySizeBits = null; 6739 final IntegerArgument keySizeBitsArgument = 6740 subCommandParser.getIntegerArgument("key-size-bits"); 6741 if ((keySizeBitsArgument != null) && keySizeBitsArgument.isPresent()) 6742 { 6743 keySizeBits = keySizeBitsArgument.getValue(); 6744 } 6745 6746 if ((keyAlgorithmIdentifier != null) && 6747 (keyAlgorithmIdentifier != PublicKeyAlgorithmIdentifier.RSA) && 6748 (keySizeBits == null)) 6749 { 6750 wrapErr(0, WRAP_COLUMN, 6751 ERR_MANAGE_CERTS_GEN_CERT_NO_KEY_SIZE_FOR_NON_RSA_KEY.get()); 6752 return ResultCode.PARAM_ERROR; 6753 } 6754 6755 String signatureAlgorithmName = null; 6756 SignatureAlgorithmIdentifier signatureAlgorithmIdentifier = null; 6757 final StringArgument signatureAlgorithmArgument = 6758 subCommandParser.getStringArgument("signature-algorithm"); 6759 if ((signatureAlgorithmArgument != null) && 6760 signatureAlgorithmArgument.isPresent()) 6761 { 6762 final String name = signatureAlgorithmArgument.getValue(); 6763 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forName(name); 6764 if (signatureAlgorithmIdentifier == null) 6765 { 6766 wrapErr(0, WRAP_COLUMN, 6767 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG.get(name)); 6768 return ResultCode.PARAM_ERROR; 6769 } 6770 else 6771 { 6772 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 6773 } 6774 } 6775 6776 if ((keyAlgorithmIdentifier != null) && 6777 (keyAlgorithmIdentifier != PublicKeyAlgorithmIdentifier.RSA) && 6778 (signatureAlgorithmIdentifier == null)) 6779 { 6780 wrapErr(0, WRAP_COLUMN, 6781 ERR_MANAGE_CERTS_GEN_CERT_NO_SIG_ALG_FOR_NON_RSA_KEY.get()); 6782 return ResultCode.PARAM_ERROR; 6783 } 6784 6785 6786 // Build a subject alternative name extension, if appropriate. 6787 final ArrayList<X509CertificateExtension> extensionList = 6788 new ArrayList<>(10); 6789 final GeneralNamesBuilder sanBuilder = new GeneralNamesBuilder(); 6790 final LinkedHashSet<String> sanValues = 6791 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 6792 final StringArgument sanDNSArgument = 6793 subCommandParser.getStringArgument("subject-alternative-name-dns"); 6794 if ((sanDNSArgument != null) && sanDNSArgument.isPresent()) 6795 { 6796 for (final String value : sanDNSArgument.getValues()) 6797 { 6798 sanBuilder.addDNSName(value); 6799 sanValues.add("DNS:" + value); 6800 } 6801 } 6802 6803 final StringArgument sanIPArgument = subCommandParser.getStringArgument( 6804 "subject-alternative-name-ip-address"); 6805 if ((sanIPArgument != null) && sanIPArgument.isPresent()) 6806 { 6807 for (final String value : sanIPArgument.getValues()) 6808 { 6809 try 6810 { 6811 sanBuilder.addIPAddress(LDAPConnectionOptions.DEFAULT_NAME_RESOLVER. 6812 getByName(value)); 6813 sanValues.add("IP:" + value); 6814 } 6815 catch (final Exception e) 6816 { 6817 // This should never happen. 6818 Debug.debugException(e); 6819 throw new RuntimeException(e); 6820 } 6821 } 6822 } 6823 6824 final StringArgument sanEmailArgument = subCommandParser.getStringArgument( 6825 "subject-alternative-name-email-address"); 6826 if ((sanEmailArgument != null) && sanEmailArgument.isPresent()) 6827 { 6828 for (final String value : sanEmailArgument.getValues()) 6829 { 6830 sanBuilder.addRFC822Name(value); 6831 sanValues.add("EMAIL:" + value); 6832 } 6833 } 6834 6835 final StringArgument sanURIArgument = 6836 subCommandParser.getStringArgument("subject-alternative-name-uri"); 6837 if ((sanURIArgument != null) && sanURIArgument.isPresent()) 6838 { 6839 for (final String value : sanURIArgument.getValues()) 6840 { 6841 sanBuilder.addUniformResourceIdentifier(value); 6842 sanValues.add("URI:" + value); 6843 } 6844 } 6845 6846 final StringArgument sanOIDArgument = 6847 subCommandParser.getStringArgument("subject-alternative-name-oid"); 6848 if ((sanOIDArgument != null) && sanOIDArgument.isPresent()) 6849 { 6850 for (final String value : sanOIDArgument.getValues()) 6851 { 6852 sanBuilder.addRegisteredID(new OID(value)); 6853 sanValues.add("OID:" + value); 6854 } 6855 } 6856 6857 if (! sanValues.isEmpty()) 6858 { 6859 try 6860 { 6861 extensionList.add( 6862 new SubjectAlternativeNameExtension(false, sanBuilder.build())); 6863 } 6864 catch (final Exception e) 6865 { 6866 // This should never happen. 6867 Debug.debugException(e); 6868 throw new RuntimeException(e); 6869 } 6870 } 6871 6872 // Build a set of issuer alternative name extension values. 6873 final GeneralNamesBuilder ianBuilder = new GeneralNamesBuilder(); 6874 final LinkedHashSet<String> ianValues = 6875 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 6876 final StringArgument ianDNSArgument = 6877 subCommandParser.getStringArgument("issuer-alternative-name-dns"); 6878 if ((ianDNSArgument != null) && ianDNSArgument.isPresent()) 6879 { 6880 for (final String value : ianDNSArgument.getValues()) 6881 { 6882 ianBuilder.addDNSName(value); 6883 ianValues.add("DNS:" + value); 6884 } 6885 } 6886 6887 final StringArgument ianIPArgument = subCommandParser.getStringArgument( 6888 "issuer-alternative-name-ip-address"); 6889 if ((ianIPArgument != null) && ianIPArgument.isPresent()) 6890 { 6891 for (final String value : ianIPArgument.getValues()) 6892 { 6893 try 6894 { 6895 ianBuilder.addIPAddress(LDAPConnectionOptions.DEFAULT_NAME_RESOLVER. 6896 getByName(value)); 6897 ianValues.add("IP:" + value); 6898 } 6899 catch (final Exception e) 6900 { 6901 // This should never happen. 6902 Debug.debugException(e); 6903 throw new RuntimeException(e); 6904 } 6905 } 6906 } 6907 6908 final StringArgument ianEmailArgument = subCommandParser.getStringArgument( 6909 "issuer-alternative-name-email-address"); 6910 if ((ianEmailArgument != null) && ianEmailArgument.isPresent()) 6911 { 6912 for (final String value : ianEmailArgument.getValues()) 6913 { 6914 ianBuilder.addRFC822Name(value); 6915 ianValues.add("EMAIL:" + value); 6916 } 6917 } 6918 6919 final StringArgument ianURIArgument = 6920 subCommandParser.getStringArgument("issuer-alternative-name-uri"); 6921 if ((ianURIArgument != null) && ianURIArgument.isPresent()) 6922 { 6923 for (final String value : ianURIArgument.getValues()) 6924 { 6925 ianBuilder.addUniformResourceIdentifier(value); 6926 ianValues.add("URI:" + value); 6927 } 6928 } 6929 6930 final StringArgument ianOIDArgument = 6931 subCommandParser.getStringArgument("issuer-alternative-name-oid"); 6932 if ((ianOIDArgument != null) && ianOIDArgument.isPresent()) 6933 { 6934 for (final String value : ianOIDArgument.getValues()) 6935 { 6936 ianBuilder.addRegisteredID(new OID(value)); 6937 ianValues.add("OID:" + value); 6938 } 6939 } 6940 6941 if (! ianValues.isEmpty()) 6942 { 6943 try 6944 { 6945 extensionList.add( 6946 new IssuerAlternativeNameExtension(false, ianBuilder.build())); 6947 } 6948 catch (final Exception e) 6949 { 6950 // This should never happen. 6951 Debug.debugException(e); 6952 throw new RuntimeException(e); 6953 } 6954 } 6955 6956 6957 // Build a basic constraints extension, if appropriate. 6958 BasicConstraintsExtension basicConstraints = null; 6959 final BooleanValueArgument basicConstraintsIsCAArgument = 6960 subCommandParser.getBooleanValueArgument("basic-constraints-is-ca"); 6961 if ((basicConstraintsIsCAArgument != null) && 6962 basicConstraintsIsCAArgument.isPresent()) 6963 { 6964 final boolean isCA = basicConstraintsIsCAArgument.getValue(); 6965 6966 Integer pathLength = null; 6967 final IntegerArgument pathLengthArgument = 6968 subCommandParser.getIntegerArgument( 6969 "basic-constraints-maximum-path-length"); 6970 if ((pathLengthArgument != null) && pathLengthArgument.isPresent()) 6971 { 6972 if (isCA) 6973 { 6974 pathLength = pathLengthArgument.getValue(); 6975 } 6976 else 6977 { 6978 wrapErr(0, WRAP_COLUMN, 6979 ERR_MANAGE_CERTS_GEN_CERT_BC_PATH_LENGTH_WITHOUT_CA.get()); 6980 return ResultCode.PARAM_ERROR; 6981 } 6982 } 6983 6984 basicConstraints = new BasicConstraintsExtension(false, isCA, pathLength); 6985 extensionList.add(basicConstraints); 6986 } 6987 6988 6989 // Build a key usage extension, if appropriate. 6990 KeyUsageExtension keyUsage = null; 6991 final StringArgument keyUsageArgument = 6992 subCommandParser.getStringArgument("key-usage"); 6993 if ((keyUsageArgument != null) && keyUsageArgument.isPresent()) 6994 { 6995 boolean digitalSignature = false; 6996 boolean nonRepudiation = false; 6997 boolean keyEncipherment = false; 6998 boolean dataEncipherment = false; 6999 boolean keyAgreement = false; 7000 boolean keyCertSign = false; 7001 boolean crlSign = false; 7002 boolean encipherOnly = false; 7003 boolean decipherOnly = false; 7004 7005 for (final String value : keyUsageArgument.getValues()) 7006 { 7007 if (value.equalsIgnoreCase("digital-signature") || 7008 value.equalsIgnoreCase("digitalSignature")) 7009 { 7010 digitalSignature = true; 7011 } 7012 else if (value.equalsIgnoreCase("non-repudiation") || 7013 value.equalsIgnoreCase("nonRepudiation") || 7014 value.equalsIgnoreCase("content-commitment") || 7015 value.equalsIgnoreCase("contentCommitment")) 7016 { 7017 nonRepudiation = true; 7018 } 7019 else if (value.equalsIgnoreCase("key-encipherment") || 7020 value.equalsIgnoreCase("keyEncipherment")) 7021 { 7022 keyEncipherment = true; 7023 } 7024 else if (value.equalsIgnoreCase("data-encipherment") || 7025 value.equalsIgnoreCase("dataEncipherment")) 7026 { 7027 dataEncipherment = true; 7028 } 7029 else if (value.equalsIgnoreCase("key-agreement") || 7030 value.equalsIgnoreCase("keyAgreement")) 7031 { 7032 keyAgreement = true; 7033 } 7034 else if (value.equalsIgnoreCase("key-cert-sign") || 7035 value.equalsIgnoreCase("keyCertSign")) 7036 { 7037 keyCertSign = true; 7038 } 7039 else if (value.equalsIgnoreCase("crl-sign") || 7040 value.equalsIgnoreCase("crlSign")) 7041 { 7042 crlSign = true; 7043 } 7044 else if (value.equalsIgnoreCase("encipher-only") || 7045 value.equalsIgnoreCase("encipherOnly")) 7046 { 7047 encipherOnly = true; 7048 } 7049 else if (value.equalsIgnoreCase("decipher-only") || 7050 value.equalsIgnoreCase("decipherOnly")) 7051 { 7052 decipherOnly = true; 7053 } 7054 else 7055 { 7056 wrapErr(0, WRAP_COLUMN, 7057 ERR_MANAGE_CERTS_GEN_CERT_INVALID_KEY_USAGE.get(value)); 7058 return ResultCode.PARAM_ERROR; 7059 } 7060 } 7061 7062 keyUsage = new KeyUsageExtension(false, digitalSignature, nonRepudiation, 7063 keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, 7064 crlSign, encipherOnly, decipherOnly); 7065 extensionList.add(keyUsage); 7066 } 7067 7068 7069 // Build an extended key usage extension, if appropriate. 7070 ExtendedKeyUsageExtension extendedKeyUsage = null; 7071 final StringArgument extendedKeyUsageArgument = 7072 subCommandParser.getStringArgument("extended-key-usage"); 7073 if ((extendedKeyUsageArgument != null) && 7074 extendedKeyUsageArgument.isPresent()) 7075 { 7076 final List<String> values = extendedKeyUsageArgument.getValues(); 7077 final ArrayList<OID> keyPurposeIDs = new ArrayList<>(values.size()); 7078 for (final String value : values) 7079 { 7080 if (value.equalsIgnoreCase("server-auth") || 7081 value.equalsIgnoreCase("serverAuth") || 7082 value.equalsIgnoreCase("server-authentication") || 7083 value.equalsIgnoreCase("serverAuthentication") || 7084 value.equalsIgnoreCase("tls-server-authentication") || 7085 value.equalsIgnoreCase("tlsServerAuthentication")) 7086 { 7087 keyPurposeIDs.add( 7088 ExtendedKeyUsageID.TLS_SERVER_AUTHENTICATION.getOID()); 7089 } 7090 else if (value.equalsIgnoreCase("client-auth") || 7091 value.equalsIgnoreCase("clientAuth") || 7092 value.equalsIgnoreCase("client-authentication") || 7093 value.equalsIgnoreCase("clientAuthentication") || 7094 value.equalsIgnoreCase("tls-client-authentication") || 7095 value.equalsIgnoreCase("tlsClientAuthentication")) 7096 { 7097 keyPurposeIDs.add( 7098 ExtendedKeyUsageID.TLS_CLIENT_AUTHENTICATION.getOID()); 7099 } 7100 else if (value.equalsIgnoreCase("code-signing") || 7101 value.equalsIgnoreCase("codeSigning")) 7102 { 7103 keyPurposeIDs.add(ExtendedKeyUsageID.CODE_SIGNING.getOID()); 7104 } 7105 else if (value.equalsIgnoreCase("email-protection") || 7106 value.equalsIgnoreCase("emailProtection")) 7107 { 7108 keyPurposeIDs.add(ExtendedKeyUsageID.EMAIL_PROTECTION.getOID()); 7109 } 7110 else if (value.equalsIgnoreCase("time-stamping") || 7111 value.equalsIgnoreCase("timeStamping")) 7112 { 7113 keyPurposeIDs.add(ExtendedKeyUsageID.TIME_STAMPING.getOID()); 7114 } 7115 else if (value.equalsIgnoreCase("ocsp-signing") || 7116 value.equalsIgnoreCase("ocspSigning")) 7117 { 7118 keyPurposeIDs.add(ExtendedKeyUsageID.OCSP_SIGNING.getOID()); 7119 } 7120 else if (OID.isStrictlyValidNumericOID(value)) 7121 { 7122 keyPurposeIDs.add(new OID(value)); 7123 } 7124 else 7125 { 7126 wrapErr(0, WRAP_COLUMN, 7127 ERR_MANAGE_CERTS_GEN_CERT_INVALID_EXTENDED_KEY_USAGE.get(value)); 7128 return ResultCode.PARAM_ERROR; 7129 } 7130 } 7131 7132 try 7133 { 7134 extendedKeyUsage = new ExtendedKeyUsageExtension(false, keyPurposeIDs); 7135 } 7136 catch (final Exception e) 7137 { 7138 // This should never happen. 7139 Debug.debugException(e); 7140 wrapErr(0, WRAP_COLUMN, 7141 ERR_MANAGE_CERTS_GEN_CERT_EXTENDED_KEY_USAGE_ERROR.get()); 7142 e.printStackTrace(getErr()); 7143 return ResultCode.PARAM_ERROR; 7144 } 7145 7146 extensionList.add(extendedKeyUsage); 7147 } 7148 7149 7150 // Build a list of generic extensions. 7151 final ArrayList<X509CertificateExtension> genericExtensions = 7152 new ArrayList<>(5); 7153 final StringArgument extensionArgument = 7154 subCommandParser.getStringArgument("extension"); 7155 if ((extensionArgument != null) && extensionArgument.isPresent()) 7156 { 7157 for (final String value : extensionArgument.getValues()) 7158 { 7159 try 7160 { 7161 final int firstColonPos = value.indexOf(':'); 7162 final int secondColonPos = value.indexOf(':', firstColonPos + 1); 7163 final OID oid = new OID(value.substring(0, firstColonPos)); 7164 if (! oid.isStrictlyValidNumericOID()) 7165 { 7166 wrapErr(0, WRAP_COLUMN, 7167 ERR_MANAGE_CERTS_GEN_CERT_EXT_MALFORMED_OID.get(value, 7168 oid.toString())); 7169 return ResultCode.PARAM_ERROR; 7170 } 7171 7172 final boolean criticality; 7173 final String criticalityString = 7174 value.substring(firstColonPos + 1, secondColonPos); 7175 if (criticalityString.equalsIgnoreCase("true") || 7176 criticalityString.equalsIgnoreCase("t") || 7177 criticalityString.equalsIgnoreCase("yes") || 7178 criticalityString.equalsIgnoreCase("y") || 7179 criticalityString.equalsIgnoreCase("on") || 7180 criticalityString.equalsIgnoreCase("1")) 7181 { 7182 criticality = true; 7183 } 7184 else if (criticalityString.equalsIgnoreCase("false") || 7185 criticalityString.equalsIgnoreCase("f") || 7186 criticalityString.equalsIgnoreCase("no") || 7187 criticalityString.equalsIgnoreCase("n") || 7188 criticalityString.equalsIgnoreCase("off") || 7189 criticalityString.equalsIgnoreCase("0")) 7190 { 7191 criticality = false; 7192 } 7193 else 7194 { 7195 wrapErr(0, WRAP_COLUMN, 7196 ERR_MANAGE_CERTS_GEN_CERT_EXT_INVALID_CRITICALITY.get( 7197 value, criticalityString)); 7198 return ResultCode.PARAM_ERROR; 7199 } 7200 7201 final byte[] valueBytes; 7202 try 7203 { 7204 valueBytes = StaticUtils.fromHex(value.substring(secondColonPos+1)); 7205 } 7206 catch (final Exception e) 7207 { 7208 Debug.debugException(e); 7209 wrapErr(0, WRAP_COLUMN, 7210 ERR_MANAGE_CERTS_GEN_CERT_EXT_INVALID_VALUE.get(value)); 7211 return ResultCode.PARAM_ERROR; 7212 } 7213 7214 final X509CertificateExtension extension = 7215 new X509CertificateExtension(oid, criticality, valueBytes); 7216 genericExtensions.add(extension); 7217 extensionList.add(extension); 7218 } 7219 catch (final Exception e) 7220 { 7221 Debug.debugException(e); 7222 wrapErr(0, WRAP_COLUMN, 7223 ERR_MANAGE_CERTS_GEN_CERT_EXT_MALFORMED.get(value)); 7224 return ResultCode.PARAM_ERROR; 7225 } 7226 } 7227 } 7228 7229 7230 final String keystoreType; 7231 try 7232 { 7233 keystoreType = inferKeystoreType(keystorePath); 7234 } 7235 catch (final LDAPException le) 7236 { 7237 Debug.debugException(le); 7238 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7239 return le.getResultCode(); 7240 } 7241 7242 final char[] keystorePassword; 7243 try 7244 { 7245 keystorePassword = getKeystorePassword(keystorePath); 7246 } 7247 catch (final LDAPException le) 7248 { 7249 Debug.debugException(le); 7250 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7251 return le.getResultCode(); 7252 } 7253 7254 7255 // Get the keystore. 7256 final KeyStore keystore; 7257 try 7258 { 7259 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 7260 } 7261 catch (final LDAPException le) 7262 { 7263 Debug.debugException(le); 7264 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7265 return le.getResultCode(); 7266 } 7267 7268 7269 // If there is a private key, then see if we need to use a private key 7270 // password that is different from the keystore password. 7271 final char[] privateKeyPassword; 7272 try 7273 { 7274 privateKeyPassword = 7275 getPrivateKeyPassword(keystore, alias, keystorePassword); 7276 } 7277 catch (final LDAPException le) 7278 { 7279 Debug.debugException(le); 7280 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7281 return le.getResultCode(); 7282 } 7283 7284 7285 // If we're going to replace an existing certificate in the keystore, then 7286 // perform the appropriate processing for that. 7287 if (useExistingKeyPair) 7288 { 7289 // Make sure that the keystore already has a private key entry with the 7290 // specified alias. 7291 if (! hasKeyAlias(keystore, alias)) 7292 { 7293 if (hasCertificateAlias(keystore, alias)) 7294 { 7295 wrapErr(0, WRAP_COLUMN, 7296 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_ALIAS_IS_CERT.get( 7297 alias, keystorePath.getAbsolutePath())); 7298 return ResultCode.PARAM_ERROR; 7299 } 7300 else 7301 { 7302 wrapErr(0, WRAP_COLUMN, 7303 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_NO_SUCH_ALIAS.get( 7304 alias, keystorePath.getAbsolutePath())); 7305 return ResultCode.PARAM_ERROR; 7306 } 7307 } 7308 7309 7310 // Get the certificate to replace, along with its key pair. 7311 final X509Certificate certToReplace; 7312 final KeyPair keyPair; 7313 try 7314 { 7315 final Certificate[] chain = keystore.getCertificateChain(alias); 7316 certToReplace = new X509Certificate(chain[0].getEncoded()); 7317 7318 final PublicKey publicKey = chain[0].getPublicKey(); 7319 final PrivateKey privateKey = 7320 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 7321 keyPair = new KeyPair(publicKey, privateKey); 7322 } 7323 catch (final Exception e) 7324 { 7325 Debug.debugException(e); 7326 wrapErr(0, WRAP_COLUMN, 7327 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_COULD_NOT_GET_CERT.get( 7328 alias)); 7329 e.printStackTrace(getErr()); 7330 return ResultCode.LOCAL_ERROR; 7331 } 7332 7333 7334 // Assign the remaining values using information in the existing 7335 // certificate. 7336 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forOID( 7337 certToReplace.getSignatureAlgorithmOID()); 7338 if (signatureAlgorithmIdentifier == null) 7339 { 7340 wrapErr(0, WRAP_COLUMN, 7341 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG_IN_CERT.get( 7342 certToReplace.getSignatureAlgorithmOID())); 7343 return ResultCode.PARAM_ERROR; 7344 } 7345 else 7346 { 7347 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 7348 } 7349 7350 if (subjectDN == null) 7351 { 7352 subjectDN = certToReplace.getSubjectDN(); 7353 } 7354 7355 if (inheritExtensions) 7356 { 7357 for (final X509CertificateExtension extension : 7358 certToReplace.getExtensions()) 7359 { 7360 if ((extension instanceof AuthorityKeyIdentifierExtension) || 7361 (extension instanceof IssuerAlternativeNameExtension)) 7362 { 7363 // This extension applies to the issuer. We won't include this in 7364 // the set of inherited extensions. 7365 } 7366 else if (extension instanceof SubjectKeyIdentifierExtension) 7367 { 7368 // The generated certificate will automatically include a subject 7369 // key identifier extension, so we don't need to include it. 7370 } 7371 else if (extension instanceof BasicConstraintsExtension) 7372 { 7373 // Don't override a value already provided on the command line. 7374 if (basicConstraints == null) 7375 { 7376 basicConstraints = (BasicConstraintsExtension) extension; 7377 extensionList.add(basicConstraints); 7378 } 7379 } 7380 else if (extension instanceof ExtendedKeyUsageExtension) 7381 { 7382 // Don't override a value already provided on the command line. 7383 if (extendedKeyUsage == null) 7384 { 7385 extendedKeyUsage = (ExtendedKeyUsageExtension) extension; 7386 extensionList.add(extendedKeyUsage); 7387 } 7388 } 7389 else if (extension instanceof KeyUsageExtension) 7390 { 7391 // Don't override a value already provided on the command line. 7392 if (keyUsage == null) 7393 { 7394 keyUsage = (KeyUsageExtension) extension; 7395 extensionList.add(keyUsage); 7396 } 7397 } 7398 else if (extension instanceof SubjectAlternativeNameExtension) 7399 { 7400 // Although we could merge values, it's safer to not do that if any 7401 // subject alternative name values were provided on the command 7402 // line. 7403 if (sanValues.isEmpty()) 7404 { 7405 final SubjectAlternativeNameExtension e = 7406 (SubjectAlternativeNameExtension) extension; 7407 for (final String dnsName : e.getDNSNames()) 7408 { 7409 sanValues.add("DNS:" + dnsName); 7410 } 7411 7412 for (final InetAddress ipAddress : e.getIPAddresses()) 7413 { 7414 sanValues.add("IP:" + ipAddress.getHostAddress()); 7415 } 7416 7417 for (final String emailAddress : e.getRFC822Names()) 7418 { 7419 sanValues.add("EMAIL:" + emailAddress); 7420 } 7421 7422 for (final String uri : e.getUniformResourceIdentifiers()) 7423 { 7424 sanValues.add("URI:" + uri); 7425 } 7426 7427 for (final OID oid : e.getRegisteredIDs()) 7428 { 7429 sanValues.add("OID:" + oid.toString()); 7430 } 7431 7432 extensionList.add(extension); 7433 } 7434 } 7435 else 7436 { 7437 genericExtensions.add(extension); 7438 extensionList.add(extension); 7439 } 7440 } 7441 } 7442 7443 7444 // Create an array with the final set of extensions to include in the 7445 // certificate or certificate signing request. 7446 final X509CertificateExtension[] extensions = 7447 new X509CertificateExtension[extensionList.size()]; 7448 extensionList.toArray(extensions); 7449 7450 7451 // If we're generating a self-signed certificate or a certificate signing 7452 // request, then we should now have everything we need to do that. Build 7453 // a keytool command that we could use to accomplish it. 7454 if (isGenerateCertificate) 7455 { 7456 if (displayKeytoolCommand) 7457 { 7458 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7459 keytoolArguments.add("-selfcert"); 7460 keytoolArguments.add("-keystore"); 7461 keytoolArguments.add(keystorePath.getAbsolutePath()); 7462 keytoolArguments.add("-storetype"); 7463 keytoolArguments.add(keystoreType); 7464 keytoolArguments.add("-storepass"); 7465 keytoolArguments.add("*****REDACTED*****"); 7466 keytoolArguments.add("-keypass"); 7467 keytoolArguments.add("*****REDACTED*****"); 7468 keytoolArguments.add("-alias"); 7469 keytoolArguments.add(alias); 7470 keytoolArguments.add("-dname"); 7471 keytoolArguments.add(subjectDN.toString()); 7472 keytoolArguments.add("-sigalg"); 7473 keytoolArguments.add(signatureAlgorithmName); 7474 keytoolArguments.add("-validity"); 7475 keytoolArguments.add(String.valueOf(daysValid)); 7476 7477 if (validityStartTime != null) 7478 { 7479 keytoolArguments.add("-startdate"); 7480 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 7481 } 7482 7483 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7484 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7485 7486 displayKeytoolCommand(keytoolArguments); 7487 } 7488 7489 7490 // Generate the self-signed certificate. 7491 final long notBefore; 7492 if (validityStartTime == null) 7493 { 7494 notBefore = System.currentTimeMillis(); 7495 } 7496 else 7497 { 7498 notBefore = validityStartTime.getTime(); 7499 } 7500 7501 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 7502 7503 final X509Certificate certificate; 7504 final Certificate[] chain; 7505 try 7506 { 7507 certificate = X509Certificate.generateSelfSignedCertificate( 7508 signatureAlgorithmIdentifier, keyPair, subjectDN, notBefore, 7509 notAfter, extensions); 7510 chain = new Certificate[] { certificate.toCertificate() }; 7511 } 7512 catch (final Exception e) 7513 { 7514 Debug.debugException(e); 7515 wrapErr(0, WRAP_COLUMN, 7516 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CERT.get()); 7517 e.printStackTrace(getErr()); 7518 return ResultCode.LOCAL_ERROR; 7519 } 7520 7521 7522 // Update the keystore with the new certificate. 7523 try 7524 { 7525 keystore.setKeyEntry(alias, keyPair.getPrivate(), privateKeyPassword, 7526 chain); 7527 writeKeystore(keystore, keystorePath, keystorePassword); 7528 } 7529 catch (final Exception e) 7530 { 7531 Debug.debugException(e); 7532 wrapErr(0, WRAP_COLUMN, 7533 ERR_MANAGE_CERTS_GEN_CERT_ERROR_UPDATING_KEYSTORE.get()); 7534 e.printStackTrace(getErr()); 7535 return ResultCode.LOCAL_ERROR; 7536 } 7537 7538 7539 // Display the certificate we just generated to the end user. 7540 out(); 7541 wrapOut(0, WRAP_COLUMN, 7542 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_SELF_CERT. 7543 get()); 7544 printCertificate(certificate, "", false); 7545 7546 7547 // If we should write an output file, then do that now. 7548 if (outputFile != null) 7549 { 7550 try (PrintStream ps = new PrintStream(outputFile)) 7551 { 7552 final byte[] certBytes = certificate.getX509CertificateBytes(); 7553 if (outputPEM) 7554 { 7555 writePEMCertificate(ps, certBytes); 7556 } 7557 else 7558 { 7559 ps.write(certBytes); 7560 } 7561 7562 out(); 7563 wrapOut(0, WRAP_COLUMN, 7564 INFO_MANAGE_CERTS_GEN_CERT_WROTE_OUTPUT_FILE.get( 7565 outputFile.getAbsolutePath())); 7566 } 7567 catch (final Exception e) 7568 { 7569 Debug.debugException(e); 7570 err(); 7571 wrapErr(0, WRAP_COLUMN, 7572 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CERT.get( 7573 outputFile.getAbsolutePath())); 7574 e.printStackTrace(getErr()); 7575 return ResultCode.LOCAL_ERROR; 7576 } 7577 } 7578 7579 return ResultCode.SUCCESS; 7580 } 7581 else 7582 { 7583 // Build the keytool command used to generate the certificate signing 7584 // request. 7585 Validator.ensureTrue(isGenerateCSR); 7586 if (displayKeytoolCommand) 7587 { 7588 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7589 keytoolArguments.add("-certreq"); 7590 keytoolArguments.add("-keystore"); 7591 keytoolArguments.add(keystorePath.getAbsolutePath()); 7592 keytoolArguments.add("-storetype"); 7593 keytoolArguments.add(keystoreType); 7594 keytoolArguments.add("-storepass"); 7595 keytoolArguments.add("*****REDACTED*****"); 7596 keytoolArguments.add("-keypass"); 7597 keytoolArguments.add("*****REDACTED*****"); 7598 keytoolArguments.add("-alias"); 7599 keytoolArguments.add(alias); 7600 keytoolArguments.add("-dname"); 7601 keytoolArguments.add(subjectDN.toString()); 7602 keytoolArguments.add("-sigalg"); 7603 keytoolArguments.add(signatureAlgorithmName); 7604 7605 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7606 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7607 7608 if (outputFile != null) 7609 { 7610 keytoolArguments.add("-file"); 7611 keytoolArguments.add(outputFile.getAbsolutePath()); 7612 } 7613 7614 displayKeytoolCommand(keytoolArguments); 7615 } 7616 7617 7618 // Generate the certificate signing request. 7619 final PKCS10CertificateSigningRequest certificateSigningRequest; 7620 try 7621 { 7622 certificateSigningRequest = PKCS10CertificateSigningRequest. 7623 generateCertificateSigningRequest(signatureAlgorithmIdentifier, 7624 keyPair, subjectDN, extensions); 7625 } 7626 catch (final Exception e) 7627 { 7628 Debug.debugException(e); 7629 wrapErr(0, WRAP_COLUMN, 7630 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CSR.get()); 7631 e.printStackTrace(getErr()); 7632 return ResultCode.LOCAL_ERROR; 7633 } 7634 7635 7636 // Write the generated certificate signing request to the appropriate 7637 // location. 7638 try 7639 { 7640 final PrintStream ps; 7641 if (outputFile == null) 7642 { 7643 ps = getOut(); 7644 } 7645 else 7646 { 7647 ps = new PrintStream(outputFile); 7648 } 7649 7650 if (outputPEM) 7651 { 7652 writePEMCertificateSigningRequest(ps, 7653 certificateSigningRequest. 7654 getPKCS10CertificateSigningRequestBytes()); 7655 } 7656 else 7657 { 7658 ps.write(certificateSigningRequest. 7659 getPKCS10CertificateSigningRequestBytes()); 7660 } 7661 7662 if (outputFile != null) 7663 { 7664 ps.close(); 7665 } 7666 } 7667 catch (final Exception e) 7668 { 7669 Debug.debugException(e); 7670 wrapErr(0, WRAP_COLUMN, 7671 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CSR.get()); 7672 e.printStackTrace(getErr()); 7673 return ResultCode.LOCAL_ERROR; 7674 } 7675 7676 7677 // If the certificate signing request was written to an output file, 7678 // then let the user know that it was successful. If it was written to 7679 // standard output, then we don't need to tell them because they'll be 7680 // able to see it. 7681 if (outputFile != null) 7682 { 7683 out(); 7684 wrapOut(0, WRAP_COLUMN, 7685 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_CSR.get( 7686 outputFile.getAbsolutePath())); 7687 } 7688 7689 return ResultCode.SUCCESS; 7690 } 7691 } 7692 7693 7694 // If we've gotten here, then we know we're not replacing an existing 7695 // certificate. Perform any remaining argument assignment and validation. 7696 if ((subjectDN == null) && (! isSignCSR)) 7697 { 7698 wrapErr(0, WRAP_COLUMN, 7699 ERR_MANAGE_CERTS_GEN_CERT_NO_SUBJECT_DN_WITHOUT_USE_EXISTING_KP. 7700 get()); 7701 return ResultCode.PARAM_ERROR; 7702 } 7703 7704 if (keyAlgorithmIdentifier == null) 7705 { 7706 keyAlgorithmIdentifier = PublicKeyAlgorithmIdentifier.RSA; 7707 keyAlgorithmName = keyAlgorithmIdentifier.getName(); 7708 } 7709 7710 if (keySizeBits == null) 7711 { 7712 keySizeBits = 2048; 7713 } 7714 7715 if ((signatureAlgorithmIdentifier == null) && (! isSignCSR)) 7716 { 7717 signatureAlgorithmIdentifier = 7718 SignatureAlgorithmIdentifier.SHA_256_WITH_RSA; 7719 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 7720 } 7721 7722 7723 // If we're going to generate a self-signed certificate or a certificate 7724 // signing request, then we first need to generate a key pair. Put together 7725 // the appropriate set of keytool arguments and then generate a self-signed 7726 // certificate. 7727 if (isGenerateCertificate || isGenerateCSR) 7728 { 7729 // Make sure that the specified alias is not already in use in the 7730 // keystore. 7731 if (hasKeyAlias(keystore, alias) || hasCertificateAlias(keystore, alias)) 7732 { 7733 wrapErr(0, WRAP_COLUMN, 7734 ERR_MANAGE_CERTS_GEN_CERT_ALIAS_EXISTS_WITHOUT_USE_EXISTING_KP.get( 7735 alias)); 7736 return ResultCode.PARAM_ERROR; 7737 } 7738 7739 7740 if (displayKeytoolCommand) 7741 { 7742 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7743 keytoolArguments.add("-genkeypair"); 7744 keytoolArguments.add("-keystore"); 7745 keytoolArguments.add(keystorePath.getAbsolutePath()); 7746 keytoolArguments.add("-storetype"); 7747 keytoolArguments.add(keystoreType); 7748 keytoolArguments.add("-storepass"); 7749 keytoolArguments.add("*****REDACTED*****"); 7750 keytoolArguments.add("-keypass"); 7751 keytoolArguments.add("*****REDACTED*****"); 7752 keytoolArguments.add("-alias"); 7753 keytoolArguments.add(alias); 7754 keytoolArguments.add("-dname"); 7755 keytoolArguments.add(subjectDN.toString()); 7756 keytoolArguments.add("-keyalg"); 7757 keytoolArguments.add(keyAlgorithmName); 7758 keytoolArguments.add("-keysize"); 7759 keytoolArguments.add(String.valueOf(keySizeBits)); 7760 keytoolArguments.add("-sigalg"); 7761 keytoolArguments.add(signatureAlgorithmName); 7762 keytoolArguments.add("-validity"); 7763 keytoolArguments.add(String.valueOf(daysValid)); 7764 7765 if (validityStartTime != null) 7766 { 7767 keytoolArguments.add("-startdate"); 7768 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 7769 } 7770 7771 addExtensionArguments(keytoolArguments, basicConstraints, 7772 keyUsage, extendedKeyUsage, sanValues, ianValues, 7773 genericExtensions); 7774 7775 displayKeytoolCommand(keytoolArguments); 7776 } 7777 7778 7779 // Generate the self-signed certificate. 7780 final long notBefore; 7781 if (validityStartTime == null) 7782 { 7783 notBefore = System.currentTimeMillis(); 7784 } 7785 else 7786 { 7787 notBefore = validityStartTime.getTime(); 7788 } 7789 7790 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 7791 7792 final X509CertificateExtension[] extensions = 7793 new X509CertificateExtension[extensionList.size()]; 7794 extensionList.toArray(extensions); 7795 7796 final Certificate[] chain; 7797 final KeyPair keyPair; 7798 final X509Certificate certificate; 7799 try 7800 { 7801 final ObjectPair<X509Certificate,KeyPair> p = 7802 X509Certificate.generateSelfSignedCertificate( 7803 signatureAlgorithmIdentifier, keyAlgorithmIdentifier, 7804 keySizeBits, subjectDN, notBefore, notAfter, extensions); 7805 certificate = p.getFirst(); 7806 chain = new Certificate[] { certificate.toCertificate() }; 7807 keyPair = p.getSecond(); 7808 } 7809 catch (final Exception e) 7810 { 7811 Debug.debugException(e); 7812 wrapErr(0, WRAP_COLUMN, 7813 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CERT.get()); 7814 e.printStackTrace(getErr()); 7815 return ResultCode.LOCAL_ERROR; 7816 } 7817 7818 7819 // Update the keystore with the new certificate. 7820 try 7821 { 7822 keystore.setKeyEntry(alias, keyPair.getPrivate(), privateKeyPassword, 7823 chain); 7824 writeKeystore(keystore, keystorePath, keystorePassword); 7825 } 7826 catch (final Exception e) 7827 { 7828 Debug.debugException(e); 7829 wrapErr(0, WRAP_COLUMN, 7830 ERR_MANAGE_CERTS_GEN_CERT_ERROR_UPDATING_KEYSTORE.get()); 7831 e.printStackTrace(getErr()); 7832 return ResultCode.LOCAL_ERROR; 7833 } 7834 7835 if (isNewKeystore) 7836 { 7837 out(); 7838 wrapOut(0, WRAP_COLUMN, 7839 INFO_MANAGE_CERTS_GEN_CERT_CERT_CREATED_KEYSTORE.get( 7840 getUserFriendlyKeystoreType(keystoreType))); 7841 } 7842 7843 7844 // If we're just generating a self-signed certificate, then display the 7845 // certificate that we generated and potentially write it to an output 7846 // file. 7847 if (isGenerateCertificate) 7848 { 7849 out(); 7850 wrapOut(0, WRAP_COLUMN, 7851 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_SELF_CERT.get()); 7852 printCertificate(certificate, "", false); 7853 7854 7855 // If we should write an output file, then do that now. 7856 if (outputFile != null) 7857 { 7858 try (PrintStream ps = new PrintStream(outputFile)) 7859 { 7860 final byte[] certBytes = certificate.getX509CertificateBytes(); 7861 if (outputPEM) 7862 { 7863 writePEMCertificate(ps, certBytes); 7864 } 7865 else 7866 { 7867 ps.write(certBytes); 7868 } 7869 7870 out(); 7871 wrapOut(0, WRAP_COLUMN, 7872 INFO_MANAGE_CERTS_GEN_CERT_WROTE_OUTPUT_FILE.get( 7873 outputFile.getAbsolutePath())); 7874 } 7875 catch (final Exception e) 7876 { 7877 Debug.debugException(e); 7878 err(); 7879 wrapErr(0, WRAP_COLUMN, 7880 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CERT.get( 7881 outputFile.getAbsolutePath())); 7882 e.printStackTrace(getErr()); 7883 return ResultCode.LOCAL_ERROR; 7884 } 7885 } 7886 7887 return ResultCode.SUCCESS; 7888 } 7889 7890 7891 // If we're generating a certificate signing request, then put together 7892 // the appropriate set of arguments for that. 7893 Validator.ensureTrue(isGenerateCSR); 7894 out(); 7895 wrapOut(0, WRAP_COLUMN, 7896 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_KEYPAIR.get()); 7897 7898 if (displayKeytoolCommand) 7899 { 7900 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7901 keytoolArguments.add("-certreq"); 7902 keytoolArguments.add("-keystore"); 7903 keytoolArguments.add(keystorePath.getAbsolutePath()); 7904 keytoolArguments.add("-storetype"); 7905 keytoolArguments.add(keystoreType); 7906 keytoolArguments.add("-storepass"); 7907 keytoolArguments.add("*****REDACTED*****"); 7908 keytoolArguments.add("-keypass"); 7909 keytoolArguments.add("*****REDACTED*****"); 7910 keytoolArguments.add("-alias"); 7911 keytoolArguments.add(alias); 7912 keytoolArguments.add("-dname"); 7913 keytoolArguments.add(subjectDN.toString()); 7914 keytoolArguments.add("-sigalg"); 7915 keytoolArguments.add(signatureAlgorithmName); 7916 7917 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7918 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7919 7920 if (outputFile != null) 7921 { 7922 keytoolArguments.add("-file"); 7923 keytoolArguments.add(outputFile.getAbsolutePath()); 7924 } 7925 7926 displayKeytoolCommand(keytoolArguments); 7927 } 7928 7929 7930 // Generate the certificate signing request. 7931 final PKCS10CertificateSigningRequest certificateSigningRequest; 7932 try 7933 { 7934 certificateSigningRequest = PKCS10CertificateSigningRequest. 7935 generateCertificateSigningRequest(signatureAlgorithmIdentifier, 7936 keyPair, subjectDN, extensions); 7937 } 7938 catch (final Exception e) 7939 { 7940 Debug.debugException(e); 7941 wrapErr(0, WRAP_COLUMN, 7942 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CSR.get()); 7943 e.printStackTrace(getErr()); 7944 return ResultCode.LOCAL_ERROR; 7945 } 7946 7947 7948 // Write the generated certificate signing request to the appropriate 7949 // location. 7950 try 7951 { 7952 final PrintStream ps; 7953 if (outputFile == null) 7954 { 7955 ps = getOut(); 7956 } 7957 else 7958 { 7959 ps = new PrintStream(outputFile); 7960 } 7961 7962 if (outputPEM) 7963 { 7964 writePEMCertificateSigningRequest(ps, 7965 certificateSigningRequest. 7966 getPKCS10CertificateSigningRequestBytes()); 7967 } 7968 else 7969 { 7970 ps.write(certificateSigningRequest. 7971 getPKCS10CertificateSigningRequestBytes()); 7972 } 7973 7974 if (outputFile != null) 7975 { 7976 ps.close(); 7977 } 7978 } 7979 catch (final Exception e) 7980 { 7981 Debug.debugException(e); 7982 wrapErr(0, WRAP_COLUMN, 7983 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CSR.get()); 7984 e.printStackTrace(getErr()); 7985 return ResultCode.LOCAL_ERROR; 7986 } 7987 7988 7989 // If the certificate signing request was written to an output file, 7990 // then let the user know that it was successful. If it was written to 7991 // standard output, then we don't need to tell them because they'll be 7992 // able to see it. 7993 if (outputFile != null) 7994 { 7995 out(); 7996 wrapOut(0, WRAP_COLUMN, 7997 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_CSR.get( 7998 outputFile.getAbsolutePath())); 7999 } 8000 8001 return ResultCode.SUCCESS; 8002 } 8003 8004 8005 // If we've gotten here, then we should be signing a certificate signing 8006 // request. Make sure that the keystore already has a private key entry 8007 // with the specified alias. 8008 Validator.ensureTrue(isSignCSR); 8009 if (! hasKeyAlias(keystore, alias)) 8010 { 8011 if (hasCertificateAlias(keystore, alias)) 8012 { 8013 wrapErr(0, WRAP_COLUMN, 8014 ERR_MANAGE_CERTS_GEN_CERT_SIGN_ALIAS_IS_CERT.get(alias, 8015 keystorePath.getAbsolutePath())); 8016 return ResultCode.PARAM_ERROR; 8017 } 8018 else 8019 { 8020 wrapErr(0, WRAP_COLUMN, 8021 ERR_MANAGE_CERTS_GEN_CERT_SIGN_NO_SUCH_ALIAS.get(alias, 8022 keystorePath.getAbsolutePath())); 8023 return ResultCode.PARAM_ERROR; 8024 } 8025 } 8026 8027 8028 // Get the signing certificate and its key pair. 8029 final PrivateKey issuerPrivateKey; 8030 final X509Certificate issuerCertificate; 8031 try 8032 { 8033 final Certificate[] chain = keystore.getCertificateChain(alias); 8034 issuerCertificate = new X509Certificate(chain[0].getEncoded()); 8035 8036 issuerPrivateKey = 8037 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 8038 } 8039 catch (final Exception e) 8040 { 8041 Debug.debugException(e); 8042 wrapErr(0, WRAP_COLUMN, 8043 ERR_MANAGE_CERTS_GEN_CERT_SIGN_CANNOT_GET_SIGNING_CERT.get(alias)); 8044 e.printStackTrace(getErr()); 8045 return ResultCode.LOCAL_ERROR; 8046 } 8047 8048 8049 // Make sure that we can decode the certificate signing request. 8050 final PKCS10CertificateSigningRequest csr; 8051 try 8052 { 8053 csr = readCertificateSigningRequestFromFile(inputFile); 8054 } 8055 catch (final LDAPException le) 8056 { 8057 Debug.debugException(le); 8058 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8059 return le.getResultCode(); 8060 } 8061 8062 8063 // Make sure that we can verify the certificate signing request's signature. 8064 try 8065 { 8066 csr.verifySignature(); 8067 } 8068 catch (final CertException ce) 8069 { 8070 Debug.debugException(ce); 8071 wrapErr(0, WRAP_COLUMN, ce.getMessage()); 8072 return ResultCode.PARAM_ERROR; 8073 } 8074 8075 8076 // Prompt about whether to sign the request, if appropriate. 8077 if (! noPrompt) 8078 { 8079 out(); 8080 wrapOut(0, WRAP_COLUMN, 8081 INFO_MANAGE_CERTS_GEN_CERT_SIGN_CONFIRM.get()); 8082 out(); 8083 printCertificateSigningRequest(csr, false, ""); 8084 out(); 8085 8086 try 8087 { 8088 if (! promptForYesNo( 8089 INFO_MANAGE_CERTS_GEN_CERT_PROMPT_SIGN.get())) 8090 { 8091 wrapErr(0, WRAP_COLUMN, 8092 ERR_MANAGE_CERTS_GEN_CERT_SIGN_CANCELED.get()); 8093 return ResultCode.USER_CANCELED; 8094 } 8095 } 8096 catch (final LDAPException le) 8097 { 8098 Debug.debugException(le); 8099 err(); 8100 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8101 return le.getResultCode(); 8102 } 8103 } 8104 8105 8106 // Read the certificate signing request and see if we need to take values 8107 // from it. 8108 if ((subjectDN == null) || (signatureAlgorithmIdentifier == null) || 8109 includeRequestedExtensions) 8110 { 8111 if (subjectDN == null) 8112 { 8113 subjectDN = csr.getSubjectDN(); 8114 } 8115 8116 if (signatureAlgorithmIdentifier == null) 8117 { 8118 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forOID( 8119 csr.getSignatureAlgorithmOID()); 8120 if (signatureAlgorithmIdentifier == null) 8121 { 8122 wrapErr(0, WRAP_COLUMN, 8123 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG_IN_CSR.get( 8124 csr.getSignatureAlgorithmOID())); 8125 return ResultCode.PARAM_ERROR; 8126 } 8127 else 8128 { 8129 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 8130 } 8131 } 8132 8133 if (includeRequestedExtensions) 8134 { 8135 for (final X509CertificateExtension extension : csr.getExtensions()) 8136 { 8137 if ((extension instanceof AuthorityKeyIdentifierExtension) || 8138 (extension instanceof IssuerAlternativeNameExtension)) 8139 { 8140 // This extension applies to the issuer. We won't include this in 8141 // the set of inherited extensions. 8142 } 8143 else if (extension instanceof SubjectKeyIdentifierExtension) 8144 { 8145 // The generated certificate will automatically include a subject 8146 // key identifier extension, so we don't need to include it. 8147 } 8148 else if (extension instanceof BasicConstraintsExtension) 8149 { 8150 // Don't override a value already provided on the command line. 8151 if (basicConstraints == null) 8152 { 8153 basicConstraints = (BasicConstraintsExtension) extension; 8154 extensionList.add(basicConstraints); 8155 } 8156 } 8157 else if (extension instanceof ExtendedKeyUsageExtension) 8158 { 8159 // Don't override a value already provided on the command line. 8160 if (extendedKeyUsage == null) 8161 { 8162 extendedKeyUsage = (ExtendedKeyUsageExtension) extension; 8163 extensionList.add(extendedKeyUsage); 8164 } 8165 } 8166 else if (extension instanceof KeyUsageExtension) 8167 { 8168 // Don't override a value already provided on the command line. 8169 if (keyUsage == null) 8170 { 8171 keyUsage = (KeyUsageExtension) extension; 8172 extensionList.add(keyUsage); 8173 } 8174 } 8175 else if (extension instanceof SubjectAlternativeNameExtension) 8176 { 8177 // Although we could merge values, it's safer to not do that if any 8178 // subject alternative name values were provided on the command 8179 // line. 8180 if (sanValues.isEmpty()) 8181 { 8182 final SubjectAlternativeNameExtension e = 8183 (SubjectAlternativeNameExtension) extension; 8184 for (final String dnsName : e.getDNSNames()) 8185 { 8186 sanBuilder.addDNSName(dnsName); 8187 sanValues.add("DNS:" + dnsName); 8188 } 8189 8190 for (final InetAddress ipAddress : e.getIPAddresses()) 8191 { 8192 sanBuilder.addIPAddress(ipAddress); 8193 sanValues.add("IP:" + ipAddress.getHostAddress()); 8194 } 8195 8196 for (final String emailAddress : e.getRFC822Names()) 8197 { 8198 sanBuilder.addRFC822Name(emailAddress); 8199 sanValues.add("EMAIL:" + emailAddress); 8200 } 8201 8202 for (final String uri : e.getUniformResourceIdentifiers()) 8203 { 8204 sanBuilder.addUniformResourceIdentifier(uri); 8205 sanValues.add("URI:" + uri); 8206 } 8207 8208 for (final OID oid : e.getRegisteredIDs()) 8209 { 8210 sanBuilder.addRegisteredID(oid); 8211 sanValues.add("OID:" + oid.toString()); 8212 } 8213 8214 try 8215 { 8216 extensionList.add( 8217 new SubjectAlternativeNameExtension(false, 8218 sanBuilder.build())); 8219 } 8220 catch (final Exception ex) 8221 { 8222 // This should never happen. 8223 Debug.debugException(ex); 8224 throw new RuntimeException(ex); 8225 } 8226 } 8227 } 8228 else 8229 { 8230 genericExtensions.add(extension); 8231 extensionList.add(extension); 8232 } 8233 } 8234 } 8235 } 8236 8237 8238 // Generate the keytool arguments to use to sign the requested certificate. 8239 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8240 keytoolArguments.add("-gencert"); 8241 keytoolArguments.add("-keystore"); 8242 keytoolArguments.add(keystorePath.getAbsolutePath()); 8243 keytoolArguments.add("-storetype"); 8244 keytoolArguments.add(keystoreType); 8245 keytoolArguments.add("-storepass"); 8246 keytoolArguments.add("*****REDACTED*****"); 8247 keytoolArguments.add("-keypass"); 8248 keytoolArguments.add("*****REDACTED*****"); 8249 keytoolArguments.add("-alias"); 8250 keytoolArguments.add(alias); 8251 keytoolArguments.add("-dname"); 8252 keytoolArguments.add(subjectDN.toString()); 8253 keytoolArguments.add("-sigalg"); 8254 keytoolArguments.add(signatureAlgorithmName); 8255 keytoolArguments.add("-validity"); 8256 keytoolArguments.add(String.valueOf(daysValid)); 8257 8258 if (validityStartTime != null) 8259 { 8260 keytoolArguments.add("-startdate"); 8261 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 8262 } 8263 8264 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 8265 extendedKeyUsage, sanValues, ianValues, genericExtensions); 8266 8267 keytoolArguments.add("-infile"); 8268 keytoolArguments.add(inputFile.getAbsolutePath()); 8269 8270 if (outputFile != null) 8271 { 8272 keytoolArguments.add("-outfile"); 8273 keytoolArguments.add(outputFile.getAbsolutePath()); 8274 } 8275 8276 if (outputPEM) 8277 { 8278 keytoolArguments.add("-rfc"); 8279 } 8280 8281 if (displayKeytoolCommand) 8282 { 8283 displayKeytoolCommand(keytoolArguments); 8284 } 8285 8286 8287 // Generate the signed certificate. 8288 final long notBefore; 8289 if (validityStartTime == null) 8290 { 8291 notBefore = System.currentTimeMillis(); 8292 } 8293 else 8294 { 8295 notBefore = validityStartTime.getTime(); 8296 } 8297 8298 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 8299 8300 final X509CertificateExtension[] extensions = 8301 new X509CertificateExtension[extensionList.size()]; 8302 extensionList.toArray(extensions); 8303 8304 final X509Certificate signedCertificate; 8305 try 8306 { 8307 signedCertificate = X509Certificate.generateIssuerSignedCertificate( 8308 signatureAlgorithmIdentifier, issuerCertificate, issuerPrivateKey, 8309 csr.getPublicKeyAlgorithmOID(), 8310 csr.getPublicKeyAlgorithmParameters(), csr.getEncodedPublicKey(), 8311 csr.getDecodedPublicKey(), subjectDN, notBefore, notAfter, 8312 extensions); 8313 } 8314 catch (final Exception e) 8315 { 8316 Debug.debugException(e); 8317 wrapErr(0, WRAP_COLUMN, 8318 ERR_MANAGE_CERTS_GEN_CERT_ERROR_SIGNING_CERT.get()); 8319 e.printStackTrace(getErr()); 8320 return ResultCode.LOCAL_ERROR; 8321 } 8322 8323 8324 // Write the signed certificate signing request to the appropriate location. 8325 try 8326 { 8327 final PrintStream ps; 8328 if (outputFile == null) 8329 { 8330 ps = getOut(); 8331 } 8332 else 8333 { 8334 ps = new PrintStream(outputFile); 8335 } 8336 8337 if (outputPEM) 8338 { 8339 writePEMCertificate(ps, signedCertificate.getX509CertificateBytes()); 8340 } 8341 else 8342 { 8343 ps.write(signedCertificate.getX509CertificateBytes()); 8344 } 8345 8346 if (outputFile != null) 8347 { 8348 ps.close(); 8349 } 8350 } 8351 catch (final Exception e) 8352 { 8353 Debug.debugException(e); 8354 wrapErr(0, WRAP_COLUMN, 8355 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_SIGNED_CERT.get()); 8356 e.printStackTrace(getErr()); 8357 return ResultCode.LOCAL_ERROR; 8358 } 8359 8360 8361 // If the certificate signing request was written to an output file, 8362 // then let the user know that it was successful. If it was written to 8363 // standard output, then we don't need to tell them because they'll be 8364 // able to see it. 8365 if (outputFile != null) 8366 { 8367 out(); 8368 wrapOut(0, WRAP_COLUMN, 8369 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_SIGNED_CERT.get( 8370 outputFile.getAbsolutePath())); 8371 } 8372 8373 return ResultCode.SUCCESS; 8374 } 8375 8376 8377 8378 /** 8379 * Performs the necessary processing for the change-certificate-alias 8380 * subcommand. 8381 * 8382 * @return A result code that indicates whether the processing completed 8383 * successfully. 8384 */ 8385 @NotNull() 8386 private ResultCode doChangeCertificateAlias() 8387 { 8388 // Get the values of a number of configured arguments. 8389 final StringArgument currentAliasArgument = 8390 subCommandParser.getStringArgument("current-alias"); 8391 final String currentAlias = currentAliasArgument.getValue(); 8392 8393 final StringArgument newAliasArgument = 8394 subCommandParser.getStringArgument("new-alias"); 8395 final String newAlias = newAliasArgument.getValue(); 8396 8397 final String keystoreType; 8398 final File keystorePath = getKeystorePath(); 8399 try 8400 { 8401 keystoreType = inferKeystoreType(keystorePath); 8402 } 8403 catch (final LDAPException le) 8404 { 8405 Debug.debugException(le); 8406 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8407 return le.getResultCode(); 8408 } 8409 8410 final char[] keystorePassword; 8411 try 8412 { 8413 keystorePassword = getKeystorePassword(keystorePath); 8414 } 8415 catch (final LDAPException le) 8416 { 8417 Debug.debugException(le); 8418 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8419 return le.getResultCode(); 8420 } 8421 8422 8423 // Get the keystore. 8424 final KeyStore keystore; 8425 try 8426 { 8427 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 8428 } 8429 catch (final LDAPException le) 8430 { 8431 Debug.debugException(le); 8432 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8433 return le.getResultCode(); 8434 } 8435 8436 8437 // See if we need to use a private key password that is different from the 8438 // keystore password. 8439 final char[] privateKeyPassword; 8440 try 8441 { 8442 privateKeyPassword = 8443 getPrivateKeyPassword(keystore, currentAlias, keystorePassword); 8444 } 8445 catch (final LDAPException le) 8446 { 8447 Debug.debugException(le); 8448 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8449 return le.getResultCode(); 8450 } 8451 8452 8453 // Make sure that the keystore has an existing entry with the current alias. 8454 // It must be either a certificate entry or a private key entry. 8455 final Certificate existingCertificate; 8456 final Certificate[] existingCertificateChain; 8457 final PrivateKey existingPrivateKey; 8458 try 8459 { 8460 if (hasCertificateAlias(keystore, currentAlias)) 8461 { 8462 existingCertificate = keystore.getCertificate(currentAlias); 8463 existingCertificateChain = null; 8464 existingPrivateKey = null; 8465 } 8466 else if (hasKeyAlias(keystore, currentAlias)) 8467 { 8468 existingCertificateChain = keystore.getCertificateChain(currentAlias); 8469 existingPrivateKey = 8470 (PrivateKey) keystore.getKey(currentAlias, privateKeyPassword); 8471 existingCertificate = null; 8472 } 8473 else 8474 { 8475 wrapErr(0, WRAP_COLUMN, 8476 ERR_MANAGE_CERTS_CHANGE_ALIAS_NO_SUCH_ALIAS.get(currentAlias)); 8477 return ResultCode.PARAM_ERROR; 8478 } 8479 } 8480 catch (final Exception e) 8481 { 8482 Debug.debugException(e); 8483 wrapErr(0, WRAP_COLUMN, 8484 ERR_MANAGE_CERTS_CHANGE_ALIAS_CANNOT_GET_EXISTING_ENTRY.get( 8485 currentAlias)); 8486 e.printStackTrace(getErr()); 8487 return ResultCode.LOCAL_ERROR; 8488 } 8489 8490 8491 // Make sure that the keystore does not have an entry with the new alias. 8492 if (hasCertificateAlias(keystore, newAlias) || 8493 hasKeyAlias(keystore, newAlias)) 8494 { 8495 wrapErr(0, WRAP_COLUMN, 8496 ERR_MANAGE_CERTS_CHANGE_ALIAS_NEW_ALIAS_IN_USE.get(newAlias)); 8497 return ResultCode.PARAM_ERROR; 8498 } 8499 8500 8501 // Generate the keytool arguments to use to change the certificate alias. 8502 final BooleanArgument displayKeytoolCommandArgument = 8503 subCommandParser.getBooleanArgument("display-keytool-command"); 8504 if ((displayKeytoolCommandArgument != null) && 8505 displayKeytoolCommandArgument.isPresent()) 8506 { 8507 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8508 keytoolArguments.add("-changealias"); 8509 keytoolArguments.add("-keystore"); 8510 keytoolArguments.add(keystorePath.getAbsolutePath()); 8511 keytoolArguments.add("-storetype"); 8512 keytoolArguments.add(keystoreType); 8513 keytoolArguments.add("-storepass"); 8514 keytoolArguments.add("*****REDACTED*****"); 8515 keytoolArguments.add("-keypass"); 8516 keytoolArguments.add("*****REDACTED*****"); 8517 keytoolArguments.add("-alias"); 8518 keytoolArguments.add(currentAlias); 8519 keytoolArguments.add("-destalias"); 8520 keytoolArguments.add(newAlias); 8521 8522 displayKeytoolCommand(keytoolArguments); 8523 } 8524 8525 8526 // Update the keystore to remove the entry with the current alias and 8527 // re-write it with the new alias. 8528 try 8529 { 8530 keystore.deleteEntry(currentAlias); 8531 if (existingCertificate != null) 8532 { 8533 keystore.setCertificateEntry(newAlias, existingCertificate); 8534 } 8535 else 8536 { 8537 keystore.setKeyEntry(newAlias, existingPrivateKey, 8538 privateKeyPassword, existingCertificateChain); 8539 } 8540 8541 writeKeystore(keystore, keystorePath, keystorePassword); 8542 } 8543 catch (final Exception e) 8544 { 8545 Debug.debugException(e); 8546 wrapErr(0, WRAP_COLUMN, 8547 ERR_MANAGE_CERTS_CHANGE_ALIAS_CANNOT_UPDATE_KEYSTORE.get()); 8548 e.printStackTrace(getErr()); 8549 return ResultCode.LOCAL_ERROR; 8550 } 8551 8552 wrapOut(0, WRAP_COLUMN, 8553 INFO_MANAGE_CERTS_CHANGE_ALIAS_SUCCESSFUL.get(currentAlias, 8554 newAlias)); 8555 return ResultCode.SUCCESS; 8556 } 8557 8558 8559 8560 /** 8561 * Performs the necessary processing for the change-keystore-password 8562 * subcommand. 8563 * 8564 * @return A result code that indicates whether the processing completed 8565 * successfully. 8566 */ 8567 @NotNull() 8568 private ResultCode doChangeKeystorePassword() 8569 { 8570 // Get the values of a number of configured arguments. 8571 final String keystoreType; 8572 final File keystorePath = getKeystorePath(); 8573 try 8574 { 8575 keystoreType = inferKeystoreType(keystorePath); 8576 } 8577 catch (final LDAPException le) 8578 { 8579 Debug.debugException(le); 8580 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8581 return le.getResultCode(); 8582 } 8583 8584 final char[] currentKeystorePassword; 8585 try 8586 { 8587 currentKeystorePassword = getKeystorePassword(keystorePath, "current"); 8588 } 8589 catch (final LDAPException le) 8590 { 8591 Debug.debugException(le); 8592 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8593 return le.getResultCode(); 8594 } 8595 8596 final char[] newKeystorePassword; 8597 try 8598 { 8599 newKeystorePassword = getKeystorePassword(keystorePath, "new"); 8600 } 8601 catch (final LDAPException le) 8602 { 8603 Debug.debugException(le); 8604 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8605 return le.getResultCode(); 8606 } 8607 8608 8609 // Get the keystore. 8610 final KeyStore keystore; 8611 try 8612 { 8613 keystore = getKeystore(keystoreType, keystorePath, 8614 currentKeystorePassword); 8615 } 8616 catch (final LDAPException le) 8617 { 8618 Debug.debugException(le); 8619 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8620 return le.getResultCode(); 8621 } 8622 8623 8624 // Generate the keytool arguments to use to change the keystore password. 8625 final BooleanArgument displayKeytoolCommandArgument = 8626 subCommandParser.getBooleanArgument("display-keytool-command"); 8627 if ((displayKeytoolCommandArgument != null) && 8628 displayKeytoolCommandArgument.isPresent()) 8629 { 8630 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8631 keytoolArguments.add("-storepasswd"); 8632 keytoolArguments.add("-keystore"); 8633 keytoolArguments.add(keystorePath.getAbsolutePath()); 8634 keytoolArguments.add("-storetype"); 8635 keytoolArguments.add(keystoreType); 8636 keytoolArguments.add("-storepass"); 8637 keytoolArguments.add("*****REDACTED*****"); 8638 keytoolArguments.add("-new"); 8639 keytoolArguments.add("*****REDACTED*****"); 8640 8641 displayKeytoolCommand(keytoolArguments); 8642 } 8643 8644 8645 // Rewrite the keystore with the new password. 8646 try 8647 { 8648 writeKeystore(keystore, keystorePath, newKeystorePassword); 8649 } 8650 catch (final LDAPException le) 8651 { 8652 Debug.debugException(le); 8653 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8654 return le.getResultCode(); 8655 } 8656 8657 wrapOut(0, WRAP_COLUMN, 8658 INFO_MANAGE_CERTS_CHANGE_KS_PW_SUCCESSFUL.get( 8659 keystorePath.getAbsolutePath())); 8660 return ResultCode.SUCCESS; 8661 } 8662 8663 8664 8665 /** 8666 * Performs the necessary processing for the change-private-key-password 8667 * subcommand. 8668 * 8669 * @return A result code that indicates whether the processing completed 8670 * successfully. 8671 */ 8672 @NotNull() 8673 private ResultCode doChangePrivateKeyPassword() 8674 { 8675 // Get the values of a number of configured arguments. 8676 final StringArgument aliasArgument = 8677 subCommandParser.getStringArgument("alias"); 8678 final String alias = aliasArgument.getValue(); 8679 8680 final String keystoreType; 8681 final File keystorePath = getKeystorePath(); 8682 try 8683 { 8684 keystoreType = inferKeystoreType(keystorePath); 8685 } 8686 catch (final LDAPException le) 8687 { 8688 Debug.debugException(le); 8689 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8690 return le.getResultCode(); 8691 } 8692 8693 final char[] keystorePassword; 8694 try 8695 { 8696 keystorePassword = getKeystorePassword(keystorePath); 8697 } 8698 catch (final LDAPException le) 8699 { 8700 Debug.debugException(le); 8701 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8702 return le.getResultCode(); 8703 } 8704 8705 8706 // Get the keystore. 8707 final KeyStore keystore; 8708 try 8709 { 8710 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 8711 } 8712 catch (final LDAPException le) 8713 { 8714 Debug.debugException(le); 8715 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8716 return le.getResultCode(); 8717 } 8718 8719 8720 // Make sure that the keystore has a key entry with the specified alias. 8721 if (hasCertificateAlias(keystore, alias)) 8722 { 8723 wrapErr(0, WRAP_COLUMN, 8724 ERR_MANAGE_CERTS_CHANGE_PK_PW_ALIAS_IS_CERT.get(alias)); 8725 return ResultCode.PARAM_ERROR; 8726 } 8727 else if (! hasKeyAlias(keystore, alias)) 8728 { 8729 wrapErr(0, WRAP_COLUMN, 8730 ERR_MANAGE_CERTS_CHANGE_PK_PW_NO_SUCH_ALIAS.get(alias)); 8731 return ResultCode.PARAM_ERROR; 8732 } 8733 8734 8735 // Get the current and new private key passwords. 8736 final char[] currentPrivateKeyPassword; 8737 try 8738 { 8739 currentPrivateKeyPassword = 8740 getPrivateKeyPassword(keystore, alias, "current", keystorePassword); 8741 } 8742 catch (final LDAPException le) 8743 { 8744 Debug.debugException(le); 8745 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8746 return le.getResultCode(); 8747 } 8748 8749 final char[] newPrivateKeyPassword; 8750 try 8751 { 8752 newPrivateKeyPassword = 8753 getPrivateKeyPassword(keystore, alias, "new", keystorePassword); 8754 } 8755 catch (final LDAPException le) 8756 { 8757 Debug.debugException(le); 8758 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8759 return le.getResultCode(); 8760 } 8761 8762 8763 // Generate the keytool arguments to use to change the private key. 8764 final BooleanArgument displayKeytoolCommandArgument = 8765 subCommandParser.getBooleanArgument("display-keytool-command"); 8766 if ((displayKeytoolCommandArgument != null) && 8767 displayKeytoolCommandArgument.isPresent()) 8768 { 8769 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8770 keytoolArguments.add("-keypasswd"); 8771 keytoolArguments.add("-keystore"); 8772 keytoolArguments.add(keystorePath.getAbsolutePath()); 8773 keytoolArguments.add("-storetype"); 8774 keytoolArguments.add(keystoreType); 8775 keytoolArguments.add("-storepass"); 8776 keytoolArguments.add("*****REDACTED*****"); 8777 keytoolArguments.add("-alias"); 8778 keytoolArguments.add(alias); 8779 keytoolArguments.add("-keypass"); 8780 keytoolArguments.add("*****REDACTED*****"); 8781 keytoolArguments.add("-new"); 8782 keytoolArguments.add("*****REDACTED*****"); 8783 8784 displayKeytoolCommand(keytoolArguments); 8785 } 8786 8787 8788 // Get the contents of the private key entry. 8789 final Certificate[] chain; 8790 final PrivateKey privateKey; 8791 try 8792 { 8793 chain = keystore.getCertificateChain(alias); 8794 privateKey = 8795 (PrivateKey) keystore.getKey(alias, currentPrivateKeyPassword); 8796 } 8797 catch (final UnrecoverableKeyException e) 8798 { 8799 Debug.debugException(e); 8800 wrapErr(0, WRAP_COLUMN, 8801 ERR_MANAGE_CERTS_CHANGE_PK_PW_WRONG_PK_PW.get(alias)); 8802 return ResultCode.PARAM_ERROR; 8803 } 8804 catch (final Exception e) 8805 { 8806 Debug.debugException(e); 8807 wrapErr(0, WRAP_COLUMN, 8808 ERR_MANAGE_CERTS_CHANGE_PK_PW_CANNOT_GET_PK.get(alias)); 8809 e.printStackTrace(getErr()); 8810 return ResultCode.LOCAL_ERROR; 8811 } 8812 8813 8814 // Remove the existing key entry and re-add it with the new password. 8815 try 8816 { 8817 keystore.deleteEntry(alias); 8818 keystore.setKeyEntry(alias, privateKey, newPrivateKeyPassword, chain); 8819 writeKeystore(keystore, keystorePath, keystorePassword); 8820 } 8821 catch (final Exception e) 8822 { 8823 Debug.debugException(e); 8824 wrapErr(0, WRAP_COLUMN, 8825 ERR_MANAGE_CERTS_CHANGE_PK_PW_CANNOT_UPDATE_KS.get()); 8826 e.printStackTrace(getErr()); 8827 return ResultCode.LOCAL_ERROR; 8828 } 8829 8830 wrapOut(0, WRAP_COLUMN, 8831 INFO_MANAGE_CERTS_CHANGE_PK_PW_SUCCESSFUL.get(alias)); 8832 return ResultCode.SUCCESS; 8833 } 8834 8835 8836 8837 /** 8838 * Performs the necessary processing for the copy-keystore subcommand. 8839 * 8840 * @return A result code that indicates whether the processing completed 8841 * successfully. 8842 */ 8843 @NotNull() 8844 private ResultCode doCopyKeystore() 8845 { 8846 // Get the source key store. 8847 final String sourceKeyStoreType; 8848 final File sourceKeyStorePath = getKeystorePath("source-keystore"); 8849 try 8850 { 8851 sourceKeyStoreType = inferKeystoreType(sourceKeyStorePath, "source"); 8852 } 8853 catch (final LDAPException le) 8854 { 8855 Debug.debugException(le); 8856 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8857 return le.getResultCode(); 8858 } 8859 8860 final char[] sourceKeyStorePassword; 8861 try 8862 { 8863 sourceKeyStorePassword = 8864 getKeystorePassword(sourceKeyStorePath, "source"); 8865 } 8866 catch (final LDAPException le) 8867 { 8868 Debug.debugException(le); 8869 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8870 return le.getResultCode(); 8871 } 8872 8873 final KeyStore sourceKeyStore; 8874 try 8875 { 8876 sourceKeyStore = getKeystore(sourceKeyStoreType, sourceKeyStorePath, 8877 sourceKeyStorePassword); 8878 } 8879 catch (final LDAPException le) 8880 { 8881 Debug.debugException(le); 8882 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8883 return le.getResultCode(); 8884 } 8885 8886 8887 // Get the destination key store. 8888 final String destinationKeyStoreType; 8889 final File destinationKeyStorePath = 8890 getKeystorePath("destination-keystore"); 8891 try 8892 { 8893 destinationKeyStoreType = inferKeystoreType(destinationKeyStorePath, 8894 "destination"); 8895 } 8896 catch (final LDAPException le) 8897 { 8898 Debug.debugException(le); 8899 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8900 return le.getResultCode(); 8901 } 8902 8903 final boolean destinationExists = destinationKeyStorePath.exists(); 8904 8905 char[] destinationKeyStorePassword; 8906 try 8907 { 8908 destinationKeyStorePassword = 8909 getKeystorePassword(destinationKeyStorePath, "destination"); 8910 if (destinationKeyStorePassword == null) 8911 { 8912 destinationKeyStorePassword = sourceKeyStorePassword; 8913 } 8914 } 8915 catch (final LDAPException le) 8916 { 8917 Debug.debugException(le); 8918 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8919 return le.getResultCode(); 8920 } 8921 8922 final KeyStore destinationKeyStore; 8923 try 8924 { 8925 destinationKeyStore = getKeystore(destinationKeyStoreType, 8926 destinationKeyStorePath, destinationKeyStorePassword); 8927 } 8928 catch (final LDAPException le) 8929 { 8930 Debug.debugException(le); 8931 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8932 return le.getResultCode(); 8933 } 8934 8935 8936 // Get the value of the aliases argument, if it was provided. 8937 final Set<String> aliases = new LinkedHashSet<>(); 8938 try 8939 { 8940 final StringArgument aliasArg = 8941 subCommandParser.getStringArgument("alias"); 8942 if ((aliasArg != null) && aliasArg.isPresent()) 8943 { 8944 for (final String alias : aliasArg.getValues()) 8945 { 8946 aliases.add(alias); 8947 if (! sourceKeyStore.containsAlias(alias)) 8948 { 8949 wrapErr(0, WRAP_COLUMN, 8950 ERR_MANAGE_CERTS_COPY_KS_NO_SUCH_SOURCE_ALIAS.get( 8951 sourceKeyStorePath.getAbsolutePath(), alias)); 8952 return ResultCode.PARAM_ERROR; 8953 } 8954 } 8955 } 8956 else 8957 { 8958 final Enumeration<String> sourceAliases = sourceKeyStore.aliases(); 8959 while (sourceAliases.hasMoreElements()) 8960 { 8961 aliases.add(sourceAliases.nextElement()); 8962 } 8963 } 8964 } 8965 catch (final Exception e) 8966 { 8967 Debug.debugException(e); 8968 wrapErr(0, WRAP_COLUMN, 8969 ERR_MANAGE_CERTS_COPY_KS_CANNOT_GET_SOURCE_ALIASES.get( 8970 sourceKeyStorePath.getAbsolutePath(), 8971 StaticUtils.getExceptionMessage(e))); 8972 return ResultCode.LOCAL_ERROR; 8973 } 8974 8975 8976 // If the set of aliases is empty and the destination key store already 8977 // exists, then exit without doing anything. 8978 if (aliases.isEmpty() && destinationExists) 8979 { 8980 wrapOut(0, WRAP_COLUMN, 8981 INFO_MANAGE_CERTS_COPY_KS_NO_CERTS_COPIED_EXISTING_KS.get( 8982 sourceKeyStorePath.getAbsolutePath(), 8983 destinationKeyStorePath.getAbsolutePath())); 8984 return ResultCode.SUCCESS; 8985 } 8986 8987 8988 // Make sure that none of the target aliases exist in the destination key 8989 // store. 8990 for (final String alias : aliases) 8991 { 8992 try 8993 { 8994 if (destinationKeyStore.containsAlias(alias)) 8995 { 8996 wrapErr(0, WRAP_COLUMN, 8997 ERR_MANAGE_CERTS_COPY_KS_CONFLICTING_ALIAS.get(alias, 8998 destinationKeyStorePath.getAbsolutePath(), 8999 subCommandParser.getCommandName())); 9000 return ResultCode.CONSTRAINT_VIOLATION; 9001 } 9002 } 9003 catch (final Exception e) 9004 { 9005 Debug.debugException(e); 9006 wrapErr(0, WRAP_COLUMN, 9007 ERR_MANAGE_CERTS_COPY_KS_CANNOT_CHECK_DEST_ALIAS.get(alias, 9008 destinationKeyStorePath.getAbsolutePath(), 9009 StaticUtils.getExceptionMessage(e))); 9010 return ResultCode.LOCAL_ERROR; 9011 } 9012 } 9013 9014 9015 // Copy each of the targeted entries from the source key store into the 9016 // destination key store. 9017 char[] sourcePrivateKeyPassword = null; 9018 char[] destinationPrivateKeyPassword = null; 9019 for (final String alias : aliases) 9020 { 9021 try 9022 { 9023 if (sourceKeyStore.isCertificateEntry(alias)) 9024 { 9025 final Certificate certificate = sourceKeyStore.getCertificate(alias); 9026 destinationKeyStore.setCertificateEntry(alias, certificate); 9027 } 9028 else 9029 { 9030 if (sourcePrivateKeyPassword == null) 9031 { 9032 sourcePrivateKeyPassword = getPrivateKeyPassword(sourceKeyStore, 9033 alias, "source", sourceKeyStorePassword); 9034 } 9035 9036 if (destinationPrivateKeyPassword == null) 9037 { 9038 destinationPrivateKeyPassword = getPrivateKeyPassword( 9039 destinationKeyStore, alias, "destination", 9040 destinationKeyStorePassword); 9041 } 9042 9043 final Certificate[] chain = sourceKeyStore.getCertificateChain(alias); 9044 final Key key = 9045 sourceKeyStore.getKey(alias, sourcePrivateKeyPassword); 9046 destinationKeyStore.setKeyEntry(alias, key, 9047 destinationPrivateKeyPassword, chain); 9048 } 9049 } 9050 catch (final Exception e) 9051 { 9052 Debug.debugException(e); 9053 wrapErr(0, WRAP_COLUMN, 9054 ERR_MANAGE_CERTS_COPY_KS_ERROR_COPYING_ENTRY.get(alias, 9055 sourceKeyStorePath.getAbsolutePath(), 9056 destinationKeyStorePath.getAbsolutePath(), 9057 StaticUtils.getExceptionMessage(e))); 9058 return ResultCode.LOCAL_ERROR; 9059 } 9060 } 9061 9062 9063 // Rewrite the destination keystore. 9064 try 9065 { 9066 writeKeystore(destinationKeyStore, destinationKeyStorePath, 9067 destinationKeyStorePassword); 9068 } 9069 catch (final LDAPException le) 9070 { 9071 Debug.debugException(le); 9072 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9073 return le.getResultCode(); 9074 } 9075 9076 if (aliases.isEmpty()) 9077 { 9078 // This should only happen if the alias argument was not provided, the 9079 // source key store is empty, and the destination key store doesn't exist. 9080 // In that case, the destination key store will have been created. 9081 wrapOut(0, WRAP_COLUMN, 9082 INFO_MANAGE_CERTS_COPY_KS_NO_CERTS_COPIED_KS_CREATED.get( 9083 sourceKeyStorePath.getAbsolutePath(), 9084 destinationKeyStoreType, 9085 destinationKeyStorePath.getAbsolutePath())); 9086 } 9087 else 9088 { 9089 // Write a message about the entries that were successfully copied. 9090 wrapOut(0, WRAP_COLUMN, 9091 INFO_MANAGE_CERTS_COPY_KS_CERTS_COPIED_HEADER.get( 9092 sourceKeyStorePath.getAbsolutePath(), 9093 destinationKeyStoreType, 9094 destinationKeyStorePath.getAbsolutePath())); 9095 for (final String alias : aliases) 9096 { 9097 out("* ", alias); 9098 } 9099 } 9100 9101 return ResultCode.SUCCESS; 9102 } 9103 9104 9105 9106 /** 9107 * Performs the necessary processing for the retrieve-server-certificate 9108 * subcommand. 9109 * 9110 * @return A result code that indicates whether the processing completed 9111 * successfully. 9112 */ 9113 @NotNull() 9114 private ResultCode doRetrieveServerCertificate() 9115 { 9116 // Get the values of a number of configured arguments. 9117 final StringArgument hostnameArgument = 9118 subCommandParser.getStringArgument("hostname"); 9119 final String hostname = hostnameArgument.getValue(); 9120 9121 final IntegerArgument portArgument = 9122 subCommandParser.getIntegerArgument("port"); 9123 final int port = portArgument.getValue(); 9124 9125 final BooleanArgument useLDAPStartTLSArgument = 9126 subCommandParser.getBooleanArgument("use-ldap-start-tls"); 9127 final boolean useLDAPStartTLS = 9128 ((useLDAPStartTLSArgument != null) && 9129 useLDAPStartTLSArgument.isPresent()); 9130 9131 final BooleanArgument onlyPeerArgument = 9132 subCommandParser.getBooleanArgument("only-peer-certificate"); 9133 final boolean onlyPeer = 9134 ((onlyPeerArgument != null) && onlyPeerArgument.isPresent()); 9135 9136 final BooleanArgument verboseArgument = 9137 subCommandParser.getBooleanArgument("verbose"); 9138 final boolean verbose = 9139 ((verboseArgument != null) && verboseArgument.isPresent()); 9140 9141 boolean outputPEM = true; 9142 final StringArgument outputFormatArgument = 9143 subCommandParser.getStringArgument("output-format"); 9144 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 9145 { 9146 final String format = outputFormatArgument.getValue().toLowerCase(); 9147 if (format.equals("der") || format.equals("binary") || 9148 format.equals("bin")) 9149 { 9150 outputPEM = false; 9151 } 9152 } 9153 9154 File outputFile = null; 9155 final FileArgument outputFileArgument = 9156 subCommandParser.getFileArgument("output-file"); 9157 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 9158 { 9159 outputFile = outputFileArgument.getValue(); 9160 } 9161 9162 9163 // Spawn a background thread to establish a connection and get the 9164 // certificate chain from the target server. 9165 final LinkedBlockingQueue<Object> responseQueue = 9166 new LinkedBlockingQueue<>(10); 9167 final ManageCertificatesServerCertificateCollector certificateCollector = 9168 new ManageCertificatesServerCertificateCollector(this, hostname, port, 9169 useLDAPStartTLS, verbose, responseQueue); 9170 certificateCollector.start(); 9171 9172 Object responseObject = 9173 ERR_MANAGE_CERTS_RETRIEVE_CERT_NO_CERT_CHAIN_RECEIVED.get( 9174 hostname + ':' + port); 9175 try 9176 { 9177 responseObject = responseQueue.poll(90L, TimeUnit.SECONDS); 9178 } 9179 catch (final Exception e) 9180 { 9181 Debug.debugException(e); 9182 } 9183 9184 final X509Certificate[] chain; 9185 if (responseObject instanceof X509Certificate[]) 9186 { 9187 chain = (X509Certificate[]) responseObject; 9188 if (chain.length == 0) 9189 { 9190 wrapErr(0, WRAP_COLUMN, 9191 ERR_MANAGE_CERTS_RETRIEVE_CERT_EMPTY_CHAIN.get()); 9192 return ResultCode.NO_RESULTS_RETURNED; 9193 } 9194 } 9195 else if (responseObject instanceof CertException) 9196 { 9197 // The error message will have already been recorded by the collector 9198 // thread, so we can just return a non-success result. 9199 return ResultCode.LOCAL_ERROR; 9200 } 9201 else 9202 { 9203 wrapErr(0, WRAP_COLUMN, String.valueOf(responseObject)); 9204 return ResultCode.LOCAL_ERROR; 9205 } 9206 9207 try 9208 { 9209 certificateCollector.join(10_000L); 9210 } 9211 catch (final Exception e) 9212 { 9213 Debug.debugException(e); 9214 } 9215 9216 9217 // If the certificates should be written to a file, then do that now. 9218 if (outputFile != null) 9219 { 9220 try (PrintStream s = new PrintStream(outputFile)) 9221 { 9222 for (final X509Certificate c : chain) 9223 { 9224 if (outputPEM) 9225 { 9226 writePEMCertificate(s, c.getX509CertificateBytes()); 9227 } 9228 else 9229 { 9230 s.write(c.getX509CertificateBytes()); 9231 } 9232 9233 if (onlyPeer) 9234 { 9235 break; 9236 } 9237 } 9238 } 9239 catch (final Exception e) 9240 { 9241 Debug.debugException(e); 9242 wrapErr(0, WRAP_COLUMN, 9243 ERR_MANAGE_CERTS_RETRIEVE_CERT_CANNOT_WRITE_TO_FILE.get( 9244 outputFile.getAbsolutePath(), 9245 StaticUtils.getExceptionMessage(e))); 9246 return ResultCode.LOCAL_ERROR; 9247 } 9248 } 9249 9250 9251 // Display information about the certificates. 9252 for (int i=0; i < chain.length; i++) 9253 { 9254 if (verbose || (i > 0)) 9255 { 9256 out(); 9257 out(); 9258 } 9259 9260 if ((! onlyPeer) && (chain.length > 1)) 9261 { 9262 wrapOut(0, WRAP_COLUMN, 9263 INFO_MANAGE_CERTS_RETRIEVE_CERT_DISPLAY_HEADER.get((i+1), 9264 chain.length)); 9265 out(); 9266 } 9267 9268 final X509Certificate c = chain[i]; 9269 writePEMCertificate(getOut(), c.getX509CertificateBytes()); 9270 out(); 9271 printCertificate(c, "", verbose); 9272 9273 if (onlyPeer) 9274 { 9275 break; 9276 } 9277 } 9278 9279 return ResultCode.SUCCESS; 9280 } 9281 9282 9283 9284 /** 9285 * Performs the necessary processing for the trust-server-certificate 9286 * subcommand. 9287 * 9288 * @return A result code that indicates whether the processing completed 9289 * successfully. 9290 */ 9291 @NotNull() 9292 private ResultCode doTrustServerCertificate() 9293 { 9294 // Get the values of a number of configured arguments. 9295 final StringArgument hostnameArgument = 9296 subCommandParser.getStringArgument("hostname"); 9297 final String hostname = hostnameArgument.getValue(); 9298 9299 final IntegerArgument portArgument = 9300 subCommandParser.getIntegerArgument("port"); 9301 final int port = portArgument.getValue(); 9302 9303 final String alias; 9304 final StringArgument aliasArgument = 9305 subCommandParser.getStringArgument("alias"); 9306 if ((aliasArgument != null) && aliasArgument.isPresent()) 9307 { 9308 alias = aliasArgument.getValue(); 9309 } 9310 else 9311 { 9312 alias = hostname + ':' + port; 9313 } 9314 9315 final BooleanArgument useLDAPStartTLSArgument = 9316 subCommandParser.getBooleanArgument("use-ldap-start-tls"); 9317 final boolean useLDAPStartTLS = 9318 ((useLDAPStartTLSArgument != null) && 9319 useLDAPStartTLSArgument.isPresent()); 9320 9321 final BooleanArgument issuersOnlyArgument = 9322 subCommandParser.getBooleanArgument("issuers-only"); 9323 final boolean issuersOnly = 9324 ((issuersOnlyArgument != null) && issuersOnlyArgument.isPresent()); 9325 9326 final BooleanArgument noPromptArgument = 9327 subCommandParser.getBooleanArgument("no-prompt"); 9328 final boolean noPrompt = 9329 ((noPromptArgument != null) && noPromptArgument.isPresent()); 9330 9331 final BooleanArgument verboseArgument = 9332 subCommandParser.getBooleanArgument("verbose"); 9333 final boolean verbose = 9334 ((verboseArgument != null) && verboseArgument.isPresent()); 9335 9336 final String keystoreType; 9337 final File keystorePath = getKeystorePath(); 9338 final boolean isNewKeystore = (! keystorePath.exists()); 9339 try 9340 { 9341 keystoreType = inferKeystoreType(keystorePath); 9342 } 9343 catch (final LDAPException le) 9344 { 9345 Debug.debugException(le); 9346 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9347 return le.getResultCode(); 9348 } 9349 9350 final char[] keystorePassword; 9351 try 9352 { 9353 keystorePassword = getKeystorePassword(keystorePath); 9354 } 9355 catch (final LDAPException le) 9356 { 9357 Debug.debugException(le); 9358 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9359 return le.getResultCode(); 9360 } 9361 9362 9363 // Get the keystore. 9364 final KeyStore keystore; 9365 try 9366 { 9367 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 9368 } 9369 catch (final LDAPException le) 9370 { 9371 Debug.debugException(le); 9372 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9373 return le.getResultCode(); 9374 } 9375 9376 9377 // Make sure that the specified alias is not already in use. 9378 if (hasCertificateAlias(keystore, alias) || 9379 hasKeyAlias(keystore, alias)) 9380 { 9381 wrapErr(0, WRAP_COLUMN, 9382 ERR_MANAGE_CERTS_TRUST_SERVER_ALIAS_IN_USE.get(alias)); 9383 return ResultCode.PARAM_ERROR; 9384 } 9385 9386 9387 // Spawn a background thread to establish a connection and get the 9388 // certificate chain from the target server. 9389 final LinkedBlockingQueue<Object> responseQueue = 9390 new LinkedBlockingQueue<>(10); 9391 final ManageCertificatesServerCertificateCollector certificateCollector = 9392 new ManageCertificatesServerCertificateCollector(this, hostname, port, 9393 useLDAPStartTLS, verbose, responseQueue); 9394 certificateCollector.start(); 9395 9396 Object responseObject = 9397 ERR_MANAGE_CERTS_TRUST_SERVER_NO_CERT_CHAIN_RECEIVED.get( 9398 hostname + ':' + port); 9399 try 9400 { 9401 responseObject = responseQueue.poll(90L, TimeUnit.SECONDS); 9402 } 9403 catch (final Exception e) 9404 { 9405 Debug.debugException(e); 9406 } 9407 9408 final X509Certificate[] chain; 9409 if (responseObject instanceof X509Certificate[]) 9410 { 9411 chain = (X509Certificate[]) responseObject; 9412 } 9413 else if (responseObject instanceof CertException) 9414 { 9415 // The error message will have already been recorded by the collector 9416 // thread, so we can just return a non-success result. 9417 return ResultCode.LOCAL_ERROR; 9418 } 9419 else 9420 { 9421 wrapErr(0, WRAP_COLUMN, String.valueOf(responseObject)); 9422 return ResultCode.LOCAL_ERROR; 9423 } 9424 9425 try 9426 { 9427 certificateCollector.join(10_000L); 9428 } 9429 catch (final Exception e) 9430 { 9431 Debug.debugException(e); 9432 } 9433 9434 9435 // If we should prompt the user about whether to trust the certificates, 9436 // then do so now. 9437 if (! noPrompt) 9438 { 9439 out(); 9440 wrapOut(0, WRAP_COLUMN, 9441 INFO_MANAGE_CERTS_TRUST_SERVER_RETRIEVED_CHAIN.get( 9442 hostname + ':' + port)); 9443 9444 boolean isFirst = true; 9445 for (final X509Certificate c : chain) 9446 { 9447 out(); 9448 9449 if (isFirst) 9450 { 9451 isFirst = false; 9452 if (issuersOnly && (chain.length > 1)) 9453 { 9454 wrapOut(0, WRAP_COLUMN, 9455 INFO_MANAGE_CERTS_TRUST_SERVER_NOTE_OMITTED.get()); 9456 out(); 9457 } 9458 } 9459 9460 printCertificate(c, "", verbose); 9461 } 9462 9463 out(); 9464 9465 try 9466 { 9467 if (! promptForYesNo(INFO_MANAGE_CERTS_TRUST_SERVER_PROMPT_TRUST.get())) 9468 { 9469 wrapErr(0, WRAP_COLUMN, 9470 ERR_MANAGE_CERTS_TRUST_SERVER_CHAIN_REJECTED.get()); 9471 return ResultCode.USER_CANCELED; 9472 } 9473 } 9474 catch (final LDAPException le) 9475 { 9476 Debug.debugException(le); 9477 err(); 9478 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9479 return le.getResultCode(); 9480 } 9481 } 9482 9483 9484 // Add the certificates to the keystore. 9485 final LinkedHashMap<String,X509Certificate> certsByAlias = 9486 new LinkedHashMap<>(StaticUtils.computeMapCapacity(chain.length)); 9487 for (int i=0; i < chain.length; i++) 9488 { 9489 if (i == 0) 9490 { 9491 if (issuersOnly && (chain.length > 1)) 9492 { 9493 continue; 9494 } 9495 9496 certsByAlias.put(alias, chain[i]); 9497 } 9498 else if ((i == 1) && (chain.length == 2)) 9499 { 9500 certsByAlias.put(alias + "-issuer", chain[i]); 9501 } 9502 else 9503 { 9504 certsByAlias.put(alias + "-issuer-" + i, chain[i]); 9505 } 9506 } 9507 9508 for (final Map.Entry<String,X509Certificate> e : certsByAlias.entrySet()) 9509 { 9510 final String certAlias = e.getKey(); 9511 final X509Certificate cert = e.getValue(); 9512 9513 try 9514 { 9515 Validator.ensureFalse( 9516 (hasCertificateAlias(keystore, certAlias) || 9517 hasKeyAlias(keystore, certAlias)), 9518 "ERROR: Alias '" + certAlias + "' is already in use in the " + 9519 "keystore."); 9520 keystore.setCertificateEntry(certAlias, cert.toCertificate()); 9521 } 9522 catch (final Exception ex) 9523 { 9524 Debug.debugException(ex); 9525 wrapErr(0, WRAP_COLUMN, 9526 ERR_MANAGE_CERTS_TRUST_SERVER_ERROR_ADDING_CERT_TO_KS.get( 9527 cert.getSubjectDN())); 9528 ex.printStackTrace(getErr()); 9529 return ResultCode.LOCAL_ERROR; 9530 } 9531 } 9532 9533 9534 // Save the updated keystore. 9535 try 9536 { 9537 writeKeystore(keystore, keystorePath, keystorePassword); 9538 } 9539 catch (final LDAPException le) 9540 { 9541 Debug.debugException(le); 9542 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9543 return le.getResultCode(); 9544 } 9545 9546 if (isNewKeystore) 9547 { 9548 out(); 9549 wrapOut(0, WRAP_COLUMN, 9550 INFO_MANAGE_CERTS_TRUST_SERVER_CERT_CREATED_KEYSTORE.get( 9551 getUserFriendlyKeystoreType(keystoreType))); 9552 } 9553 9554 out(); 9555 if (certsByAlias.size() == 1) 9556 { 9557 wrapOut(0, WRAP_COLUMN, 9558 INFO_MANAGE_CERTS_TRUST_SERVER_ADDED_CERT_TO_KS.get()); 9559 } 9560 else 9561 { 9562 wrapOut(0, WRAP_COLUMN, 9563 INFO_MANAGE_CERTS_TRUST_SERVER_ADDED_CERTS_TO_KS.get( 9564 certsByAlias.size())); 9565 } 9566 9567 return ResultCode.SUCCESS; 9568 } 9569 9570 9571 9572 /** 9573 * Performs the necessary processing for the check-certificate-usability 9574 * subcommand. 9575 * 9576 * @return A result code that indicates whether the processing completed 9577 * successfully. 9578 */ 9579 @NotNull() 9580 private ResultCode doCheckCertificateUsability() 9581 { 9582 // Get the values of a number of configured arguments. 9583 final StringArgument aliasArgument = 9584 subCommandParser.getStringArgument("alias"); 9585 final String alias = aliasArgument.getValue(); 9586 9587 final String keystoreType; 9588 final File keystorePath = getKeystorePath(); 9589 try 9590 { 9591 keystoreType = inferKeystoreType(keystorePath); 9592 } 9593 catch (final LDAPException le) 9594 { 9595 Debug.debugException(le); 9596 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9597 return le.getResultCode(); 9598 } 9599 9600 final char[] keystorePassword; 9601 try 9602 { 9603 keystorePassword = getKeystorePassword(keystorePath); 9604 } 9605 catch (final LDAPException le) 9606 { 9607 Debug.debugException(le); 9608 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9609 return le.getResultCode(); 9610 } 9611 9612 9613 // Get the keystore. 9614 final KeyStore keystore; 9615 try 9616 { 9617 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 9618 } 9619 catch (final LDAPException le) 9620 { 9621 Debug.debugException(le); 9622 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9623 return le.getResultCode(); 9624 } 9625 9626 9627 // Make sure that the specified entry exists in the keystore and is 9628 // associated with a certificate chain and a private key. 9629 final X509Certificate[] chain; 9630 if (hasKeyAlias(keystore, alias)) 9631 { 9632 try 9633 { 9634 final Certificate[] genericChain = keystore.getCertificateChain(alias); 9635 Validator.ensureTrue((genericChain.length > 0), 9636 "ERROR: The keystore has a private key entry for alias '" + 9637 alias + "', but the associated certificate chain is empty."); 9638 9639 chain = new X509Certificate[genericChain.length]; 9640 for (int i=0; i < genericChain.length; i++) 9641 { 9642 chain[i] = new X509Certificate(genericChain[i].getEncoded()); 9643 } 9644 9645 out(); 9646 wrapOut(0, WRAP_COLUMN, 9647 INFO_MANAGE_CERTS_CHECK_USABILITY_GOT_CHAIN.get(alias)); 9648 9649 for (final X509Certificate c : chain) 9650 { 9651 out(); 9652 printCertificate(c, "", false); 9653 } 9654 } 9655 catch (final Exception e) 9656 { 9657 Debug.debugException(e); 9658 wrapErr(0, WRAP_COLUMN, 9659 ERR_MANAGE_CERTS_CHECK_USABILITY_CANNOT_GET_CHAIN.get(alias)); 9660 e.printStackTrace(getErr()); 9661 return ResultCode.LOCAL_ERROR; 9662 } 9663 } 9664 else if (hasCertificateAlias(keystore, alias)) 9665 { 9666 wrapErr(0, WRAP_COLUMN, 9667 ERR_MANAGE_CERTS_CHECK_USABILITY_NO_PRIVATE_KEY.get(alias)); 9668 return ResultCode.PARAM_ERROR; 9669 } 9670 else 9671 { 9672 wrapErr(0, WRAP_COLUMN, 9673 ERR_MANAGE_CERTS_CHECK_USABILITY_NO_SUCH_ALIAS.get(alias)); 9674 return ResultCode.PARAM_ERROR; 9675 } 9676 9677 9678 // Check to see if the certificate is self-signed. If so, then that's a 9679 // warning. If not, then make sure that the chain is complete and that each 9680 // subsequent certificate is the issuer of the previous. 9681 int numWarnings = 0; 9682 int numErrors = 0; 9683 if (chain[0].isSelfSigned()) 9684 { 9685 err(); 9686 wrapErr(0, WRAP_COLUMN, 9687 WARN_MANAGE_CERTS_CHECK_USABILITY_CERT_IS_SELF_SIGNED.get( 9688 chain[0].getSubjectDN())); 9689 numWarnings++; 9690 } 9691 else if ((chain.length == 1) || (! chain[chain.length - 1].isSelfSigned())) 9692 { 9693 err(); 9694 wrapErr(0, WRAP_COLUMN, 9695 ERR_MANAGE_CERTS_CHECK_USABILITY_END_OF_CHAIN_NOT_SELF_SIGNED.get( 9696 alias)); 9697 numErrors++; 9698 } 9699 else 9700 { 9701 boolean chainError = false; 9702 final StringBuilder nonMatchReason = new StringBuilder(); 9703 for (int i=1; i < chain.length; i++) 9704 { 9705 if (! chain[i].isIssuerFor(chain[i-1], nonMatchReason)) 9706 { 9707 err(); 9708 wrapErr(0, WRAP_COLUMN, 9709 ERR_MANAGE_CERTS_CHECK_USABILITY_CHAIN_ISSUER_MISMATCH.get( 9710 alias, chain[i].getSubjectDN(), chain[i-1].getSubjectDN(), 9711 nonMatchReason)); 9712 numErrors++; 9713 chainError = true; 9714 } 9715 } 9716 9717 if (! chainError) 9718 { 9719 out(); 9720 wrapOut(0, WRAP_COLUMN, 9721 INFO_MANAGE_CERTS_CHECK_USABILITY_CHAIN_COMPLETE.get()); 9722 } 9723 } 9724 9725 9726 // If there are multiple certificates in the chain, and if the last 9727 // certificate in the chain is self-signed, then check to see if it is 9728 // contained in the JVM-default trust manager. If it isn't, then we'll 9729 // display a notice, but we won't consider it a warning in and of itself. 9730 if ((chain.length > 1) && chain[chain.length-1].isSelfSigned()) 9731 { 9732 final X509Certificate caCert = chain[chain.length-1]; 9733 9734 try 9735 { 9736 final String jvmDefaultTrustStoreType = 9737 inferKeystoreType(JVM_DEFAULT_CACERTS_FILE); 9738 final KeyStore jvmDefaultTrustStore = 9739 CryptoHelper.getKeyStore(jvmDefaultTrustStoreType); 9740 try (FileInputStream inputStream = 9741 new FileInputStream(JVM_DEFAULT_CACERTS_FILE)) 9742 { 9743 jvmDefaultTrustStore.load(inputStream, null); 9744 } 9745 9746 boolean found = false; 9747 final Enumeration<String> aliases = jvmDefaultTrustStore.aliases(); 9748 while (aliases.hasMoreElements()) 9749 { 9750 final String jvmDefaultCertAlias = aliases.nextElement(); 9751 if (jvmDefaultTrustStore.isCertificateEntry(jvmDefaultCertAlias)) 9752 { 9753 final Certificate c = 9754 jvmDefaultTrustStore.getCertificate(jvmDefaultCertAlias); 9755 final X509Certificate xc = new X509Certificate(c.getEncoded()); 9756 if ((caCert.getSubjectDN().equals(xc.getSubjectDN())) && 9757 Arrays.equals(caCert.getSignatureValue().getBits(), 9758 xc.getSignatureValue().getBits())) 9759 { 9760 found = true; 9761 break; 9762 } 9763 } 9764 } 9765 9766 if (found) 9767 { 9768 out(); 9769 wrapOut(0, WRAP_COLUMN, 9770 INFO_MANAGE_CERTS_CHECK_USABILITY_CA_TRUSTED_OK.get( 9771 caCert.getSubjectDN())); 9772 } 9773 else 9774 { 9775 out(); 9776 wrapOut(0, WRAP_COLUMN, 9777 INFO_MANAGE_CERTS_CHECK_USABILITY_CA_NOT_IN_JVM_DEFAULT_TS.get( 9778 caCert.getSubjectDN())); 9779 } 9780 } 9781 catch (final Exception e) 9782 { 9783 Debug.debugException(e); 9784 err(); 9785 wrapErr(0, WRAP_COLUMN, 9786 WARN_MANAGE_CERTS_CHECK_USABILITY_CHECK_CA_IN_TS_ERROR.get( 9787 caCert.getSubjectDN(), StaticUtils.getExceptionMessage(e))); 9788 numWarnings++; 9789 } 9790 } 9791 9792 9793 // Make sure that the signature is valid for each certificate in the 9794 // chain. If any certificate has an invalid signature, then that's an 9795 // error. 9796 for (int i=0; i < chain.length; i++) 9797 { 9798 final X509Certificate c = chain[i]; 9799 9800 try 9801 { 9802 if (c.isSelfSigned()) 9803 { 9804 c.verifySignature(null); 9805 } 9806 else if ((i + 1) < chain.length) 9807 { 9808 c.verifySignature(chain[i+1]); 9809 } 9810 9811 out(); 9812 wrapOut(0, WRAP_COLUMN, 9813 INFO_MANAGE_CERTS_CHECK_USABILITY_CERT_SIGNATURE_VALID.get( 9814 c.getSubjectDN())); 9815 } 9816 catch (final CertException ce) 9817 { 9818 err(); 9819 wrapErr(0, WRAP_COLUMN, ce.getMessage()); 9820 numErrors++; 9821 } 9822 } 9823 9824 9825 // Check the validity window for each certificate in the chain. If any of 9826 // them is expired or not yet valid, then that's an error. If any of them 9827 // will expire in the near future, then that's a warning. 9828 final long currentTime = System.currentTimeMillis(); 9829 final long thirtyDaysFromNow = 9830 currentTime + (30L * 24L * 60L * 60L * 1000L); 9831 for (int i=0; i < chain.length; i++) 9832 { 9833 final X509Certificate c = chain[i]; 9834 if (c.getNotBeforeTime() > currentTime) 9835 { 9836 err(); 9837 if (i == 0) 9838 { 9839 wrapErr(0, WRAP_COLUMN, 9840 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_NOT_YET_VALID.get( 9841 c.getSubjectDN(), formatDateAndTime(c.getNotBeforeDate()))); 9842 } 9843 else 9844 { 9845 wrapErr(0, WRAP_COLUMN, 9846 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_NOT_YET_VALID.get( 9847 c.getSubjectDN(), formatDateAndTime(c.getNotBeforeDate()))); 9848 } 9849 9850 numErrors++; 9851 } 9852 else if (c.getNotAfterTime() < currentTime) 9853 { 9854 err(); 9855 if (i == 0) 9856 { 9857 wrapErr(0, WRAP_COLUMN, 9858 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_EXPIRED.get( 9859 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9860 } 9861 else 9862 { 9863 wrapErr(0, WRAP_COLUMN, 9864 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_EXPIRED.get( 9865 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9866 } 9867 9868 numErrors++; 9869 } 9870 else if (c.getNotAfterTime() < thirtyDaysFromNow) 9871 { 9872 err(); 9873 if (i == 0) 9874 { 9875 wrapErr(0, WRAP_COLUMN, 9876 WARN_MANAGE_CERTS_CHECK_USABILITY_END_CERT_NEAR_EXPIRATION.get( 9877 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9878 } 9879 else 9880 { 9881 wrapErr(0, WRAP_COLUMN, 9882 WARN_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_NEAR_EXPIRATION. 9883 get(c.getSubjectDN(), 9884 formatDateAndTime(c.getNotAfterDate()))); 9885 } 9886 9887 numWarnings++; 9888 } 9889 else 9890 { 9891 if (i == 0) 9892 { 9893 out(); 9894 wrapOut(0, WRAP_COLUMN, 9895 INFO_MANAGE_CERTS_CHECK_USABILITY_END_CERT_VALIDITY_OK.get( 9896 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9897 } 9898 else 9899 { 9900 out(); 9901 wrapOut(0, WRAP_COLUMN, 9902 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_VALIDITY_OK.get( 9903 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9904 } 9905 } 9906 } 9907 9908 9909 // Look at all of the extensions for all of the certificates and perform the 9910 // following validation: 9911 // - If the certificate at the head of the chain has an extended key usage 9912 // extension, then make sure it includes the serverAuth usage. If it 9913 // does not include an extended key usage extension, then warn that it 9914 // should. 9915 // - If any of the issuer certificates has a basic constraints extension, 9916 // then make sure it indicates that the associated certificate is a 9917 // certification authority. Further, if it has a path length constraint, 9918 // then make sure the chain does not exceed that length. If any issuer 9919 // certificate does not have a basic constraints extension, then warn that 9920 // it should. 9921 // - If any of the issuer certificates has a key usage extension, then 9922 // make sure it has the certSign usage. If any issuer certificate does 9923 // not have a key usage extension, then warn that it should. 9924 // - TODO: If any certificate has a CRL distribution points extension, then 9925 // retrieve the CRL and make sure the certificate hasn't been revoked. 9926 // - TODO: If any certificate has an authority information access 9927 // extension that points to an OCSP service, then consult that service to 9928 // determine whether the certificate has been revoked. 9929 for (int i=0; i < chain.length; i++) 9930 { 9931 boolean basicConstraintsFound = false; 9932 boolean extendedKeyUsageFound = false; 9933 boolean keyUsageFound = false; 9934 final X509Certificate c = chain[i]; 9935 for (final X509CertificateExtension extension : c.getExtensions()) 9936 { 9937 if (extension instanceof ExtendedKeyUsageExtension) 9938 { 9939 extendedKeyUsageFound = true; 9940 if (i == 0) 9941 { 9942 final ExtendedKeyUsageExtension e = 9943 (ExtendedKeyUsageExtension) extension; 9944 if (!e.getKeyPurposeIDs().contains( 9945 ExtendedKeyUsageID.TLS_SERVER_AUTHENTICATION.getOID())) 9946 { 9947 err(); 9948 wrapErr(0, WRAP_COLUMN, 9949 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_BAD_EKU.get( 9950 c.getSubjectDN())); 9951 numErrors++; 9952 } 9953 else 9954 { 9955 out(); 9956 wrapOut(0, WRAP_COLUMN, 9957 INFO_MANAGE_CERTS_CHECK_USABILITY_END_CERT_GOOD_EKU.get( 9958 c.getSubjectDN())); 9959 } 9960 } 9961 } 9962 else if (extension instanceof BasicConstraintsExtension) 9963 { 9964 basicConstraintsFound = true; 9965 if (i > 0) 9966 { 9967 final BasicConstraintsExtension e = 9968 (BasicConstraintsExtension) extension; 9969 if (!e.isCA()) 9970 { 9971 err(); 9972 wrapErr(0, WRAP_COLUMN, 9973 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_BAD_BC_CA.get( 9974 c.getSubjectDN())); 9975 numErrors++; 9976 } 9977 else if ((e.getPathLengthConstraint() != null) && 9978 ((i - 1) > e.getPathLengthConstraint())) 9979 { 9980 err(); 9981 wrapErr(0, WRAP_COLUMN, 9982 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_BAD_BC_LENGTH. 9983 get(c.getSubjectDN(), e.getPathLengthConstraint(), 9984 chain[0].getSubjectDN(), (i-1))); 9985 numErrors++; 9986 } 9987 else 9988 { 9989 out(); 9990 wrapOut(0, WRAP_COLUMN, 9991 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_GOOD_BC.get( 9992 c.getSubjectDN())); 9993 } 9994 } 9995 } 9996 else if (extension instanceof KeyUsageExtension) 9997 { 9998 keyUsageFound = true; 9999 if (i > 0) 10000 { 10001 final KeyUsageExtension e = (KeyUsageExtension) extension; 10002 if (! e.isKeyCertSignBitSet()) 10003 { 10004 err(); 10005 wrapErr(0, WRAP_COLUMN, 10006 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_NO_CERT_SIGN_KU.get( 10007 c.getSubjectDN())); 10008 numErrors++; 10009 } 10010 else 10011 { 10012 out(); 10013 wrapOut(0, WRAP_COLUMN, 10014 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_GOOD_KU.get( 10015 c.getSubjectDN())); 10016 } 10017 } 10018 } 10019 } 10020 10021 if (i == 0) 10022 { 10023 if (! extendedKeyUsageFound) 10024 { 10025 err(); 10026 wrapErr(0, WRAP_COLUMN, 10027 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_EKU.get( 10028 c.getSubjectDN())); 10029 numWarnings++; 10030 } 10031 } 10032 else 10033 { 10034 if (! basicConstraintsFound) 10035 { 10036 err(); 10037 wrapErr(0, WRAP_COLUMN, 10038 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_BC.get( 10039 c.getSubjectDN())); 10040 numWarnings++; 10041 } 10042 10043 if (! keyUsageFound) 10044 { 10045 err(); 10046 wrapErr(0, WRAP_COLUMN, 10047 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_KU.get( 10048 c.getSubjectDN())); 10049 numWarnings++; 10050 } 10051 } 10052 } 10053 10054 10055 // Make sure that none of the certificates has a signature algorithm that 10056 // uses MD5 or SHA-1. If it uses an unrecognized signature algorithm, then 10057 // that's a warning. 10058 boolean isIssuer = false; 10059 final BooleanArgument ignoreSHA1WarningArg = 10060 subCommandParser.getBooleanArgument( 10061 "allow-sha-1-signature-for-issuer-certificates"); 10062 final boolean ignoreSHA1SignatureWarningForIssuerCertificates = 10063 ((ignoreSHA1WarningArg != null) && ignoreSHA1WarningArg.isPresent()); 10064 for (final X509Certificate c : chain) 10065 { 10066 final OID signatureAlgorithmOID = c.getSignatureAlgorithmOID(); 10067 final SignatureAlgorithmIdentifier id = 10068 SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID); 10069 if (id == null) 10070 { 10071 err(); 10072 wrapErr(0, WRAP_COLUMN, 10073 WARN_MANAGE_CERTS_CHECK_USABILITY_UNKNOWN_SIG_ALG.get( 10074 c.getSubjectDN(), signatureAlgorithmOID)); 10075 numWarnings++; 10076 } 10077 else 10078 { 10079 switch (id) 10080 { 10081 case MD2_WITH_RSA: 10082 case MD5_WITH_RSA: 10083 err(); 10084 wrapErr(0, WRAP_COLUMN, 10085 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_SIG_ALG.get( 10086 c.getSubjectDN(), id.getUserFriendlyName())); 10087 numErrors++; 10088 break; 10089 10090 case SHA_1_WITH_RSA: 10091 case SHA_1_WITH_DSA: 10092 case SHA_1_WITH_ECDSA: 10093 if (isIssuer && ignoreSHA1SignatureWarningForIssuerCertificates) 10094 { 10095 err(); 10096 wrapErr(0, WRAP_COLUMN, 10097 WARN_MANAGE_CERTS_CHECK_USABILITY_ISSUER_WITH_SHA1_SIG.get( 10098 c.getSubjectDN(), id.getUserFriendlyName(), 10099 ignoreSHA1WarningArg.getIdentifierString())); 10100 } 10101 else 10102 { 10103 err(); 10104 wrapErr(0, WRAP_COLUMN, 10105 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_SIG_ALG.get( 10106 c.getSubjectDN(), id.getUserFriendlyName())); 10107 numErrors++; 10108 } 10109 break; 10110 10111 case SHA_224_WITH_RSA: 10112 case SHA_224_WITH_DSA: 10113 case SHA_224_WITH_ECDSA: 10114 case SHA_256_WITH_RSA: 10115 case SHA_256_WITH_DSA: 10116 case SHA_256_WITH_ECDSA: 10117 case SHA_384_WITH_RSA: 10118 case SHA_384_WITH_ECDSA: 10119 case SHA_512_WITH_RSA: 10120 case SHA_512_WITH_ECDSA: 10121 out(); 10122 wrapOut(0, WRAP_COLUMN, 10123 INFO_MANAGE_CERTS_CHECK_USABILITY_SIG_ALG_OK.get( 10124 c.getSubjectDN(), id.getUserFriendlyName())); 10125 break; 10126 } 10127 } 10128 10129 isIssuer = true; 10130 } 10131 10132 10133 // Make sure that none of the certificates that uses the RSA key algorithm 10134 // has a public modulus size smaller than 2048 bits. 10135 for (final X509Certificate c : chain) 10136 { 10137 if ((c.getDecodedPublicKey() != null) && 10138 (c.getDecodedPublicKey() instanceof RSAPublicKey)) 10139 { 10140 final RSAPublicKey rsaPublicKey = 10141 (RSAPublicKey) c.getDecodedPublicKey(); 10142 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10143 int modulusSizeBits = modulusBytes.length * 8; 10144 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10145 { 10146 modulusSizeBits -= 8; 10147 } 10148 10149 if (modulusSizeBits < 2048) 10150 { 10151 err(); 10152 wrapErr(0, WRAP_COLUMN, 10153 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_RSA_MODULUS.get( 10154 c.getSubjectDN(), modulusSizeBits)); 10155 numErrors++; 10156 } 10157 else 10158 { 10159 out(); 10160 wrapOut(0, WRAP_COLUMN, 10161 INFO_MANAGE_CERTS_CHECK_USABILITY_RSA_MODULUS_OK.get( 10162 c.getSubjectDN(), modulusSizeBits)); 10163 } 10164 } 10165 } 10166 10167 10168 switch (numErrors) 10169 { 10170 case 0: 10171 break; 10172 case 1: 10173 err(); 10174 wrapErr(0, WRAP_COLUMN, 10175 ERR_MANAGE_CERTS_CHECK_USABILITY_ONE_ERROR.get()); 10176 return ResultCode.PARAM_ERROR; 10177 default: 10178 err(); 10179 wrapErr(0, WRAP_COLUMN, 10180 ERR_MANAGE_CERTS_CHECK_USABILITY_MULTIPLE_ERRORS.get(numErrors)); 10181 return ResultCode.PARAM_ERROR; 10182 } 10183 10184 switch (numWarnings) 10185 { 10186 case 0: 10187 out(); 10188 wrapOut(0, WRAP_COLUMN, 10189 INFO_MANAGE_CERTS_CHECK_USABILITY_NO_ERRORS_OR_WARNINGS.get()); 10190 return ResultCode.SUCCESS; 10191 case 1: 10192 err(); 10193 wrapErr(0, WRAP_COLUMN, 10194 ERR_MANAGE_CERTS_CHECK_USABILITY_ONE_WARNING.get()); 10195 return ResultCode.PARAM_ERROR; 10196 default: 10197 err(); 10198 wrapErr(0, WRAP_COLUMN, 10199 ERR_MANAGE_CERTS_CHECK_USABILITY_MULTIPLE_WARNINGS.get( 10200 numWarnings)); 10201 return ResultCode.PARAM_ERROR; 10202 } 10203 } 10204 10205 10206 10207 /** 10208 * Performs the necessary processing for the display-certificate-file 10209 * subcommand. 10210 * 10211 * @return A result code that indicates whether the processing completed 10212 * successfully. 10213 */ 10214 @NotNull() 10215 private ResultCode doDisplayCertificateFile() 10216 { 10217 // Get the values of a number of configured arguments. 10218 final FileArgument certificateFileArgument = 10219 subCommandParser.getFileArgument("certificate-file"); 10220 final File certificateFile = certificateFileArgument.getValue(); 10221 10222 final BooleanArgument verboseArgument = 10223 subCommandParser.getBooleanArgument("verbose"); 10224 final boolean verbose = 10225 ((verboseArgument != null) && verboseArgument.isPresent()); 10226 10227 final BooleanArgument displayKeytoolCommandArgument = 10228 subCommandParser.getBooleanArgument("display-keytool-command"); 10229 if ((displayKeytoolCommandArgument != null) && 10230 displayKeytoolCommandArgument.isPresent()) 10231 { 10232 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 10233 keytoolArgs.add("-printcert"); 10234 keytoolArgs.add("-file"); 10235 keytoolArgs.add(certificateFile.getAbsolutePath()); 10236 10237 if (verbose) 10238 { 10239 keytoolArgs.add("-v"); 10240 } 10241 10242 displayKeytoolCommand(keytoolArgs); 10243 } 10244 10245 10246 // Read the certificates from the specified file. 10247 final List<X509Certificate> certificates; 10248 try 10249 { 10250 certificates = readCertificatesFromFile(certificateFile); 10251 } 10252 catch (final LDAPException le) 10253 { 10254 Debug.debugException(le); 10255 wrapErr(0, WRAP_COLUMN, le.getMessage()); 10256 return le.getResultCode(); 10257 } 10258 10259 10260 // If there aren't any certificates in the file, print that. 10261 if (certificates.isEmpty()) 10262 { 10263 wrapOut(0, WRAP_COLUMN, INFO_MANAGE_CERTS_DISPLAY_CERT_NO_CERTS.get( 10264 certificateFile.getAbsolutePath())); 10265 } 10266 else 10267 { 10268 for (final X509Certificate c : certificates) 10269 { 10270 out(); 10271 printCertificate(c, "", verbose); 10272 } 10273 } 10274 10275 return ResultCode.SUCCESS; 10276 } 10277 10278 10279 10280 /** 10281 * Performs the necessary processing for the 10282 * display-certificate-signing-request-file subcommand. 10283 * 10284 * @return A result code that indicates whether the processing completed 10285 * successfully. 10286 */ 10287 @NotNull() 10288 private ResultCode doDisplayCertificateSigningRequestFile() 10289 { 10290 // Get the values of a number of configured arguments. 10291 final FileArgument csrFileArgument = 10292 subCommandParser.getFileArgument("certificate-signing-request-file"); 10293 final File csrFile = csrFileArgument.getValue(); 10294 10295 final BooleanArgument verboseArgument = 10296 subCommandParser.getBooleanArgument("verbose"); 10297 final boolean verbose = 10298 ((verboseArgument != null) && verboseArgument.isPresent()); 10299 10300 final BooleanArgument displayKeytoolCommandArgument = 10301 subCommandParser.getBooleanArgument("display-keytool-command"); 10302 if ((displayKeytoolCommandArgument != null) && 10303 displayKeytoolCommandArgument.isPresent()) 10304 { 10305 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 10306 keytoolArgs.add("-printcertreq"); 10307 keytoolArgs.add("-file"); 10308 keytoolArgs.add(csrFile.getAbsolutePath()); 10309 keytoolArgs.add("-v"); 10310 10311 displayKeytoolCommand(keytoolArgs); 10312 } 10313 10314 10315 // Read the certificate signing request from the specified file. 10316 final PKCS10CertificateSigningRequest csr; 10317 try 10318 { 10319 csr = readCertificateSigningRequestFromFile(csrFile); 10320 } 10321 catch (final LDAPException le) 10322 { 10323 Debug.debugException(le); 10324 wrapErr(0, WRAP_COLUMN, le.getMessage()); 10325 return le.getResultCode(); 10326 } 10327 10328 out(); 10329 printCertificateSigningRequest(csr, verbose, ""); 10330 10331 return ResultCode.SUCCESS; 10332 } 10333 10334 10335 10336 /** 10337 * Prints a string representation of the provided certificate to standard 10338 * output. 10339 * 10340 * @param certificate The certificate to be printed. 10341 * @param indent The string to place at the beginning of each line to 10342 * indent that line. 10343 * @param verbose Indicates whether to display verbose information about 10344 * the certificate. 10345 */ 10346 private void printCertificate(@NotNull final X509Certificate certificate, 10347 @NotNull final String indent, 10348 final boolean verbose) 10349 { 10350 if (verbose) 10351 { 10352 out(indent + 10353 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VERSION.get( 10354 certificate.getVersion().getName())); 10355 } 10356 10357 out(indent + 10358 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_DN.get( 10359 certificate.getSubjectDN())); 10360 out(indent + 10361 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ISSUER_DN.get( 10362 certificate.getIssuerDN())); 10363 10364 if (verbose) 10365 { 10366 out(indent + 10367 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SERIAL_NUMBER.get( 10368 toColonDelimitedHex( 10369 certificate.getSerialNumber().toByteArray()))); 10370 } 10371 10372 out(indent + 10373 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_START.get( 10374 formatDateAndTime(certificate.getNotBeforeDate()))); 10375 out(indent + 10376 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_END.get( 10377 formatDateAndTime(certificate.getNotAfterDate()))); 10378 10379 final long currentTime = System.currentTimeMillis(); 10380 if (currentTime < certificate.getNotBeforeTime()) 10381 { 10382 out(indent + 10383 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_NOT_YET_VALID. 10384 get()); 10385 } 10386 else if (currentTime > certificate.getNotAfterTime()) 10387 { 10388 out(indent + 10389 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_EXPIRED.get()); 10390 } 10391 else 10392 { 10393 out(indent + 10394 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_VALID.get()); 10395 } 10396 10397 out(indent + 10398 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_ALG.get( 10399 certificate.getSignatureAlgorithmNameOrOID())); 10400 if (verbose) 10401 { 10402 String signatureString; 10403 try 10404 { 10405 signatureString = 10406 toColonDelimitedHex(certificate.getSignatureValue().getBytes()); 10407 } 10408 catch (final Exception e) 10409 { 10410 Debug.debugException(e); 10411 signatureString = certificate.getSignatureValue().toString(); 10412 } 10413 out(indent + 10414 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_VALUE.get()); 10415 for (final String line : StaticUtils.wrapLine(signatureString, 78)) 10416 { 10417 out(indent + " " + line); 10418 } 10419 } 10420 10421 final String pkAlg; 10422 final String pkSummary = getPublicKeySummary( 10423 certificate.getPublicKeyAlgorithmOID(), 10424 certificate.getDecodedPublicKey(), 10425 certificate.getPublicKeyAlgorithmParameters()); 10426 if (pkSummary == null) 10427 { 10428 pkAlg = certificate.getPublicKeyAlgorithmNameOrOID(); 10429 } 10430 else 10431 { 10432 pkAlg = certificate.getPublicKeyAlgorithmNameOrOID() + " (" + 10433 pkSummary + ')'; 10434 } 10435 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_PK_ALG.get(pkAlg)); 10436 10437 if (verbose) 10438 { 10439 printPublicKey(certificate.getEncodedPublicKey(), 10440 certificate.getDecodedPublicKey(), 10441 certificate.getPublicKeyAlgorithmParameters(), indent); 10442 10443 if (certificate.getSubjectUniqueID() != null) 10444 { 10445 String subjectUniqueID; 10446 try 10447 { 10448 subjectUniqueID = toColonDelimitedHex( 10449 certificate.getSubjectUniqueID().getBytes()); 10450 } 10451 catch (final Exception e) 10452 { 10453 Debug.debugException(e); 10454 subjectUniqueID = certificate.getSubjectUniqueID().toString(); 10455 } 10456 10457 out(indent + 10458 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_UNIQUE_ID.get()); 10459 for (final String line : StaticUtils.wrapLine(subjectUniqueID, 78)) 10460 { 10461 out(indent + " " + line); 10462 } 10463 } 10464 10465 if (certificate.getIssuerUniqueID() != null) 10466 { 10467 String issuerUniqueID; 10468 try 10469 { 10470 issuerUniqueID = toColonDelimitedHex( 10471 certificate.getIssuerUniqueID().getBytes()); 10472 } 10473 catch (final Exception e) 10474 { 10475 Debug.debugException(e); 10476 issuerUniqueID = certificate.getIssuerUniqueID().toString(); 10477 } 10478 10479 out(indent + 10480 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ISSUER_UNIQUE_ID.get()); 10481 for (final String line : StaticUtils.wrapLine(issuerUniqueID, 78)) 10482 { 10483 out(indent + " " + line); 10484 } 10485 } 10486 10487 printExtensions(certificate.getExtensions(), indent); 10488 } 10489 10490 try 10491 { 10492 out(indent + 10493 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_FINGERPRINT.get("SHA-1", 10494 toColonDelimitedHex(certificate.getSHA1Fingerprint()))); 10495 } 10496 catch (final Exception e) 10497 { 10498 Debug.debugException(e); 10499 } 10500 10501 try 10502 { 10503 out(indent + 10504 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_FINGERPRINT.get("SHA-256", 10505 toColonDelimitedHex(certificate.getSHA256Fingerprint()))); 10506 } 10507 catch (final Exception e) 10508 { 10509 Debug.debugException(e); 10510 } 10511 } 10512 10513 10514 10515 /** 10516 * Prints a string representation of the provided certificate signing request 10517 * to standard output. 10518 * 10519 * @param csr The certificate signing request to be printed. 10520 * @param verbose Indicates whether to display verbose information about 10521 * the contents of the request. 10522 * @param indent The string to place at the beginning of each line to 10523 * indent that line. 10524 */ 10525 private void printCertificateSigningRequest( 10526 @NotNull final PKCS10CertificateSigningRequest csr, 10527 final boolean verbose, @NotNull final String indent) 10528 { 10529 out(indent + 10530 INFO_MANAGE_CERTS_PRINT_CSR_LABEL_VERSION.get( 10531 csr.getVersion().getName())); 10532 out(indent + 10533 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_DN.get( 10534 csr.getSubjectDN())); 10535 out(indent + 10536 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_ALG.get( 10537 csr.getSignatureAlgorithmNameOrOID())); 10538 10539 if (verbose) 10540 { 10541 String signatureString; 10542 try 10543 { 10544 signatureString = 10545 toColonDelimitedHex(csr.getSignatureValue().getBytes()); 10546 } 10547 catch (final Exception e) 10548 { 10549 Debug.debugException(e); 10550 signatureString = csr.getSignatureValue().toString(); 10551 } 10552 out(indent + 10553 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_VALUE.get()); 10554 for (final String line : StaticUtils.wrapLine(signatureString, 78)) 10555 { 10556 out(indent + " " + line); 10557 } 10558 } 10559 10560 final String pkAlg; 10561 final String pkSummary = getPublicKeySummary(csr.getPublicKeyAlgorithmOID(), 10562 csr.getDecodedPublicKey(), csr.getPublicKeyAlgorithmParameters()); 10563 if (pkSummary == null) 10564 { 10565 pkAlg = csr.getPublicKeyAlgorithmNameOrOID(); 10566 } 10567 else 10568 { 10569 pkAlg = csr.getPublicKeyAlgorithmNameOrOID() + " (" + 10570 pkSummary + ')'; 10571 } 10572 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_PK_ALG.get(pkAlg)); 10573 10574 if (verbose) 10575 { 10576 printPublicKey(csr.getEncodedPublicKey(), csr.getDecodedPublicKey(), 10577 csr.getPublicKeyAlgorithmParameters(), indent); 10578 printExtensions(csr.getExtensions(), indent); 10579 } 10580 } 10581 10582 10583 10584 /** 10585 * Prints information about the provided public key. 10586 * 10587 * @param encodedPublicKey The encoded representation of the public key. 10588 * This must not be {@code null}. 10589 * @param decodedPublicKey The decoded representation of the public key, if 10590 * available. 10591 * @param parameters The public key algorithm parameters, if any. 10592 * @param indent The string to place at the beginning of each 10593 * line to indent that line. 10594 */ 10595 private void printPublicKey(@NotNull final ASN1BitString encodedPublicKey, 10596 @Nullable final DecodedPublicKey decodedPublicKey, 10597 @Nullable final ASN1Element parameters, 10598 @NotNull final String indent) 10599 { 10600 if (decodedPublicKey == null) 10601 { 10602 String pkString; 10603 try 10604 { 10605 pkString = toColonDelimitedHex(encodedPublicKey.getBytes()); 10606 } 10607 catch (final Exception e) 10608 { 10609 Debug.debugException(e); 10610 pkString = encodedPublicKey.toString(); 10611 } 10612 10613 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ENCODED_PK.get()); 10614 for (final String line : StaticUtils.wrapLine(pkString, 78)) 10615 { 10616 out(indent + " " + line); 10617 } 10618 10619 return; 10620 } 10621 10622 if (decodedPublicKey instanceof RSAPublicKey) 10623 { 10624 final RSAPublicKey rsaPublicKey = (RSAPublicKey) decodedPublicKey; 10625 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10626 10627 int modulusSizeBits = modulusBytes.length * 8; 10628 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10629 { 10630 modulusSizeBits -= 8; 10631 } 10632 10633 out(indent + 10634 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_RSA_MODULUS.get( 10635 modulusSizeBits)); 10636 final String modulusHex = toColonDelimitedHex(modulusBytes); 10637 for (final String line : StaticUtils.wrapLine(modulusHex, 78)) 10638 { 10639 out(indent + " " + line); 10640 } 10641 10642 out(indent + 10643 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_RSA_EXPONENT.get( 10644 toColonDelimitedHex( 10645 rsaPublicKey.getPublicExponent().toByteArray()))); 10646 } 10647 else if (decodedPublicKey instanceof EllipticCurvePublicKey) 10648 { 10649 final EllipticCurvePublicKey ecPublicKey = 10650 (EllipticCurvePublicKey) decodedPublicKey; 10651 10652 out(indent + 10653 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_IS_COMPRESSED.get( 10654 String.valueOf(ecPublicKey.usesCompressedForm()))); 10655 out(indent + 10656 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_X.get( 10657 String.valueOf(ecPublicKey.getXCoordinate()))); 10658 if (ecPublicKey.getYCoordinate() == null) 10659 { 10660 out(indent + 10661 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_Y_IS_EVEN.get( 10662 String.valueOf(ecPublicKey.yCoordinateIsEven()))); 10663 } 10664 else 10665 { 10666 out(indent + 10667 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_Y.get( 10668 String.valueOf(ecPublicKey.getYCoordinate()))); 10669 } 10670 } 10671 } 10672 10673 10674 10675 /** 10676 * Retrieves a short summary of the provided public key, if available. For 10677 * RSA keys, this will be the modulus size in bits. For elliptic curve keys, 10678 * this will be the named curve, if available. 10679 * 10680 * @param publicKeyAlgorithmOID The OID that identifies the type of public 10681 * key. 10682 * @param publicKey The decoded public key. This may be 10683 * {@code null} if the decoded public key is 10684 * not available. 10685 * @param parameters The encoded public key algorithm parameters. 10686 * This may be {@code null} if no public key 10687 * algorithm parameters are available. 10688 * 10689 * @return A short summary of the provided public key, or {@code null} if 10690 * no summary is available. 10691 */ 10692 @NotNull() 10693 private static String getPublicKeySummary( 10694 @NotNull final OID publicKeyAlgorithmOID, 10695 @Nullable final DecodedPublicKey publicKey, 10696 @Nullable final ASN1Element parameters) 10697 { 10698 if (publicKey instanceof RSAPublicKey) 10699 { 10700 final RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; 10701 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10702 10703 int modulusSizeBits = modulusBytes.length * 8; 10704 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10705 { 10706 modulusSizeBits -= 8; 10707 } 10708 10709 return INFO_MANAGE_CERTS_GET_PK_SUMMARY_RSA_MODULUS_SIZE.get( 10710 modulusSizeBits); 10711 } 10712 else if ((parameters != null) && 10713 publicKeyAlgorithmOID.equals(PublicKeyAlgorithmIdentifier.EC.getOID())) 10714 { 10715 try 10716 { 10717 final OID namedCurveOID = 10718 parameters.decodeAsObjectIdentifier().getOID(); 10719 return NamedCurve.getNameOrOID(namedCurveOID); 10720 } 10721 catch (final Exception e) 10722 { 10723 Debug.debugException(e); 10724 } 10725 } 10726 10727 return null; 10728 } 10729 10730 10731 10732 /** 10733 * Prints information about the provided extensions. 10734 * 10735 * @param extensions The list of extensions to be printed. 10736 * @param indent The string to place at the beginning of each line to 10737 * indent that line. 10738 */ 10739 void printExtensions(@NotNull final List<X509CertificateExtension> extensions, 10740 @NotNull final String indent) 10741 { 10742 if (extensions.isEmpty()) 10743 { 10744 return; 10745 } 10746 10747 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXTENSIONS.get()); 10748 for (final X509CertificateExtension extension : extensions) 10749 { 10750 if (extension instanceof AuthorityKeyIdentifierExtension) 10751 { 10752 out(indent + " " + 10753 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_EXT.get()); 10754 out(indent + " " + 10755 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10756 extension.getOID().toString())); 10757 out(indent + " " + 10758 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10759 String.valueOf(extension.isCritical()))); 10760 10761 final AuthorityKeyIdentifierExtension e = 10762 (AuthorityKeyIdentifierExtension) extension; 10763 if (e.getKeyIdentifier() != null) 10764 { 10765 out(indent + " " + 10766 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_ID.get()); 10767 final String idHex = 10768 toColonDelimitedHex(e.getKeyIdentifier().getValue()); 10769 for (final String line : StaticUtils.wrapLine(idHex, 78)) 10770 { 10771 out(indent + " " + line); 10772 } 10773 } 10774 10775 if (e.getAuthorityCertIssuer() != null) 10776 { 10777 out(indent + " " + 10778 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_ISSUER. 10779 get()); 10780 printGeneralNames(e.getAuthorityCertIssuer(), 10781 indent + " "); 10782 } 10783 10784 if (e.getAuthorityCertSerialNumber() != null) 10785 { 10786 out(indent + " " + 10787 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_SERIAL.get( 10788 toColonDelimitedHex(e.getAuthorityCertSerialNumber(). 10789 toByteArray()))); 10790 } 10791 } 10792 else if (extension instanceof BasicConstraintsExtension) 10793 { 10794 out(indent + " " + 10795 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_EXT.get()); 10796 out(indent + " " + 10797 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10798 extension.getOID().toString())); 10799 out(indent + " " + 10800 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10801 String.valueOf(extension.isCritical()))); 10802 10803 final BasicConstraintsExtension e = 10804 (BasicConstraintsExtension) extension; 10805 out(indent + " " + 10806 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_IS_CA.get( 10807 String.valueOf(e.isCA()))); 10808 10809 if (e.getPathLengthConstraint() != null) 10810 { 10811 out(indent + " " + 10812 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_LENGTH.get( 10813 e.getPathLengthConstraint())); 10814 } 10815 } 10816 else if (extension instanceof CRLDistributionPointsExtension) 10817 { 10818 out(indent + " " + 10819 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_EXT.get()); 10820 out(indent + " " + 10821 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10822 extension.getOID().toString())); 10823 out(indent + " " + 10824 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10825 String.valueOf(extension.isCritical()))); 10826 10827 final CRLDistributionPointsExtension crlDPE = 10828 (CRLDistributionPointsExtension) extension; 10829 for (final CRLDistributionPoint dp : 10830 crlDPE.getCRLDistributionPoints()) 10831 { 10832 out(indent + " " + 10833 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_HEADER.get()); 10834 if (dp.getFullName() != null) 10835 { 10836 out(indent + " " + 10837 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_FULL_NAME. 10838 get()); 10839 printGeneralNames(dp.getFullName(), 10840 indent + " "); 10841 } 10842 10843 if (dp.getNameRelativeToCRLIssuer() != null) 10844 { 10845 out(indent + " " + 10846 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_REL_NAME.get( 10847 dp.getNameRelativeToCRLIssuer())); 10848 } 10849 10850 if (! dp.getPotentialRevocationReasons().isEmpty()) 10851 { 10852 out(indent + " " + 10853 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_REASON.get()); 10854 for (final CRLDistributionPointRevocationReason r : 10855 dp.getPotentialRevocationReasons()) 10856 { 10857 out(indent + " " + r.getName()); 10858 } 10859 } 10860 10861 if (dp.getCRLIssuer() != null) 10862 { 10863 out(indent + " " + 10864 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_CRL_ISSUER. 10865 get()); 10866 printGeneralNames(dp.getCRLIssuer(), 10867 indent + " "); 10868 } 10869 } 10870 } 10871 else if (extension instanceof ExtendedKeyUsageExtension) 10872 { 10873 out(indent + " " + 10874 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_EXT.get()); 10875 out(indent + " " + 10876 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10877 extension.getOID().toString())); 10878 out(indent + " " + 10879 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10880 String.valueOf(extension.isCritical()))); 10881 10882 final ExtendedKeyUsageExtension e = 10883 (ExtendedKeyUsageExtension) extension; 10884 for (final OID oid : e.getKeyPurposeIDs()) 10885 { 10886 final ExtendedKeyUsageID id = ExtendedKeyUsageID.forOID(oid); 10887 if (id == null) 10888 { 10889 out(indent + " " + 10890 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_ID.get(oid)); 10891 } 10892 else 10893 { 10894 out(indent + " " + 10895 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_ID.get( 10896 id.getName())); 10897 } 10898 } 10899 } 10900 else if (extension instanceof IssuerAlternativeNameExtension) 10901 { 10902 out(indent + " " + 10903 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IAN_EXT.get()); 10904 out(indent + " " + 10905 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10906 extension.getOID().toString())); 10907 out(indent + " " + 10908 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10909 String.valueOf(extension.isCritical()))); 10910 10911 final IssuerAlternativeNameExtension e = 10912 (IssuerAlternativeNameExtension) extension; 10913 printGeneralNames(e.getGeneralNames(), indent + " "); 10914 } 10915 else if (extension instanceof KeyUsageExtension) 10916 { 10917 out(indent + " " + 10918 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_EXT.get()); 10919 out(indent + " " + 10920 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10921 extension.getOID().toString())); 10922 out(indent + " " + 10923 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10924 String.valueOf(extension.isCritical()))); 10925 10926 out(indent + " " + 10927 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_USAGES.get()); 10928 final KeyUsageExtension kue = (KeyUsageExtension) extension; 10929 if (kue.isDigitalSignatureBitSet()) 10930 { 10931 out(indent + " " + 10932 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DS.get()); 10933 } 10934 10935 if (kue.isNonRepudiationBitSet()) 10936 { 10937 out(indent + " " + 10938 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_NR.get()); 10939 } 10940 10941 if (kue.isKeyEnciphermentBitSet()) 10942 { 10943 out(indent + " " + 10944 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KE.get()); 10945 } 10946 10947 if (kue.isDataEnciphermentBitSet()) 10948 { 10949 out(indent + " " + 10950 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DE.get()); 10951 } 10952 10953 if (kue.isKeyAgreementBitSet()) 10954 { 10955 out(indent + " " + 10956 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KA.get()); 10957 } 10958 10959 if (kue.isKeyCertSignBitSet()) 10960 { 10961 out(indent + " " + 10962 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KCS.get()); 10963 } 10964 10965 if (kue.isCRLSignBitSet()) 10966 { 10967 out(indent + " " + 10968 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_CRL_SIGN.get()); 10969 } 10970 10971 if (kue.isEncipherOnlyBitSet()) 10972 { 10973 out(indent + " " + 10974 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_EO.get()); 10975 } 10976 10977 if (kue.isDecipherOnlyBitSet()) 10978 { 10979 out(indent + " " + 10980 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DO.get()); 10981 } 10982 } 10983 else if (extension instanceof SubjectAlternativeNameExtension) 10984 { 10985 out(indent + " " + 10986 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SAN_EXT.get()); 10987 out(indent + " " + 10988 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10989 extension.getOID().toString())); 10990 out(indent + " " + 10991 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10992 String.valueOf(extension.isCritical()))); 10993 10994 final SubjectAlternativeNameExtension e = 10995 (SubjectAlternativeNameExtension) extension; 10996 printGeneralNames(e.getGeneralNames(), indent + " "); 10997 } 10998 else if (extension instanceof SubjectKeyIdentifierExtension) 10999 { 11000 out(indent + " " + 11001 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SKI_EXT.get()); 11002 out(indent + " " + 11003 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 11004 extension.getOID().toString())); 11005 out(indent + " " + 11006 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 11007 String.valueOf(extension.isCritical()))); 11008 11009 final SubjectKeyIdentifierExtension e = 11010 (SubjectKeyIdentifierExtension) extension; 11011 final String idHex = 11012 toColonDelimitedHex(e.getKeyIdentifier().getValue()); 11013 out(indent + " " + 11014 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SKI_ID.get()); 11015 for (final String line : StaticUtils.wrapLine(idHex, 78)) 11016 { 11017 out(indent + " " + line); 11018 } 11019 } 11020 else 11021 { 11022 out(indent + " " + 11023 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_GENERIC.get()); 11024 out(indent + " " + 11025 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 11026 extension.getOID().toString())); 11027 out(indent + " " + 11028 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 11029 String.valueOf(extension.isCritical()))); 11030 11031 final String valueHex = toColonDelimitedHex(extension.getValue()); 11032 out(indent + " " + 11033 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_VALUE.get()); 11034 getOut().print(StaticUtils.toHexPlusASCII(extension.getValue(), 11035 (indent.length() + 15))); 11036 } 11037 } 11038 } 11039 11040 11041 11042 /** 11043 * Prints information about the contents of the provided general names object. 11044 * 11045 * @param generalNames The general names object to print. 11046 * @param indent The string to place at the beginning of each line to 11047 * indent that line. 11048 */ 11049 private void printGeneralNames(@NotNull final GeneralNames generalNames, 11050 @NotNull final String indent) 11051 { 11052 for (final String dnsName : generalNames.getDNSNames()) 11053 { 11054 out(indent + INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_DNS.get(dnsName)); 11055 } 11056 11057 for (final InetAddress ipAddress : generalNames.getIPAddresses()) 11058 { 11059 out(indent + 11060 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_IP.get( 11061 ipAddress.getHostAddress())); 11062 } 11063 11064 for (final String name : generalNames.getRFC822Names()) 11065 { 11066 out(indent + 11067 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_RFC_822_NAME.get(name)); 11068 } 11069 11070 for (final DN dn : generalNames.getDirectoryNames()) 11071 { 11072 out(indent + 11073 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_DIRECTORY_NAME.get( 11074 String.valueOf(dn))); 11075 } 11076 11077 for (final String uri : generalNames.getUniformResourceIdentifiers()) 11078 { 11079 out(indent + INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_URI.get(uri)); 11080 } 11081 11082 for (final OID oid : generalNames.getRegisteredIDs()) 11083 { 11084 out(indent + 11085 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_REGISTERED_ID.get( 11086 oid.toString())); 11087 } 11088 11089 if (! generalNames.getOtherNames().isEmpty()) 11090 { 11091 out(indent + 11092 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_OTHER_NAME_COUNT.get( 11093 generalNames.getOtherNames().size())); 11094 } 11095 11096 if (! generalNames.getX400Addresses().isEmpty()) 11097 { 11098 out(indent + 11099 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_X400_ADDR_COUNT.get( 11100 generalNames.getX400Addresses().size())); 11101 } 11102 11103 if (! generalNames.getEDIPartyNames().isEmpty()) 11104 { 11105 out(indent + 11106 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_EDI_PARTY_NAME_COUNT.get( 11107 generalNames.getEDIPartyNames().size())); 11108 } 11109 } 11110 11111 11112 11113 /** 11114 * Writes a PEM-encoded representation of the provided encoded certificate to 11115 * the given print stream. 11116 * 11117 * @param printStream The print stream to which the PEM-encoded 11118 * certificate should be written. It must not be 11119 * {@code null}. 11120 * @param encodedCertificate The bytes that comprise the encoded 11121 * certificate. It must not be {@code null}. 11122 */ 11123 private static void writePEMCertificate( 11124 @NotNull final PrintStream printStream, 11125 @NotNull final byte[] encodedCertificate) 11126 { 11127 final String certBase64 = Base64.encode(encodedCertificate); 11128 printStream.println("-----BEGIN CERTIFICATE-----"); 11129 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11130 { 11131 printStream.println(line); 11132 } 11133 printStream.println("-----END CERTIFICATE-----"); 11134 } 11135 11136 11137 11138 /** 11139 * Writes a PEM-encoded representation of the provided encoded certificate 11140 * signing request to the given print stream. 11141 * 11142 * @param printStream The print stream to which the PEM-encoded certificate 11143 * signing request should be written. It must not be 11144 * {@code null}. 11145 * @param encodedCSR The bytes that comprise the encoded certificate 11146 * signing request. It must not be {@code null}. 11147 */ 11148 private static void writePEMCertificateSigningRequest( 11149 @NotNull final PrintStream printStream, 11150 @NotNull final byte[] encodedCSR) 11151 { 11152 final String certBase64 = Base64.encode(encodedCSR); 11153 printStream.println("-----BEGIN CERTIFICATE REQUEST-----"); 11154 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11155 { 11156 printStream.println(line); 11157 } 11158 printStream.println("-----END CERTIFICATE REQUEST-----"); 11159 } 11160 11161 11162 11163 /** 11164 * Writes a PEM-encoded representation of the provided encoded private key to 11165 * the given print stream. 11166 * 11167 * @param printStream The print stream to which the PEM-encoded 11168 * private key should be written. It must not be 11169 * {@code null}. 11170 * @param encodedPrivateKey The bytes that comprise the encoded private 11171 * key. It must not be {@code null}. 11172 * @param encryptionPassword The password to use to encrypt the private key. 11173 * It may be {@code null} if the private key 11174 * should not be encrypted. 11175 * 11176 * @throws LDAPException If a problem occurs while trying write the private 11177 * key. 11178 */ 11179 private static void writePEMPrivateKey( 11180 @NotNull final PrintStream printStream, 11181 @NotNull final byte[] encodedPrivateKey, 11182 @Nullable final char[] encryptionPassword) 11183 throws LDAPException 11184 { 11185 if (encryptionPassword == null) 11186 { 11187 final String certBase64 = Base64.encode(encodedPrivateKey); 11188 printStream.println("-----BEGIN PRIVATE KEY-----"); 11189 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11190 { 11191 printStream.println(line); 11192 } 11193 printStream.println("-----END PRIVATE KEY-----"); 11194 } 11195 else 11196 { 11197 final byte[] encryptedPrivateKey; 11198 try 11199 { 11200 encryptedPrivateKey = PKCS8EncryptionHandler.encryptPrivateKey( 11201 encodedPrivateKey, encryptionPassword, 11202 new PKCS8EncryptionProperties()); 11203 } 11204 catch (final CertException e) 11205 { 11206 Debug.debugException(e); 11207 throw new LDAPException(ResultCode.LOCAL_ERROR, e.getMessage(), e); 11208 } 11209 11210 final String encryptedCertBase64 = Base64.encode(encryptedPrivateKey); 11211 printStream.println("-----BEGIN ENCRYPTED PRIVATE KEY-----"); 11212 for (final String line : StaticUtils.wrapLine(encryptedCertBase64, 64)) 11213 { 11214 printStream.println(line); 11215 } 11216 printStream.println("-----END ENCRYPTED PRIVATE KEY-----"); 11217 } 11218 } 11219 11220 11221 11222 /** 11223 * Displays the keytool command that can be invoked to produce approximately 11224 * equivalent functionality. 11225 * 11226 * @param keytoolArgs The arguments to provide to the keytool command. 11227 */ 11228 private void displayKeytoolCommand(@NotNull final List<String> keytoolArgs) 11229 { 11230 final StringBuilder buffer = new StringBuilder(); 11231 buffer.append("# keytool"); 11232 11233 boolean lastWasArgName = false; 11234 for (final String arg : keytoolArgs) 11235 { 11236 if (arg.startsWith("-")) 11237 { 11238 buffer.append(' '); 11239 buffer.append(StaticUtils.getCommandLineContinuationString()); 11240 buffer.append(StaticUtils.EOL); 11241 buffer.append("# "); 11242 buffer.append(arg); 11243 lastWasArgName = true; 11244 } 11245 else if (lastWasArgName) 11246 { 11247 buffer.append(' '); 11248 buffer.append(StaticUtils.cleanExampleCommandLineArgument(arg)); 11249 lastWasArgName = false; 11250 } 11251 else 11252 { 11253 buffer.append(' '); 11254 buffer.append(StaticUtils.getCommandLineContinuationString()); 11255 buffer.append(StaticUtils.EOL); 11256 buffer.append("# "); 11257 buffer.append(arg); 11258 lastWasArgName = false; 11259 } 11260 } 11261 11262 out(); 11263 out(INFO_MANAGE_CERTS_APPROXIMATE_KEYTOOL_COMMAND.get()); 11264 out(buffer); 11265 out(); 11266 } 11267 11268 11269 11270 /** 11271 * Retrieves the path to the target key store file. 11272 * 11273 * @return The path to the target key store file, or {@code null} if no 11274 * keystore path was configured. 11275 */ 11276 @Nullable() 11277 private File getKeystorePath() 11278 { 11279 return getKeystorePath("keystore"); 11280 } 11281 11282 11283 11284 /** 11285 * Retrieves the path to the target key store file. 11286 * 11287 * @param keystoreArgumentName The name of the argument used to specify the 11288 * path to the target key store. 11289 * 11290 * @return The path to the target keystore file, or {@code null} if no 11291 * keystore path was configured. 11292 */ 11293 @Nullable() 11294 private File getKeystorePath(@NotNull final String keystoreArgumentName) 11295 { 11296 final FileArgument keystoreArgument = 11297 subCommandParser.getFileArgument(keystoreArgumentName); 11298 if ((keystoreArgument != null) && keystoreArgument.isPresent()) 11299 { 11300 return keystoreArgument.getValue(); 11301 } 11302 11303 final BooleanArgument useJVMDefaultTrustStoreArgument = 11304 subCommandParser.getBooleanArgument("useJVMDefaultTrustStore"); 11305 if ((useJVMDefaultTrustStoreArgument != null) && 11306 useJVMDefaultTrustStoreArgument.isPresent()) 11307 { 11308 return JVM_DEFAULT_CACERTS_FILE; 11309 } 11310 11311 return 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 * 11322 * @return The password needed to access the keystore, or {@code null} if 11323 * no keystore password was configured. 11324 * 11325 * @throws LDAPException If a problem is encountered while trying to get the 11326 * keystore password. 11327 */ 11328 @Nullable() 11329 private char[] getKeystorePassword(@NotNull final File keystoreFile) 11330 throws LDAPException 11331 { 11332 return getKeystorePassword(keystoreFile, null); 11333 } 11334 11335 11336 11337 /** 11338 * Retrieves the password needed to access the keystore. 11339 * 11340 * @param keystoreFile The path to the keystore file for which to get the 11341 * password. 11342 * @param prefix The prefix string to use for the arguments. This may 11343 * be {@code null} if no prefix is needed. 11344 * 11345 * @return The password needed to access the keystore, or {@code null} if 11346 * no keystore password was configured. 11347 * 11348 * @throws LDAPException If a problem is encountered while trying to get the 11349 * keystore password. 11350 */ 11351 @Nullable() 11352 private char[] getKeystorePassword(@NotNull final File keystoreFile, 11353 @Nullable final String prefix) 11354 throws LDAPException 11355 { 11356 final String prefixDash; 11357 if (prefix == null) 11358 { 11359 prefixDash = ""; 11360 } 11361 else 11362 { 11363 prefixDash = prefix + '-'; 11364 } 11365 11366 final StringArgument keystorePasswordArgument = 11367 subCommandParser.getStringArgument(prefixDash + "keystore-password"); 11368 if ((keystorePasswordArgument != null) && 11369 keystorePasswordArgument.isPresent()) 11370 { 11371 final char[] keystorePWChars = 11372 keystorePasswordArgument.getValue().toCharArray(); 11373 if ((! keystoreFile.exists()) && (keystorePWChars.length < 6)) 11374 { 11375 throw new LDAPException(ResultCode.PARAM_ERROR, 11376 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11377 } 11378 11379 return keystorePWChars; 11380 } 11381 11382 11383 final FileArgument keystorePasswordFileArgument = 11384 subCommandParser.getFileArgument( 11385 prefixDash + "keystore-password-file"); 11386 if ((keystorePasswordFileArgument != null) && 11387 keystorePasswordFileArgument.isPresent()) 11388 { 11389 final File f = keystorePasswordFileArgument.getValue(); 11390 try 11391 { 11392 final char[] passwordChars = getPasswordFileReader().readPassword(f); 11393 if (passwordChars.length < 6) 11394 { 11395 throw new LDAPException(ResultCode.PARAM_ERROR, 11396 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11397 } 11398 return passwordChars; 11399 } 11400 catch (final LDAPException e) 11401 { 11402 Debug.debugException(e); 11403 throw e; 11404 } 11405 catch (final Exception e) 11406 { 11407 Debug.debugException(e); 11408 throw new LDAPException(ResultCode.LOCAL_ERROR, 11409 ERR_MANAGE_CERTS_GET_KS_PW_ERROR_READING_FILE.get( 11410 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11411 e); 11412 } 11413 } 11414 11415 11416 final BooleanArgument promptArgument = subCommandParser.getBooleanArgument( 11417 "prompt-for-" + prefixDash + "keystore-password"); 11418 if ((promptArgument != null) && promptArgument.isPresent()) 11419 { 11420 out(); 11421 if (keystoreFile.exists() && (! "new".equals(prefix))) 11422 { 11423 // We're only going to prompt once. 11424 if ((prefix != null) && prefix.equals("current")) 11425 { 11426 return promptForPassword( 11427 INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_CURRENT_PROMPT.get( 11428 keystoreFile.getAbsolutePath()), 11429 false); 11430 } 11431 else 11432 { 11433 return promptForPassword( 11434 INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_PROMPT.get( 11435 keystoreFile.getAbsolutePath()), 11436 false); 11437 } 11438 } 11439 else 11440 { 11441 // We're creating a new keystore, so we should prompt for the password 11442 // twice to prevent setting the wrong password because of a typo. 11443 while (true) 11444 { 11445 final String prompt1; 11446 if ("new".equals(prefix)) 11447 { 11448 prompt1 = INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_NEW_PROMPT.get(); 11449 } 11450 else 11451 { 11452 prompt1 = INFO_MANAGE_CERTS_KEY_KS_PW_NEW_PROMPT_1.get( 11453 keystoreFile.getAbsolutePath()); 11454 } 11455 final char[] pwChars = promptForPassword(prompt1, false); 11456 11457 if (pwChars.length < 6) 11458 { 11459 wrapErr(0, WRAP_COLUMN, 11460 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11461 err(); 11462 continue; 11463 } 11464 11465 final char[] confirmChars = promptForPassword( 11466 INFO_MANAGE_CERTS_KEY_KS_PW_NEW_PROMPT_2.get(), true); 11467 11468 if (Arrays.equals(pwChars, confirmChars)) 11469 { 11470 Arrays.fill(confirmChars, '\u0000'); 11471 return pwChars; 11472 } 11473 else 11474 { 11475 wrapErr(0, WRAP_COLUMN, 11476 ERR_MANAGE_CERTS_KEY_KS_PW_PROMPT_MISMATCH.get()); 11477 err(); 11478 } 11479 } 11480 } 11481 } 11482 11483 11484 return null; 11485 } 11486 11487 11488 11489 /** 11490 * Retrieves the password used to encrypt a private key. 11491 * 11492 * @param forDecrypt Indicates whether the password will be used to decrypt 11493 * the private key rather than to encrypt it. 11494 * 11495 * @return The password used to encrypt a private key, or {@code null} if no 11496 * encryption password was specified. 11497 * 11498 * @throws LDAPException If a problem is encountered while trying to get the 11499 * keystore password. 11500 */ 11501 @Nullable() 11502 private char[] getPrivateKeyEncryptionPassword(final boolean forDecrypt) 11503 throws LDAPException 11504 { 11505 final StringArgument passwordArgument = 11506 subCommandParser.getStringArgument("encryption-password"); 11507 if ((passwordArgument != null) && passwordArgument.isPresent()) 11508 { 11509 return passwordArgument.getValue().toCharArray(); 11510 } 11511 11512 11513 final FileArgument passwordFileArgument = 11514 subCommandParser.getFileArgument("encryption-password-file"); 11515 if ((passwordFileArgument != null) && passwordFileArgument.isPresent()) 11516 { 11517 final File f = passwordFileArgument.getValue(); 11518 try 11519 { 11520 return getPasswordFileReader().readPassword(f); 11521 } 11522 catch (final LDAPException e) 11523 { 11524 Debug.debugException(e); 11525 throw e; 11526 } 11527 catch (final Exception e) 11528 { 11529 Debug.debugException(e); 11530 throw new LDAPException(ResultCode.LOCAL_ERROR, 11531 ERR_MANAGE_CERTS_GET_PK_ENC_PW_ERROR_READING_FILE.get( 11532 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11533 e); 11534 } 11535 } 11536 11537 11538 final BooleanArgument promptArgument = subCommandParser.getBooleanArgument( 11539 "prompt-for-encryption-password"); 11540 if ((promptArgument != null) && promptArgument.isPresent()) 11541 { 11542 out(); 11543 if (forDecrypt) 11544 { 11545 // We'll be decrypting an existing private key, so we only need to 11546 // prompt for the password once. 11547 return promptForPassword( 11548 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_DECRYPT.get(), false); 11549 } 11550 else 11551 { 11552 // We'll be encrypting the private key, so we need to prompt twice to 11553 // confirm that the entered password is what the user intended. 11554 while (true) 11555 { 11556 final char[] pwChars = promptForPassword( 11557 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_ENCRYPT_1.get(), false); 11558 final char[] confirmChars = promptForPassword( 11559 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_ENCRYPT_2.get(), true); 11560 11561 if (Arrays.equals(pwChars, confirmChars)) 11562 { 11563 Arrays.fill(confirmChars, '\u0000'); 11564 return pwChars; 11565 } 11566 else 11567 { 11568 wrapErr(0, WRAP_COLUMN, 11569 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_MISMATCH.get()); 11570 err(); 11571 } 11572 } 11573 } 11574 } 11575 11576 11577 return null; 11578 } 11579 11580 11581 11582 /** 11583 * Prompts for a password and retrieves the value that the user entered. 11584 * 11585 * @param prompt The prompt to display to the user. 11586 * @param allowEmpty Indicates whether to allow the password to be empty. 11587 * 11588 * @return The password that was read, or an empty array if the user did not 11589 * type a password before pressing ENTER. 11590 * 11591 * @throws LDAPException If a problem is encountered while reading the 11592 * password. 11593 */ 11594 @NotNull() 11595 private char[] promptForPassword(@NotNull final String prompt, 11596 final boolean allowEmpty) 11597 throws LDAPException 11598 { 11599 final Iterator<String> iterator = 11600 StaticUtils.wrapLine(prompt, WRAP_COLUMN).iterator(); 11601 while (iterator.hasNext()) 11602 { 11603 final String line = iterator.next(); 11604 if (iterator.hasNext()) 11605 { 11606 out(line); 11607 } 11608 else 11609 { 11610 getOut().print(line); 11611 } 11612 } 11613 11614 final char[] passwordChars = PasswordReader.readPasswordChars(); 11615 if ((passwordChars.length == 0) && (! allowEmpty)) 11616 { 11617 wrapErr(0, WRAP_COLUMN, 11618 ERR_MANAGE_CERTS_PROMPT_FOR_PW_EMPTY_PW.get()); 11619 err(); 11620 return promptForPassword(prompt, allowEmpty); 11621 } 11622 11623 return passwordChars; 11624 } 11625 11626 11627 11628 /** 11629 * Prompts the user for a yes or no response. 11630 * 11631 * @param prompt The prompt to display to the end user. 11632 * 11633 * @return {@code true} if the user chooses the "yes" response, or 11634 * {@code false} if the user chooses the "no" throws. 11635 * 11636 * @throws LDAPException If a problem is encountered while reading data from 11637 * the client. 11638 */ 11639 private boolean promptForYesNo(@NotNull final String prompt) 11640 throws LDAPException 11641 { 11642 while (true) 11643 { 11644 final List<String> lines = 11645 StaticUtils.wrapLine((prompt + ' '), WRAP_COLUMN); 11646 11647 final Iterator<String> lineIterator = lines.iterator(); 11648 while (lineIterator.hasNext()) 11649 { 11650 final String line = lineIterator.next(); 11651 if (lineIterator.hasNext()) 11652 { 11653 out(line); 11654 } 11655 else 11656 { 11657 getOut().print(line); 11658 } 11659 } 11660 11661 try 11662 { 11663 final String response = readLineFromIn(); 11664 if (response.equalsIgnoreCase("yes") || response.equalsIgnoreCase("y")) 11665 { 11666 return true; 11667 } 11668 else if (response.equalsIgnoreCase("no") || 11669 response.equalsIgnoreCase("n")) 11670 { 11671 return false; 11672 } 11673 else 11674 { 11675 err(); 11676 wrapErr(0, WRAP_COLUMN, 11677 ERR_MANAGE_CERTS_PROMPT_FOR_YES_NO_INVALID_RESPONSE.get()); 11678 err(); 11679 } 11680 } 11681 catch (final Exception e) 11682 { 11683 Debug.debugException(e); 11684 throw new LDAPException(ResultCode.LOCAL_ERROR, 11685 ERR_MANAGE_CERTS_PROMPT_FOR_YES_NO_READ_ERROR.get( 11686 StaticUtils.getExceptionMessage(e)), 11687 e); 11688 } 11689 } 11690 } 11691 11692 11693 11694 /** 11695 * Reads a line of input from standard input. 11696 * 11697 * @return The line read from standard input. 11698 * 11699 * @throws IOException If a problem is encountered while reading from 11700 * standard input. 11701 */ 11702 @NotNull() 11703 private String readLineFromIn() 11704 throws IOException 11705 { 11706 final ByteStringBuffer buffer = new ByteStringBuffer(); 11707 while (true) 11708 { 11709 final int byteRead = in.read(); 11710 if (byteRead < 0) 11711 { 11712 if (buffer.isEmpty()) 11713 { 11714 return null; 11715 } 11716 else 11717 { 11718 return buffer.toString(); 11719 } 11720 } 11721 11722 if (byteRead == '\n') 11723 { 11724 return buffer.toString(); 11725 } 11726 else if (byteRead == '\r') 11727 { 11728 final int nextByteRead = in.read(); 11729 Validator.ensureTrue(((nextByteRead < 0) || (nextByteRead == '\n')), 11730 "ERROR: Read a carriage return from standard input that was " + 11731 "not followed by a new line."); 11732 return buffer.toString(); 11733 } 11734 else 11735 { 11736 buffer.append((byte) (byteRead & 0xFF)); 11737 } 11738 } 11739 } 11740 11741 11742 11743 /** 11744 * Retrieves the password needed to access the private key. 11745 * 11746 * @param keystore The keystore that contains the target private 11747 * key. This must not be {@code null}. 11748 * @param alias The alias of the target private key. This must 11749 * not be {@code null}. 11750 * @param keystorePassword The keystore password to use if no specific 11751 * private key password was provided. 11752 * 11753 * @return The password needed to access the private key, or the provided 11754 * keystore password if no arguments were provided to specify a 11755 * different private key password. 11756 * 11757 * @throws LDAPException If a problem is encountered while trying to get the 11758 * private key password. 11759 */ 11760 @Nullable() 11761 private char[] getPrivateKeyPassword(@NotNull final KeyStore keystore, 11762 @NotNull final String alias, 11763 @Nullable final char[] keystorePassword) 11764 throws LDAPException 11765 { 11766 return getPrivateKeyPassword(keystore, alias, null, keystorePassword); 11767 } 11768 11769 11770 11771 /** 11772 * Retrieves the password needed to access the private key. 11773 * 11774 * @param keystore The keystore that contains the target private 11775 * key. This must not be {@code null}. 11776 * @param alias The alias of the target private key. This must 11777 * not be {@code null}. 11778 * @param prefix The prefix string to use for the arguments. This 11779 * may be {@code null} if no prefix is needed. 11780 * @param keystorePassword The keystore password to use if no specific 11781 * private key password was provided. 11782 * 11783 * @return The password needed to access the private key, or the provided 11784 * keystore password if no arguments were provided to specify a 11785 * different private key password. 11786 * 11787 * @throws LDAPException If a problem is encountered while trying to get the 11788 * private key password. 11789 */ 11790 @Nullable() 11791 private char[] getPrivateKeyPassword(@NotNull final KeyStore keystore, 11792 @NotNull final String alias, 11793 @Nullable final String prefix, 11794 @Nullable final char[] keystorePassword) 11795 throws LDAPException 11796 { 11797 final String prefixDash; 11798 if (prefix == null) 11799 { 11800 prefixDash = ""; 11801 } 11802 else 11803 { 11804 prefixDash = prefix + '-'; 11805 } 11806 11807 final StringArgument privateKeyPasswordArgument = 11808 subCommandParser.getStringArgument( 11809 prefixDash + "private-key-password"); 11810 if ((privateKeyPasswordArgument != null) && 11811 privateKeyPasswordArgument.isPresent()) 11812 { 11813 final char[] pkPasswordChars = 11814 privateKeyPasswordArgument.getValue().toCharArray(); 11815 if ((pkPasswordChars.length < 6) && 11816 (! (hasCertificateAlias(keystore, alias) || 11817 hasKeyAlias(keystore, alias)))) 11818 { 11819 throw new LDAPException(ResultCode.PARAM_ERROR, 11820 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 11821 } 11822 11823 return pkPasswordChars; 11824 } 11825 11826 11827 final FileArgument privateKeyPasswordFileArgument = 11828 subCommandParser.getFileArgument( 11829 prefixDash + "private-key-password-file"); 11830 if ((privateKeyPasswordFileArgument != null) && 11831 privateKeyPasswordFileArgument.isPresent()) 11832 { 11833 final File f = privateKeyPasswordFileArgument.getValue(); 11834 try 11835 { 11836 final char[] passwordChars = getPasswordFileReader().readPassword(f); 11837 if (passwordChars.length < 6) 11838 { 11839 throw new LDAPException(ResultCode.PARAM_ERROR, 11840 ERR_MANAGE_CERTS_GET_PK_PW_EMPTY_FILE.get(f.getAbsolutePath())); 11841 } 11842 11843 return passwordChars; 11844 } 11845 catch (final LDAPException e) 11846 { 11847 Debug.debugException(e); 11848 throw e; 11849 } 11850 catch (final Exception e) 11851 { 11852 Debug.debugException(e); 11853 throw new LDAPException(ResultCode.LOCAL_ERROR, 11854 ERR_MANAGE_CERTS_GET_PK_PW_ERROR_READING_FILE.get( 11855 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11856 e); 11857 } 11858 } 11859 11860 11861 final BooleanArgument promptArgument = 11862 subCommandParser.getBooleanArgument( 11863 "prompt-for-" + prefixDash + "private-key-password"); 11864 if ((promptArgument != null) && promptArgument.isPresent()) 11865 { 11866 out(); 11867 11868 try 11869 { 11870 if ((hasKeyAlias(keystore, alias) || 11871 hasCertificateAlias(keystore, alias)) && 11872 (! "new".equals(prefix)) && (! "destination".equals(prefix))) 11873 { 11874 // This means that the private key already exists, so we just need to 11875 // prompt once. 11876 final String prompt; 11877 if ("current".equals(prefix)) 11878 { 11879 prompt = 11880 INFO_MANAGE_CERTS_GET_PK_PW_CURRENT_PROMPT.get(alias); 11881 } 11882 else 11883 { 11884 prompt = 11885 INFO_MANAGE_CERTS_GET_PK_PW_EXISTING_PROMPT.get(alias); 11886 } 11887 11888 return promptForPassword(prompt, false); 11889 } 11890 else 11891 { 11892 // This means that we'll be creating a new private key, so we need to 11893 // prompt twice. 11894 while (true) 11895 { 11896 final String prompt; 11897 if ("new".equals(prefix)) 11898 { 11899 prompt = INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT.get(); 11900 } 11901 else 11902 { 11903 prompt = INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT_1.get(alias); 11904 } 11905 11906 final char[] pwChars = promptForPassword(prompt, false); 11907 if (pwChars.length < 6) 11908 { 11909 wrapErr(0, WRAP_COLUMN, 11910 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 11911 err(); 11912 continue; 11913 } 11914 11915 final char[] confirmChars = promptForPassword( 11916 INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT_2.get(), true); 11917 11918 if (Arrays.equals(pwChars, confirmChars)) 11919 { 11920 Arrays.fill(confirmChars, '\u0000'); 11921 return pwChars; 11922 } 11923 else 11924 { 11925 wrapErr(0, WRAP_COLUMN, 11926 ERR_MANAGE_CERTS_GET_PK_PW_PROMPT_MISMATCH.get()); 11927 err(); 11928 } 11929 } 11930 } 11931 } 11932 catch (final LDAPException le) 11933 { 11934 Debug.debugException(le); 11935 throw le; 11936 } 11937 catch (final Exception e) 11938 { 11939 Debug.debugException(e); 11940 throw new LDAPException(ResultCode.LOCAL_ERROR, 11941 ERR_MANAGE_CERTS_GET_PK_PW_PROMPT_ERROR.get(alias, 11942 StaticUtils.getExceptionMessage(e)), 11943 e); 11944 } 11945 } 11946 11947 11948 return keystorePassword; 11949 } 11950 11951 11952 11953 /** 11954 * Infers the keystore type from the provided keystore file. 11955 * 11956 * @param keystorePath The path to the file to examine. 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 throws LDAPException 11966 { 11967 return inferKeystoreType(keystorePath, null); 11968 } 11969 11970 11971 11972 /** 11973 * Infers the keystore type from the provided keystore file. 11974 * 11975 * @param keystorePath The path to the file to examine. 11976 * @param prefix The prefix string to use for the arguments. This 11977 * may be {@code null} if no prefix is needed. 11978 * 11979 * @return The keystore type inferred from the provided keystore file. 11980 * 11981 * @throws LDAPException If a problem is encountered while trying to infer 11982 * the keystore type. 11983 */ 11984 @NotNull() 11985 private String inferKeystoreType(@NotNull final File keystorePath, 11986 @Nullable final String prefix) 11987 throws LDAPException 11988 { 11989 // If the keystore type argument was specified, then use its value. 11990 final StringArgument keystoreTypeArgument; 11991 if (prefix == null) 11992 { 11993 keystoreTypeArgument = 11994 subCommandParser.getStringArgument("keystore-type"); 11995 } 11996 else 11997 { 11998 keystoreTypeArgument = 11999 subCommandParser.getStringArgument(prefix + "-keystore-type"); 12000 } 12001 12002 if ((keystoreTypeArgument != null) && keystoreTypeArgument.isPresent()) 12003 { 12004 final String ktaValue = keystoreTypeArgument.getValue(); 12005 if (ktaValue.equalsIgnoreCase("PKCS11") || 12006 ktaValue.equalsIgnoreCase("PKCS 11") || 12007 ktaValue.equalsIgnoreCase("PKCS#11") || 12008 ktaValue.equalsIgnoreCase("PKCS #11")) 12009 { 12010 return CryptoHelper.KEY_STORE_TYPE_PKCS_11; 12011 } 12012 else if (ktaValue.equalsIgnoreCase("PKCS12") || 12013 ktaValue.equalsIgnoreCase("PKCS 12") || 12014 ktaValue.equalsIgnoreCase("PKCS#12") || 12015 ktaValue.equalsIgnoreCase("PKCS #12")) 12016 { 12017 return CryptoHelper.KEY_STORE_TYPE_PKCS_12; 12018 } 12019 else if (ktaValue.equalsIgnoreCase(BCFKS_KEYSTORE_TYPE)) 12020 { 12021 return BCFKS_KEYSTORE_TYPE; 12022 } 12023 else 12024 { 12025 return CryptoHelper.KEY_STORE_TYPE_JKS; 12026 } 12027 } 12028 12029 12030 // If we've gotten here, then the keystore type was not explicitly specified 12031 // so we will need to infer it. If the LDAP SDK is running in FIPS mode, 12032 // then we'll always use the BCFKS key store type. 12033 if (CryptoHelper.usingFIPSMode()) 12034 { 12035 return BouncyCastleFIPSHelper.FIPS_KEY_STORE_TYPE; 12036 } 12037 12038 12039 // If the key store file doesn't exist, then we must be creating it. Use 12040 // the default key store type. 12041 if (! keystorePath.exists()) 12042 { 12043 return DEFAULT_KEYSTORE_TYPE; 12044 } 12045 12046 12047 try 12048 { 12049 return CryptoHelper.inferKeyStoreType(keystorePath); 12050 } 12051 catch (final Exception e) 12052 { 12053 Debug.debugException(e); 12054 throw new LDAPException(ResultCode.PARAM_ERROR, e.getMessage(), e); 12055 } 12056 } 12057 12058 12059 12060 /** 12061 * Retrieves a user-friendly representation of the provided keystore type. 12062 * 12063 * @param keystoreType The keystore type for which to get the user-friendly 12064 * name. 12065 * 12066 * @return "JKS" if the provided keystore type is for a JKS keystore, 12067 * "PKCS #12" if the provided keystore type is for a PKCS #12 12068 * keystore, or the provided string if it is for some other keystore 12069 * type. 12070 */ 12071 @NotNull() 12072 static String getUserFriendlyKeystoreType(@NotNull final String keystoreType) 12073 { 12074 if (keystoreType.equalsIgnoreCase("JKS")) 12075 { 12076 return "JKS"; 12077 } 12078 else if (keystoreType.equalsIgnoreCase("PKCS11") || 12079 keystoreType.equalsIgnoreCase("PKCS 11") || 12080 keystoreType.equalsIgnoreCase("PKCS#11") || 12081 keystoreType.equalsIgnoreCase("PKCS #11")) 12082 { 12083 return "PKCS #11"; 12084 } 12085 else if (keystoreType.equalsIgnoreCase("PKCS12") || 12086 keystoreType.equalsIgnoreCase("PKCS 12") || 12087 keystoreType.equalsIgnoreCase("PKCS#12") || 12088 keystoreType.equalsIgnoreCase("PKCS #12")) 12089 { 12090 return "PKCS #12"; 12091 } 12092 else if (keystoreType.equalsIgnoreCase(BCFKS_KEYSTORE_TYPE)) 12093 { 12094 return BCFKS_KEYSTORE_TYPE; 12095 } 12096 else 12097 { 12098 return keystoreType; 12099 } 12100 } 12101 12102 12103 12104 /** 12105 * Gets access to a keystore based on information included in command-line 12106 * arguments. 12107 * 12108 * @param keystoreType The keystore type for the keystore to access. 12109 * @param keystorePath The path to the keystore file. 12110 * @param keystorePassword The password to use to access the keystore. 12111 * 12112 * @return The configured keystore instance. 12113 * 12114 * @throws LDAPException If it is not possible to access the keystore. 12115 */ 12116 @NotNull() 12117 static KeyStore getKeystore(@NotNull final String keystoreType, 12118 @NotNull final File keystorePath, 12119 @Nullable final char[] keystorePassword) 12120 throws LDAPException 12121 { 12122 // Instantiate a keystore instance of the desired keystore type. 12123 final KeyStore keystore; 12124 try 12125 { 12126 if (keystoreType.equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11)) 12127 { 12128 // NOTE: For PKCS #11 key store types, the key store path will be 12129 // treated as the path to the provider configuration file. 12130 final Provider pkcs11Provider = PKCS11KeyManager.getProvider(null, 12131 keystorePath, keystoreType, true); 12132 keystore = CryptoHelper.getKeyStore(keystoreType, pkcs11Provider); 12133 } 12134 else if (keystoreType.equals(BCFKS_KEYSTORE_TYPE)) 12135 { 12136 keystore = CryptoHelper.getKeyStore(keystoreType, 12137 BouncyCastleFIPSHelper.getBouncyCastleFIPSProvider()); 12138 } 12139 else 12140 { 12141 keystore = CryptoHelper.getKeyStore(keystoreType); 12142 } 12143 } 12144 catch (final Exception e) 12145 { 12146 Debug.debugException(e); 12147 throw new LDAPException(ResultCode.LOCAL_ERROR, 12148 ERR_MANAGE_CERTS_CANNOT_INSTANTIATE_KS_TYPE.get(keystoreType, 12149 StaticUtils.getExceptionMessage(e)), 12150 e); 12151 } 12152 12153 12154 // Get an input stream that may be used to access the keystore. 12155 final InputStream inputStream; 12156 try 12157 { 12158 if (keystorePath.exists() && 12159 (! keystoreType.equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11))) 12160 { 12161 inputStream = new FileInputStream(keystorePath); 12162 } 12163 else 12164 { 12165 inputStream = null; 12166 } 12167 } 12168 catch (final Exception e) 12169 { 12170 Debug.debugException(e); 12171 throw new LDAPException(ResultCode.LOCAL_ERROR, 12172 ERR_MANAGE_CERTS_CANNOT_OPEN_KS_FILE_FOR_READING.get( 12173 keystorePath.getAbsolutePath(), 12174 StaticUtils.getExceptionMessage(e)), 12175 e); 12176 } 12177 12178 try 12179 { 12180 keystore.load(inputStream, keystorePassword); 12181 } 12182 catch (final Exception e) 12183 { 12184 Debug.debugException(e); 12185 final Throwable cause = e.getCause(); 12186 if ((e instanceof IOException) && (cause != null) && 12187 (cause instanceof UnrecoverableKeyException) && 12188 (keystorePassword != null)) 12189 { 12190 throw new LDAPException(ResultCode.PARAM_ERROR, 12191 ERR_MANAGE_CERTS_CANNOT_LOAD_KS_WRONG_PW.get( 12192 keystorePath.getAbsolutePath()), 12193 e); 12194 } 12195 else 12196 { 12197 throw new LDAPException(ResultCode.PARAM_ERROR, 12198 ERR_MANAGE_CERTS_ERROR_CANNOT_LOAD_KS.get( 12199 keystorePath.getAbsolutePath(), 12200 StaticUtils.getExceptionMessage(e)), 12201 e); 12202 } 12203 } 12204 finally 12205 { 12206 try 12207 { 12208 if (inputStream != null) 12209 { 12210 inputStream.close(); 12211 } 12212 } 12213 catch (final Exception e) 12214 { 12215 Debug.debugException(e); 12216 } 12217 } 12218 12219 return keystore; 12220 } 12221 12222 12223 12224 /** 12225 * Reads all of the certificates contained in the specified file. The file 12226 * must exist and may contain zero or more certificates that are either all in 12227 * PEM format or all in DER format. 12228 * 12229 * @param f The path to the certificate file to read. It must not be 12230 * {@code null}. 12231 * 12232 * @return A list of the certificates read from the specified file. 12233 * 12234 * @throws LDAPException If a problem is encountered while reading 12235 * certificates from the specified file. 12236 */ 12237 @NotNull() 12238 public static List<X509Certificate> readCertificatesFromFile( 12239 @NotNull final File f) 12240 throws LDAPException 12241 { 12242 // Read the first byte of the file to see if it contains DER-formatted data, 12243 // which we can determine by seeing if the first byte is 0x30. 12244 try (BufferedInputStream inputStream = 12245 new BufferedInputStream(new FileInputStream(f))) 12246 { 12247 inputStream.mark(1); 12248 final int firstByte = inputStream.read(); 12249 12250 if (firstByte < 0) 12251 { 12252 // This means that the file is empty. 12253 return Collections.emptyList(); 12254 } 12255 else 12256 { 12257 inputStream.reset(); 12258 } 12259 12260 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 12261 if ((firstByte & 0xFF) == 0x30) 12262 { 12263 // It is a DER-encoded file. Read ASN.1 elements and decode them as 12264 // X.509 certificates. 12265 while (true) 12266 { 12267 final ASN1Element certElement; 12268 try 12269 { 12270 certElement = ASN1Element.readFrom(inputStream); 12271 } 12272 catch (final Exception e) 12273 { 12274 Debug.debugException(e); 12275 throw new LDAPException(ResultCode.LOCAL_ERROR, 12276 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DER_NOT_VALID_ASN1.get( 12277 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12278 e); 12279 } 12280 12281 if (certElement == null) 12282 { 12283 // We've reached the end of the input stream. 12284 return certList; 12285 } 12286 12287 try 12288 { 12289 certList.add(new X509Certificate(certElement.encode())); 12290 } 12291 catch (final CertException e) 12292 { 12293 Debug.debugException(e); 12294 throw new LDAPException(ResultCode.PARAM_ERROR, 12295 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DER_NOT_VALID_CERT.get( 12296 f.getAbsolutePath(), e.getMessage()), 12297 e); 12298 } 12299 } 12300 } 12301 else 12302 { 12303 try (BufferedReader reader = 12304 new BufferedReader(new InputStreamReader(inputStream))) 12305 { 12306 boolean inCert = false; 12307 final StringBuilder buffer = new StringBuilder(); 12308 while (true) 12309 { 12310 String line = reader.readLine(); 12311 if (line == null) 12312 { 12313 if (inCert) 12314 { 12315 throw new LDAPException(ResultCode.PARAM_ERROR, 12316 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_EOF_WITHOUT_END.get( 12317 f.getAbsolutePath())); 12318 } 12319 12320 return certList; 12321 } 12322 12323 line = line.trim(); 12324 if (line.isEmpty() || line.startsWith("#")) 12325 { 12326 continue; 12327 } 12328 12329 if (line.equals("-----BEGIN CERTIFICATE-----")) 12330 { 12331 if (inCert) 12332 { 12333 throw new LDAPException(ResultCode.PARAM_ERROR, 12334 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_MULTIPLE_BEGIN.get( 12335 f.getAbsolutePath())); 12336 } 12337 else 12338 { 12339 inCert = true; 12340 } 12341 } 12342 else if (line.equals("-----END CERTIFICATE-----")) 12343 { 12344 if (! inCert) 12345 { 12346 throw new LDAPException(ResultCode.PARAM_ERROR, 12347 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_END_WITHOUT_BEGIN. 12348 get(f.getAbsolutePath())); 12349 } 12350 12351 inCert = false; 12352 final byte[] certBytes; 12353 try 12354 { 12355 certBytes = Base64.decode(buffer.toString()); 12356 } 12357 catch (final Exception e) 12358 { 12359 Debug.debugException(e); 12360 throw new LDAPException(ResultCode.PARAM_ERROR, 12361 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_PEM_CERT_NOT_BASE64. 12362 get(f.getAbsolutePath(), 12363 StaticUtils.getExceptionMessage(e)), 12364 e); 12365 } 12366 12367 try 12368 { 12369 certList.add(new X509Certificate(certBytes)); 12370 } 12371 catch (final CertException e) 12372 { 12373 Debug.debugException(e); 12374 throw new LDAPException(ResultCode.PARAM_ERROR, 12375 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_PEM_CERT_NOT_CERT. 12376 get(f.getAbsolutePath(), e.getMessage()), 12377 e); 12378 } 12379 12380 buffer.setLength(0); 12381 } 12382 else if (inCert) 12383 { 12384 buffer.append(line); 12385 } 12386 else 12387 { 12388 throw new LDAPException(ResultCode.PARAM_ERROR, 12389 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12390 f.getAbsolutePath())); 12391 } 12392 } 12393 } 12394 } 12395 } 12396 catch (final LDAPException le) 12397 { 12398 Debug.debugException(le); 12399 throw le; 12400 } 12401 catch (final Exception e) 12402 { 12403 Debug.debugException(e); 12404 throw new LDAPException(ResultCode.LOCAL_ERROR, 12405 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_READ_ERROR.get( 12406 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12407 e); 12408 } 12409 } 12410 12411 12412 12413 /** 12414 * Reads a private key from the specified file. The file must exist and must 12415 * contain exactly one PEM-encoded or DER-encoded PKCS #8 private key. 12416 * 12417 * @param f The path to the private key file to read. It 12418 * must not be {@code null}. 12419 * @param encryptionPassword The password to use to encrypt the private key. 12420 * It may be {@code null} if the private key is 12421 * not encrypted. 12422 * 12423 * @return The private key read from the file. 12424 * 12425 * @throws LDAPException If a problem is encountered while reading the 12426 * private key. 12427 */ 12428 @NotNull() 12429 static PKCS8PrivateKey readPrivateKeyFromFile(@NotNull final File f, 12430 @Nullable final char[] encryptionPassword) 12431 throws LDAPException 12432 { 12433 // Read the first byte of the file to see if it contains DER-formatted data, 12434 // which we can determine by seeing if the first byte is 0x30. 12435 try (BufferedInputStream inputStream = 12436 new BufferedInputStream(new FileInputStream(f))) 12437 { 12438 inputStream.mark(1); 12439 final int firstByte = inputStream.read(); 12440 12441 if (firstByte < 0) 12442 { 12443 // This means that the file is empty. 12444 throw new LDAPException(ResultCode.PARAM_ERROR, 12445 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12446 f.getAbsolutePath())); 12447 } 12448 else 12449 { 12450 inputStream.reset(); 12451 } 12452 12453 PKCS8PrivateKey privateKey = null; 12454 if ((firstByte & 0xFF) == 0x30) 12455 { 12456 // It is a DER-encoded file. Read an ASN.1 element and decode it as a 12457 // certificate. 12458 while (true) 12459 { 12460 final ASN1Element pkElement; 12461 try 12462 { 12463 pkElement = ASN1Element.readFrom(inputStream); 12464 } 12465 catch (final Exception e) 12466 { 12467 Debug.debugException(e); 12468 throw new LDAPException(ResultCode.LOCAL_ERROR, 12469 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DER_NOT_VALID_ASN1.get( 12470 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12471 e); 12472 } 12473 12474 if (pkElement == null) 12475 { 12476 // We've reached the end of the input stream. 12477 if (privateKey == null) 12478 { 12479 throw new LDAPException(ResultCode.PARAM_ERROR, 12480 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12481 f.getAbsolutePath())); 12482 } 12483 else 12484 { 12485 return privateKey; 12486 } 12487 } 12488 else if (privateKey == null) 12489 { 12490 try 12491 { 12492 if (encryptionPassword == null) 12493 { 12494 privateKey = new PKCS8PrivateKey(pkElement.encode()); 12495 } 12496 else 12497 { 12498 privateKey = PKCS8EncryptionHandler.decryptPrivateKey( 12499 pkElement.encode(), encryptionPassword); 12500 } 12501 } 12502 catch (final Exception e) 12503 { 12504 Debug.debugException(e); 12505 throw new LDAPException(ResultCode.PARAM_ERROR, 12506 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DER_NOT_VALID_PK.get( 12507 f.getAbsolutePath(), e.getMessage()), 12508 e); 12509 } 12510 } 12511 else 12512 { 12513 throw new LDAPException(ResultCode.PARAM_ERROR, 12514 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_KEYS.get( 12515 f.getAbsolutePath())); 12516 } 12517 } 12518 } 12519 else 12520 { 12521 try (BufferedReader reader = 12522 new BufferedReader(new InputStreamReader(inputStream))) 12523 { 12524 boolean inKey = false; 12525 boolean isRSAKey = false; 12526 boolean isEncryptedKey = false; 12527 final StringBuilder buffer = new StringBuilder(); 12528 while (true) 12529 { 12530 String line = reader.readLine(); 12531 if (line == null) 12532 { 12533 if (inKey) 12534 { 12535 throw new LDAPException(ResultCode.PARAM_ERROR, 12536 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EOF_WITHOUT_END.get( 12537 f.getAbsolutePath())); 12538 } 12539 12540 if (privateKey == null) 12541 { 12542 throw new LDAPException(ResultCode.PARAM_ERROR, 12543 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12544 f.getAbsolutePath())); 12545 } 12546 else 12547 { 12548 return privateKey; 12549 } 12550 } 12551 12552 line = line.trim(); 12553 if (line.isEmpty() || line.startsWith("#")) 12554 { 12555 continue; 12556 } 12557 12558 if (line.equals("-----BEGIN PRIVATE KEY-----") || 12559 line.equals("-----BEGIN RSA PRIVATE KEY-----") || 12560 line.equals("-----BEGIN ENCRYPTED PRIVATE KEY-----")) 12561 { 12562 if (inKey) 12563 { 12564 throw new LDAPException(ResultCode.PARAM_ERROR, 12565 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_BEGIN.get( 12566 f.getAbsolutePath())); 12567 } 12568 else if (privateKey != null) 12569 { 12570 throw new LDAPException(ResultCode.PARAM_ERROR, 12571 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_KEYS.get( 12572 f.getAbsolutePath())); 12573 } 12574 else 12575 { 12576 inKey = true; 12577 if (line.equals("-----BEGIN RSA PRIVATE KEY-----")) 12578 { 12579 isRSAKey = true; 12580 } 12581 else if (line.equals("-----BEGIN ENCRYPTED PRIVATE KEY-----")) 12582 { 12583 isEncryptedKey = true; 12584 if (encryptionPassword == null) 12585 { 12586 throw new LDAPException(ResultCode.PARAM_ERROR, 12587 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PK_ENCRYPTED_NO_PW. 12588 get(f.getAbsolutePath())); 12589 } 12590 } 12591 } 12592 } 12593 else if (line.equals("-----END PRIVATE KEY-----") || 12594 line.equals("-----END RSA PRIVATE KEY-----") || 12595 line.equals("-----END ENCRYPTED PRIVATE KEY-----")) 12596 { 12597 if (! inKey) 12598 { 12599 throw new LDAPException(ResultCode.PARAM_ERROR, 12600 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_END_WITHOUT_BEGIN.get( 12601 f.getAbsolutePath())); 12602 } 12603 12604 inKey = false; 12605 byte[] pkBytes; 12606 try 12607 { 12608 pkBytes = Base64.decode(buffer.toString()); 12609 } 12610 catch (final Exception e) 12611 { 12612 Debug.debugException(e); 12613 throw new LDAPException(ResultCode.PARAM_ERROR, 12614 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PEM_PK_NOT_BASE64.get( 12615 f.getAbsolutePath(), 12616 StaticUtils.getExceptionMessage(e)), 12617 e); 12618 } 12619 12620 if (isRSAKey) 12621 { 12622 pkBytes = PKCS8PrivateKey.wrapRSAPrivateKey(pkBytes); 12623 } 12624 12625 try 12626 { 12627 if (isEncryptedKey) 12628 { 12629 privateKey = PKCS8EncryptionHandler. 12630 decryptPrivateKey(pkBytes, encryptionPassword); 12631 } 12632 else 12633 { 12634 privateKey = new PKCS8PrivateKey(pkBytes); 12635 } 12636 } 12637 catch (final CertException e) 12638 { 12639 Debug.debugException(e); 12640 throw new LDAPException(ResultCode.PARAM_ERROR, 12641 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PEM_PK_NOT_PK.get( 12642 f.getAbsolutePath(), e.getMessage()), 12643 e); 12644 } 12645 12646 buffer.setLength(0); 12647 } 12648 else if (inKey) 12649 { 12650 buffer.append(line); 12651 } 12652 else 12653 { 12654 throw new LDAPException(ResultCode.PARAM_ERROR, 12655 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12656 f.getAbsolutePath())); 12657 } 12658 } 12659 } 12660 } 12661 } 12662 catch (final LDAPException le) 12663 { 12664 Debug.debugException(le); 12665 throw le; 12666 } 12667 catch (final Exception e) 12668 { 12669 Debug.debugException(e); 12670 throw new LDAPException(ResultCode.LOCAL_ERROR, 12671 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_READ_ERROR.get( 12672 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12673 e); 12674 } 12675 } 12676 12677 12678 12679 /** 12680 * Reads a certificate signing request from the specified file. The file must 12681 * exist and must contain exactly one PEM-encoded or DER-encoded PKCS #10 12682 * certificate signing request. 12683 * 12684 * @param f The path to the private key file to read. It must not be 12685 * {@code null}. 12686 * 12687 * @return The certificate signing request read from the file. 12688 * 12689 * @throws LDAPException If a problem is encountered while reading the 12690 * certificate signing request. 12691 */ 12692 @NotNull() 12693 public static PKCS10CertificateSigningRequest 12694 readCertificateSigningRequestFromFile( 12695 @NotNull final File f) 12696 throws LDAPException 12697 { 12698 // Read the first byte of the file to see if it contains DER-formatted data, 12699 // which we can determine by seeing if the first byte is 0x30. 12700 try (BufferedInputStream inputStream = 12701 new BufferedInputStream(new FileInputStream(f))) 12702 { 12703 inputStream.mark(1); 12704 final int firstByte = inputStream.read(); 12705 12706 if (firstByte < 0) 12707 { 12708 // This means that the file is empty. 12709 throw new LDAPException(ResultCode.PARAM_ERROR, 12710 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12711 f.getAbsolutePath())); 12712 } 12713 else 12714 { 12715 inputStream.reset(); 12716 } 12717 12718 PKCS10CertificateSigningRequest csr = null; 12719 if ((firstByte & 0xFF) == 0x30) 12720 { 12721 // It is a DER-encoded file. Read an ASN.1 element and decode it as a 12722 // certificate. 12723 while (true) 12724 { 12725 final ASN1Element csrElement; 12726 try 12727 { 12728 csrElement = ASN1Element.readFrom(inputStream); 12729 } 12730 catch (final Exception e) 12731 { 12732 Debug.debugException(e); 12733 throw new LDAPException(ResultCode.LOCAL_ERROR, 12734 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DER_NOT_VALID_ASN1.get( 12735 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12736 e); 12737 } 12738 12739 if (csrElement == null) 12740 { 12741 // We've reached the end of the input stream. 12742 if (csr == null) 12743 { 12744 throw new LDAPException(ResultCode.PARAM_ERROR, 12745 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12746 f.getAbsolutePath())); 12747 } 12748 else 12749 { 12750 return csr; 12751 } 12752 } 12753 else if (csr == null) 12754 { 12755 try 12756 { 12757 csr = new PKCS10CertificateSigningRequest(csrElement.encode()); 12758 } 12759 catch (final Exception e) 12760 { 12761 Debug.debugException(e); 12762 throw new LDAPException(ResultCode.PARAM_ERROR, 12763 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DER_NOT_VALID_CSR.get( 12764 f.getAbsolutePath(), e.getMessage()), 12765 e); 12766 } 12767 } 12768 else 12769 { 12770 throw new LDAPException(ResultCode.PARAM_ERROR, 12771 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_CSRS.get( 12772 f.getAbsolutePath())); 12773 } 12774 } 12775 } 12776 else 12777 { 12778 try (BufferedReader reader = 12779 new BufferedReader(new InputStreamReader(inputStream))) 12780 { 12781 boolean inCSR = false; 12782 final StringBuilder buffer = new StringBuilder(); 12783 while (true) 12784 { 12785 String line = reader.readLine(); 12786 if (line == null) 12787 { 12788 if (inCSR) 12789 { 12790 throw new LDAPException(ResultCode.PARAM_ERROR, 12791 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EOF_WITHOUT_END.get( 12792 f.getAbsolutePath())); 12793 } 12794 12795 if (csr == null) 12796 { 12797 throw new LDAPException(ResultCode.PARAM_ERROR, 12798 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12799 f.getAbsolutePath())); 12800 } 12801 else 12802 { 12803 return csr; 12804 } 12805 } 12806 12807 line = line.trim(); 12808 if (line.isEmpty() || line.startsWith("#")) 12809 { 12810 continue; 12811 } 12812 12813 if (line.equals("-----BEGIN CERTIFICATE REQUEST-----") || 12814 line.equals("-----BEGIN NEW CERTIFICATE REQUEST-----")) 12815 { 12816 if (inCSR) 12817 { 12818 throw new LDAPException(ResultCode.PARAM_ERROR, 12819 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_BEGIN.get( 12820 f.getAbsolutePath())); 12821 } 12822 else if (csr != null) 12823 { 12824 throw new LDAPException(ResultCode.PARAM_ERROR, 12825 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_CSRS.get( 12826 f.getAbsolutePath())); 12827 } 12828 else 12829 { 12830 inCSR = true; 12831 } 12832 } 12833 else if (line.equals("-----END CERTIFICATE REQUEST-----") || 12834 line.equals("-----END NEW CERTIFICATE REQUEST-----")) 12835 { 12836 if (! inCSR) 12837 { 12838 throw new LDAPException(ResultCode.PARAM_ERROR, 12839 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_END_WITHOUT_BEGIN.get( 12840 f.getAbsolutePath())); 12841 } 12842 12843 inCSR = false; 12844 final byte[] csrBytes; 12845 try 12846 { 12847 csrBytes = Base64.decode(buffer.toString()); 12848 } 12849 catch (final Exception e) 12850 { 12851 Debug.debugException(e); 12852 throw new LDAPException(ResultCode.PARAM_ERROR, 12853 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_PEM_CSR_NOT_BASE64.get( 12854 f.getAbsolutePath(), 12855 StaticUtils.getExceptionMessage(e)), 12856 e); 12857 } 12858 12859 try 12860 { 12861 csr = new PKCS10CertificateSigningRequest(csrBytes); 12862 } 12863 catch (final CertException e) 12864 { 12865 Debug.debugException(e); 12866 throw new LDAPException(ResultCode.PARAM_ERROR, 12867 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_PEM_CSR_NOT_CSR.get( 12868 f.getAbsolutePath(), e.getMessage()), 12869 e); 12870 } 12871 12872 buffer.setLength(0); 12873 } 12874 else if (inCSR) 12875 { 12876 buffer.append(line); 12877 } 12878 else 12879 { 12880 throw new LDAPException(ResultCode.PARAM_ERROR, 12881 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12882 f.getAbsolutePath())); 12883 } 12884 } 12885 } 12886 } 12887 } 12888 catch (final LDAPException le) 12889 { 12890 Debug.debugException(le); 12891 throw le; 12892 } 12893 catch (final Exception e) 12894 { 12895 Debug.debugException(e); 12896 throw new LDAPException(ResultCode.LOCAL_ERROR, 12897 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_READ_ERROR.get( 12898 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12899 e); 12900 } 12901 } 12902 12903 12904 12905 /** 12906 * Retrieves a colon-delimited hexadecimal representation of the contents of 12907 * the provided byte array. 12908 * 12909 * @param bytes The byte array for which to get the hexadecimal 12910 * representation. It must not be {@code null}. 12911 * 12912 * @return A colon-delimited hexadecimal representation of the contents of 12913 * the provided byte array. 12914 */ 12915 @NotNull() 12916 private static String toColonDelimitedHex(@NotNull final byte... bytes) 12917 { 12918 final StringBuilder buffer = new StringBuilder(bytes.length * 3); 12919 StaticUtils.toHex(bytes, ":", buffer); 12920 return buffer.toString(); 12921 } 12922 12923 12924 12925 /** 12926 * Retrieves a formatted representation of the provided date in a 12927 * human-readable format that includes an offset from the current time. 12928 * 12929 * @param d The date to format. It must not be {@code null}. 12930 * 12931 * @return A formatted representation of the provided date. 12932 */ 12933 @NotNull() 12934 private static String formatDateAndTime(@NotNull final Date d) 12935 { 12936 // Example: Sunday, January 1, 2017 12937 final String dateFormatString = "EEEE, MMMM d, yyyy"; 12938 final String formattedDate = 12939 new SimpleDateFormat(dateFormatString).format(d); 12940 12941 // Example: 12:34:56 AM CDT 12942 final String timeFormatString = "hh:mm:ss aa z"; 12943 final String formattedTime = 12944 new SimpleDateFormat(timeFormatString).format(d); 12945 12946 final long providedTime = d.getTime(); 12947 final long currentTime = System.currentTimeMillis(); 12948 if (providedTime > currentTime) 12949 { 12950 final long secondsInFuture = ((providedTime - currentTime) / 1000L); 12951 final String durationInFuture = 12952 StaticUtils.secondsToHumanReadableDuration(secondsInFuture); 12953 return INFO_MANAGE_CERTS_FORMAT_DATE_AND_TIME_IN_FUTURE.get(formattedDate, 12954 formattedTime, durationInFuture); 12955 } 12956 else 12957 { 12958 final long secondsInPast = ((currentTime - providedTime) / 1000L); 12959 final String durationInPast = 12960 StaticUtils.secondsToHumanReadableDuration(secondsInPast); 12961 return INFO_MANAGE_CERTS_FORMAT_DATE_AND_TIME_IN_PAST.get(formattedDate, 12962 formattedTime, durationInPast); 12963 } 12964 } 12965 12966 12967 12968 /** 12969 * Retrieves a formatted representation of the provided date in a format 12970 * suitable for use as the validity start time value provided to the keytool 12971 * command. 12972 * 12973 * @param d The date to format. It must not be {@code null}. 12974 * 12975 * @return A formatted representation of the provided date. 12976 */ 12977 @NotNull() 12978 private static String formatValidityStartTime(@NotNull final Date d) 12979 { 12980 // Example: 2017/01/01 01:23:45 12981 final String dateFormatString = "yyyy'/'MM'/'dd HH':'mm':'ss"; 12982 return new SimpleDateFormat(dateFormatString).format(d); 12983 } 12984 12985 12986 12987 /** 12988 * Retrieves the certificate chain for the specified certificate from the 12989 * given keystore. If any issuer certificate is not in the provided keystore, 12990 * then the JVM-default trust store will be checked to see if it can be found 12991 * there. 12992 * 12993 * @param alias The alias of the certificate for which to get the 12994 * certificate chain. This must not be 12995 * {@code null}. 12996 * @param keystore The keystore from which to get the certificate 12997 * chain. This must not be {@code null}. 12998 * @param missingIssuerRef A reference that will be updated with the DN of a 12999 * missing issuer certificate, if any certificate in 13000 * the chain cannot be located. This must not be 13001 * {@code null}. 13002 * 13003 * @return The certificate chain for the specified certificate, or an empty 13004 * array if no certificate exists with the specified alias. 13005 * 13006 * @throws LDAPException If a problem is encountered while getting the 13007 * certificate chain. 13008 */ 13009 @NotNull() 13010 private static X509Certificate[] getCertificateChain( 13011 @NotNull final String alias, 13012 @NotNull final KeyStore keystore, 13013 @NotNull final AtomicReference<DN> missingIssuerRef) 13014 throws LDAPException 13015 { 13016 try 13017 { 13018 // First, see if the keystore will give us the certificate chain. This 13019 // will only happen if the alias references an entry that includes the 13020 // private key, but it will save us a lot of work. 13021 final Certificate[] chain = keystore.getCertificateChain(alias); 13022 if ((chain != null) && (chain.length > 0)) 13023 { 13024 final X509Certificate[] x509Chain = new X509Certificate[chain.length]; 13025 for (int i=0; i < chain.length; i++) 13026 { 13027 x509Chain[i] = new X509Certificate(chain[i].getEncoded()); 13028 } 13029 return x509Chain; 13030 } 13031 13032 13033 // We couldn't get the keystore to give us the chain, but see if we can 13034 // get a certificate with the specified alias. 13035 final Certificate endCert = keystore.getCertificate(alias); 13036 if (endCert == null) 13037 { 13038 // This means there isn't any certificate with the specified alias. 13039 // Return an empty chain. 13040 return new X509Certificate[0]; 13041 } 13042 13043 final ArrayList<X509Certificate> chainList = new ArrayList<>(5); 13044 X509Certificate certificate = new X509Certificate(endCert.getEncoded()); 13045 chainList.add(certificate); 13046 13047 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 13048 new AtomicReference<>(); 13049 while (true) 13050 { 13051 final X509Certificate issuerCertificate = 13052 getIssuerCertificate(certificate, keystore, 13053 jvmDefaultTrustStoreRef, missingIssuerRef); 13054 if (issuerCertificate == null) 13055 { 13056 break; 13057 } 13058 13059 chainList.add(issuerCertificate); 13060 certificate = issuerCertificate; 13061 } 13062 13063 final X509Certificate[] x509Chain = new X509Certificate[chainList.size()]; 13064 return chainList.toArray(x509Chain); 13065 } 13066 catch (final Exception e) 13067 { 13068 Debug.debugException(e); 13069 throw new LDAPException(ResultCode.LOCAL_ERROR, 13070 ERR_MANAGE_CERTS_GET_CHAIN_ERROR.get(alias, 13071 StaticUtils.getExceptionMessage(e)), 13072 e); 13073 } 13074 } 13075 13076 13077 13078 /** 13079 * Attempts to retrieve the issuer certificate for the provided certificate 13080 * from the given keystore or the JVM-default trust store. 13081 * 13082 * @param certificate The certificate for which to retrieve the 13083 * issuer certificate. 13084 * @param keystore The keystore in which to look for the 13085 * issuer certificate. 13086 * @param jvmDefaultTrustStoreRef A reference that will be used to hold the 13087 * JVM-default trust store if it is obtained 13088 * in the process of retrieving the issuer 13089 * certificate. 13090 * @param missingIssuerRef A reference that will be updated with the 13091 * DN of a missing issuer certificate, if any 13092 * certificate in the chain cannot be 13093 * located. This must not be {@code null}. 13094 * 13095 * @return The issuer certificate for the provided certificate, or 13096 * {@code null} if the issuer certificate could not be retrieved. 13097 * 13098 * @throws Exception If a problem is encountered while trying to retrieve 13099 * the issuer certificate. 13100 */ 13101 @Nullable() 13102 private static X509Certificate getIssuerCertificate( 13103 @NotNull final X509Certificate certificate, 13104 @NotNull final KeyStore keystore, 13105 @NotNull final AtomicReference<KeyStore> jvmDefaultTrustStoreRef, 13106 @NotNull final AtomicReference<DN> missingIssuerRef) 13107 throws Exception 13108 { 13109 final DN subjectDN = certificate.getSubjectDN(); 13110 final DN issuerDN = certificate.getIssuerDN(); 13111 if (subjectDN.equals(issuerDN)) 13112 { 13113 // This means that the certificate is self-signed, so there is no issuer. 13114 return null; 13115 } 13116 13117 13118 // See if we can find the issuer certificate in the provided keystore. 13119 X509Certificate issuerCertificate = getIssuerCertificate(certificate, 13120 keystore); 13121 if (issuerCertificate != null) 13122 { 13123 return issuerCertificate; 13124 } 13125 13126 13127 // See if we can get the JVM-default trust store. 13128 KeyStore jvmDefaultTrustStore = jvmDefaultTrustStoreRef.get(); 13129 if (jvmDefaultTrustStore == null) 13130 { 13131 if (JVM_DEFAULT_CACERTS_FILE == null) 13132 { 13133 missingIssuerRef.set(issuerDN); 13134 return null; 13135 } 13136 13137 final String[] keystoreTypes = 13138 { 13139 CryptoHelper.KEY_STORE_TYPE_JKS, 13140 CryptoHelper.KEY_STORE_TYPE_PKCS_12, 13141 BouncyCastleFIPSHelper.FIPS_KEY_STORE_TYPE 13142 }; 13143 13144 for (final String keystoreType : keystoreTypes) 13145 { 13146 try 13147 { 13148 final KeyStore ks = 13149 CryptoHelper.getKeyStore(keystoreType, null, true); 13150 try (FileInputStream inputStream = 13151 new FileInputStream(JVM_DEFAULT_CACERTS_FILE)) 13152 { 13153 ks.load(inputStream, null); 13154 jvmDefaultTrustStore = ks; 13155 jvmDefaultTrustStoreRef.set(jvmDefaultTrustStore); 13156 break; 13157 } 13158 } 13159 catch (final Exception e) 13160 { 13161 Debug.debugException(e); 13162 } 13163 } 13164 } 13165 13166 if (jvmDefaultTrustStore != null) 13167 { 13168 issuerCertificate = getIssuerCertificate(certificate, 13169 jvmDefaultTrustStore); 13170 } 13171 13172 if (issuerCertificate == null) 13173 { 13174 missingIssuerRef.set(issuerDN); 13175 } 13176 13177 return issuerCertificate; 13178 } 13179 13180 13181 13182 /** 13183 * Attempts to retrieve the issuer certificate for the provided certificate 13184 * from the given keystore. 13185 * 13186 * @param certificate The certificate for which to retrieve the issuer 13187 * certificate. 13188 * @param keystore The keystore in which to look for the issuer 13189 * certificate. 13190 * 13191 * @return The issuer certificate for the provided certificate, or 13192 * {@code null} if the issuer certificate could not be retrieved. 13193 * 13194 * @throws Exception If a problem is encountered while trying to retrieve 13195 * the issuer certificate. 13196 */ 13197 @Nullable() 13198 private static X509Certificate getIssuerCertificate( 13199 @NotNull final X509Certificate certificate, 13200 @NotNull final KeyStore keystore) 13201 throws Exception 13202 { 13203 final Enumeration<String> aliases = keystore.aliases(); 13204 while (aliases.hasMoreElements()) 13205 { 13206 final String alias = aliases.nextElement(); 13207 13208 Certificate[] certs = null; 13209 if (hasCertificateAlias(keystore, alias)) 13210 { 13211 final Certificate c = keystore.getCertificate(alias); 13212 if (c == null) 13213 { 13214 continue; 13215 } 13216 13217 certs = new Certificate[] { c }; 13218 } 13219 else if (hasKeyAlias(keystore, alias)) 13220 { 13221 certs = keystore.getCertificateChain(alias); 13222 } 13223 13224 if (certs != null) 13225 { 13226 for (final Certificate c : certs) 13227 { 13228 final X509Certificate xc = new X509Certificate(c.getEncoded()); 13229 if (xc.isIssuerFor(certificate)) 13230 { 13231 return xc; 13232 } 13233 } 13234 } 13235 } 13236 13237 return null; 13238 } 13239 13240 13241 13242 /** 13243 * Retrieves the authority key identifier value for the provided certificate, 13244 * if present. 13245 * 13246 * @param c The certificate for which to retrieve the authority key 13247 * identifier. 13248 * 13249 * @return The authority key identifier value for the provided certificate, 13250 * or {@code null} if the certificate does not have an authority 13251 * key identifier. 13252 */ 13253 @Nullable() 13254 private static byte[] getAuthorityKeyIdentifier( 13255 @NotNull final X509Certificate c) 13256 { 13257 for (final X509CertificateExtension extension : c.getExtensions()) 13258 { 13259 if (extension instanceof AuthorityKeyIdentifierExtension) 13260 { 13261 final AuthorityKeyIdentifierExtension e = 13262 (AuthorityKeyIdentifierExtension) extension; 13263 if (e.getKeyIdentifier() != null) 13264 { 13265 return e.getKeyIdentifier().getValue(); 13266 } 13267 } 13268 } 13269 13270 return null; 13271 } 13272 13273 13274 13275 /** 13276 * Writes the provided keystore to the specified file. If the keystore file 13277 * already exists, a new temporary file will be created, the old file renamed 13278 * out of the way, the new file renamed into place, and the old file deleted. 13279 * If the keystore file does not exist, then it will simply be created in the 13280 * correct place. 13281 * 13282 * @param keystore The keystore to be written. 13283 * @param keystorePath The path to the keystore file to be written. 13284 * @param keystorePassword The password to use for the keystore. 13285 * 13286 * @throws LDAPException If a problem is encountered while writing the 13287 * keystore. 13288 */ 13289 static void writeKeystore(@NotNull final KeyStore keystore, 13290 @NotNull final File keystorePath, 13291 @Nullable final char[] keystorePassword) 13292 throws LDAPException 13293 { 13294 // If the key store type is PKCS #11, then we don't need to worry about a 13295 // key store file. 13296 if (keystore.getType().equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11)) 13297 { 13298 try 13299 { 13300 keystore.store(null); 13301 return; 13302 } 13303 catch (final Exception e) 13304 { 13305 Debug.debugException(e); 13306 throw new LDAPException(ResultCode.LOCAL_ERROR, 13307 ERR_MANAGE_CERTS_PKCS11_WRITE_ERROR.get( 13308 StaticUtils.getExceptionMessage(e)), 13309 e); 13310 } 13311 } 13312 13313 13314 File copyOfExistingKeystore = null; 13315 final String timestamp = 13316 StaticUtils.encodeGeneralizedTime(System.currentTimeMillis()); 13317 if (keystorePath.exists()) 13318 { 13319 copyOfExistingKeystore = new File(keystorePath.getAbsolutePath() + 13320 ".backup-" + timestamp); 13321 try 13322 { 13323 Files.copy(keystorePath.toPath(), copyOfExistingKeystore.toPath()); 13324 } 13325 catch (final Exception e) 13326 { 13327 Debug.debugException(e); 13328 throw new LDAPException(ResultCode.LOCAL_ERROR, 13329 ERR_MANAGE_CERTS_WRITE_KS_ERROR_COPYING_EXISTING_KS.get( 13330 keystorePath.getAbsolutePath(), 13331 copyOfExistingKeystore.getAbsolutePath(), 13332 StaticUtils.getExceptionMessage(e)), 13333 e); 13334 } 13335 } 13336 13337 try (FileOutputStream outputStream = new FileOutputStream(keystorePath)) 13338 { 13339 keystore.store(outputStream, keystorePassword); 13340 } 13341 catch (final Exception e) 13342 { 13343 Debug.debugException(e); 13344 if (copyOfExistingKeystore == null) 13345 { 13346 throw new LDAPException(ResultCode.LOCAL_ERROR, 13347 ERR_MANAGE_CERTS_WRITE_KS_ERROR_WRITING_NEW_KS.get( 13348 keystorePath.getAbsolutePath(), 13349 StaticUtils.getExceptionMessage(e)), 13350 e); 13351 } 13352 else 13353 { 13354 throw new LDAPException(ResultCode.LOCAL_ERROR, 13355 ERR_MANAGE_CERTS_WRITE_KS_ERROR_OVERWRITING_KS.get( 13356 keystorePath.getAbsolutePath(), 13357 StaticUtils.getExceptionMessage(e), 13358 copyOfExistingKeystore.getAbsolutePath()), 13359 e); 13360 } 13361 } 13362 13363 if (copyOfExistingKeystore != null) 13364 { 13365 try 13366 { 13367 Files.delete(copyOfExistingKeystore.toPath()); 13368 } 13369 catch (final Exception e) 13370 { 13371 Debug.debugException(e); 13372 throw new LDAPException(ResultCode.LOCAL_ERROR, 13373 ERR_MANAGE_CERTS_WRITE_KS_ERROR_DELETING_KS_BACKUP.get( 13374 copyOfExistingKeystore.getAbsolutePath(), 13375 keystorePath.getAbsolutePath(), 13376 StaticUtils.getExceptionMessage(e)), 13377 e); 13378 } 13379 } 13380 } 13381 13382 13383 13384 /** 13385 * Indicates whether the provided keystore has a certificate entry with the 13386 * specified alias. 13387 * 13388 * @param keystore The keystore to examine. 13389 * @param alias The alias for which to make the determination. 13390 * 13391 * @return {@code true} if the keystore has a certificate entry with the 13392 * specified alias, or {@code false} if the alias doesn't exist or 13393 * is associated with some other type of entry (like a key). 13394 */ 13395 private static boolean hasCertificateAlias(@NotNull final KeyStore keystore, 13396 @NotNull final String alias) 13397 { 13398 try 13399 { 13400 return keystore.isCertificateEntry(alias); 13401 } 13402 catch (final Exception e) 13403 { 13404 // This should never happen. If it does, then we'll assume the alias 13405 // doesn't exist or isn't associated with a certificate. 13406 Debug.debugException(e); 13407 return false; 13408 } 13409 } 13410 13411 13412 13413 /** 13414 * Indicates whether the provided keystore has a key entry with the specified 13415 * alias. 13416 * 13417 * @param keystore The keystore to examine. 13418 * @param alias The alias for which to make the determination. 13419 * 13420 * @return {@code true} if the keystore has a key entry with the specified 13421 * alias, or {@code false} if the alias doesn't exist or is 13422 * associated with some other type of entry (like a certificate). 13423 */ 13424 private static boolean hasKeyAlias(@NotNull final KeyStore keystore, 13425 @NotNull final String alias) 13426 { 13427 try 13428 { 13429 return keystore.isKeyEntry(alias); 13430 } 13431 catch (final Exception e) 13432 { 13433 // This should never happen. If it does, then we'll assume the alias 13434 // doesn't exist or isn't associated with a key. 13435 Debug.debugException(e); 13436 return false; 13437 } 13438 } 13439 13440 13441 13442 /** 13443 * Adds arguments for each of the provided extensions to the given list. 13444 * 13445 * @param keytoolArguments The list to which the extension arguments should 13446 * be added. 13447 * @param basicConstraints The basic constraints extension to include. It 13448 * may be {@code null} if this extension should not 13449 * be included. 13450 * @param keyUsage The key usage extension to include. It may be 13451 * {@code null} if this extension should not be 13452 * included. 13453 * @param extendedKeyUsage The extended key usage extension to include. It 13454 * may be {@code null} if this extension should not 13455 * be included. 13456 * @param sanValues The list of subject alternative name values to 13457 * include. It must not be {@code null} but may be 13458 * empty. 13459 * @param ianValues The list of issuer alternative name values to 13460 * include. It must not be {@code null} but may be 13461 * empty. 13462 * @param genericExtensions The list of generic extensions to include. It 13463 * must not be {@code null} but may be empty. 13464 */ 13465 private static void addExtensionArguments( 13466 @NotNull final List<String> keytoolArguments, 13467 @Nullable final BasicConstraintsExtension basicConstraints, 13468 @Nullable final KeyUsageExtension keyUsage, 13469 @Nullable final ExtendedKeyUsageExtension extendedKeyUsage, 13470 @NotNull final Set<String> sanValues, 13471 @NotNull final Set<String> ianValues, 13472 @NotNull final List<X509CertificateExtension> genericExtensions) 13473 { 13474 if (basicConstraints != null) 13475 { 13476 final StringBuilder basicConstraintsValue = new StringBuilder(); 13477 basicConstraintsValue.append("ca:"); 13478 basicConstraintsValue.append(basicConstraints.isCA()); 13479 13480 if (basicConstraints.getPathLengthConstraint() != null) 13481 { 13482 basicConstraintsValue.append(",pathlen:"); 13483 basicConstraintsValue.append( 13484 basicConstraints.getPathLengthConstraint()); 13485 } 13486 13487 keytoolArguments.add("-ext"); 13488 keytoolArguments.add("BasicConstraints=" + basicConstraintsValue); 13489 } 13490 13491 if (keyUsage != null) 13492 { 13493 final StringBuilder keyUsageValue = new StringBuilder(); 13494 if (keyUsage.isDigitalSignatureBitSet()) 13495 { 13496 commaAppend(keyUsageValue, "digitalSignature"); 13497 } 13498 13499 if (keyUsage.isNonRepudiationBitSet()) 13500 { 13501 commaAppend(keyUsageValue, "nonRepudiation"); 13502 } 13503 13504 if (keyUsage.isKeyEnciphermentBitSet()) 13505 { 13506 commaAppend(keyUsageValue, "keyEncipherment"); 13507 } 13508 13509 if (keyUsage.isDataEnciphermentBitSet()) 13510 { 13511 commaAppend(keyUsageValue, "dataEncipherment"); 13512 } 13513 13514 if (keyUsage.isKeyAgreementBitSet()) 13515 { 13516 commaAppend(keyUsageValue, "keyAgreement"); 13517 } 13518 13519 if (keyUsage.isKeyCertSignBitSet()) 13520 { 13521 commaAppend(keyUsageValue, "keyCertSign"); 13522 } 13523 13524 if (keyUsage.isCRLSignBitSet()) 13525 { 13526 commaAppend(keyUsageValue, "cRLSign"); 13527 } 13528 13529 if (keyUsage.isEncipherOnlyBitSet()) 13530 { 13531 commaAppend(keyUsageValue, "encipherOnly"); 13532 } 13533 13534 if (keyUsage.isEncipherOnlyBitSet()) 13535 { 13536 commaAppend(keyUsageValue, "decipherOnly"); 13537 } 13538 13539 keytoolArguments.add("-ext"); 13540 keytoolArguments.add("KeyUsage=" + keyUsageValue); 13541 } 13542 13543 if (extendedKeyUsage != null) 13544 { 13545 final StringBuilder extendedKeyUsageValue = new StringBuilder(); 13546 for (final OID oid : extendedKeyUsage.getKeyPurposeIDs()) 13547 { 13548 final ExtendedKeyUsageID id = ExtendedKeyUsageID.forOID(oid); 13549 if (id == null) 13550 { 13551 commaAppend(extendedKeyUsageValue, oid.toString()); 13552 } 13553 else 13554 { 13555 switch (id) 13556 { 13557 case TLS_SERVER_AUTHENTICATION: 13558 commaAppend(extendedKeyUsageValue, "serverAuth"); 13559 break; 13560 case TLS_CLIENT_AUTHENTICATION: 13561 commaAppend(extendedKeyUsageValue, "clientAuth"); 13562 break; 13563 case CODE_SIGNING: 13564 commaAppend(extendedKeyUsageValue, "codeSigning"); 13565 break; 13566 case EMAIL_PROTECTION: 13567 commaAppend(extendedKeyUsageValue, "emailProtection"); 13568 break; 13569 case TIME_STAMPING: 13570 commaAppend(extendedKeyUsageValue, "timeStamping"); 13571 break; 13572 case OCSP_SIGNING: 13573 commaAppend(extendedKeyUsageValue, "OCSPSigning"); 13574 break; 13575 default: 13576 // This should never happen. 13577 commaAppend(extendedKeyUsageValue, id.getOID().toString()); 13578 break; 13579 } 13580 } 13581 } 13582 13583 keytoolArguments.add("-ext"); 13584 keytoolArguments.add("ExtendedKeyUsage=" + extendedKeyUsageValue); 13585 } 13586 13587 if (! sanValues.isEmpty()) 13588 { 13589 final StringBuilder subjectAltNameValue = new StringBuilder(); 13590 for (final String sanValue : sanValues) 13591 { 13592 commaAppend(subjectAltNameValue, sanValue); 13593 } 13594 13595 keytoolArguments.add("-ext"); 13596 keytoolArguments.add("SAN=" + subjectAltNameValue); 13597 } 13598 13599 if (! ianValues.isEmpty()) 13600 { 13601 final StringBuilder issuerAltNameValue = new StringBuilder(); 13602 for (final String ianValue : ianValues) 13603 { 13604 commaAppend(issuerAltNameValue, ianValue); 13605 } 13606 13607 keytoolArguments.add("-ext"); 13608 keytoolArguments.add("IAN=" + issuerAltNameValue); 13609 } 13610 13611 for (final X509CertificateExtension e : genericExtensions) 13612 { 13613 keytoolArguments.add("-ext"); 13614 if (e.isCritical()) 13615 { 13616 keytoolArguments.add(e.getOID().toString() + ":critical=" + 13617 toColonDelimitedHex(e.getValue())); 13618 } 13619 else 13620 { 13621 keytoolArguments.add(e.getOID().toString() + '=' + 13622 toColonDelimitedHex(e.getValue())); 13623 } 13624 } 13625 } 13626 13627 13628 13629 /** 13630 * Appends the provided value to the given buffer. If the buffer is not 13631 * empty, the new value will be preceded by a comma. There will not be any 13632 * spaces on either side of the comma. 13633 * 13634 * @param buffer The buffer to which the value should be appended. 13635 * @param value The value to append to the buffer. 13636 */ 13637 private static void commaAppend(@NotNull final StringBuilder buffer, 13638 @NotNull final String value) 13639 { 13640 if (buffer.length() > 0) 13641 { 13642 buffer.append(','); 13643 } 13644 13645 buffer.append(value); 13646 } 13647 13648 13649 13650 /** 13651 * Retrieves a set of information that may be used to generate example usage 13652 * information. Each element in the returned map should consist of a map 13653 * between an example set of arguments and a string that describes the 13654 * behavior of the tool when invoked with that set of arguments. 13655 * 13656 * @return A set of information that may be used to generate example usage 13657 * information. It may be {@code null} or empty if no example usage 13658 * information is available. 13659 */ 13660 @Override() 13661 @NotNull() 13662 public LinkedHashMap<String[],String> getExampleUsages() 13663 { 13664 final String keystorePath = getPlatformSpecificPath("config", "keystore"); 13665 final String keystorePWPath = 13666 getPlatformSpecificPath("config", "keystore.pin"); 13667 final String privateKeyPWPath = 13668 getPlatformSpecificPath("config", "server-cert-private-key.pin"); 13669 final String exportCertOutputFile = 13670 getPlatformSpecificPath("server-cert.crt"); 13671 final String exportKeyOutputFile = 13672 getPlatformSpecificPath("server-cert.private-key"); 13673 final String genCSROutputFile = getPlatformSpecificPath("server-cert.csr"); 13674 final String truststorePath = 13675 getPlatformSpecificPath("config", "truststore"); 13676 final String truststorePWPath = 13677 getPlatformSpecificPath("config", "truststore.pin"); 13678 13679 final LinkedHashMap<String[],String> examples = 13680 new LinkedHashMap<>(StaticUtils.computeMapCapacity(20)); 13681 13682 examples.put( 13683 new String[] 13684 { 13685 "list-certificates", 13686 "--keystore", keystorePath, 13687 "--keystore-password-file", keystorePWPath, 13688 "--verbose", 13689 "--display-keytool-command" 13690 }, 13691 INFO_MANAGE_CERTS_EXAMPLE_LIST_1.get(keystorePath)); 13692 13693 examples.put( 13694 new String[] 13695 { 13696 "export-certificate", 13697 "--keystore", keystorePath, 13698 "--keystore-password-file", keystorePWPath, 13699 "--alias", "server-cert", 13700 "--output-file", exportCertOutputFile, 13701 "--output-format", "PEM", 13702 "--verbose", 13703 "--display-keytool-command" 13704 }, 13705 INFO_MANAGE_CERTS_EXAMPLE_EXPORT_CERT_1.get(keystorePath, 13706 exportCertOutputFile)); 13707 13708 examples.put( 13709 new String[] 13710 { 13711 "export-private-key", 13712 "--keystore", keystorePath, 13713 "--keystore-password-file", keystorePWPath, 13714 "--private-key-password-file", privateKeyPWPath, 13715 "--alias", "server-cert", 13716 "--output-file", exportKeyOutputFile, 13717 "--output-format", "PEM", 13718 "--verbose", 13719 "--display-keytool-command" 13720 }, 13721 INFO_MANAGE_CERTS_EXAMPLE_EXPORT_KEY_1.get(keystorePath, 13722 exportKeyOutputFile)); 13723 13724 examples.put( 13725 new String[] 13726 { 13727 "import-certificate", 13728 "--keystore", keystorePath, 13729 "--keystore-type", "JKS", 13730 "--keystore-password-file", keystorePWPath, 13731 "--alias", "server-cert", 13732 "--certificate-file", exportCertOutputFile, 13733 "--private-key-file", exportKeyOutputFile, 13734 "--display-keytool-command" 13735 }, 13736 INFO_MANAGE_CERTS_EXAMPLE_IMPORT_1.get(exportCertOutputFile, 13737 exportKeyOutputFile, keystorePath)); 13738 13739 examples.put( 13740 new String[] 13741 { 13742 "delete-certificate", 13743 "--keystore", keystorePath, 13744 "--keystore-password-file", keystorePWPath, 13745 "--alias", "server-cert" 13746 }, 13747 INFO_MANAGE_CERTS_EXAMPLE_DELETE_1.get(keystorePath)); 13748 13749 examples.put( 13750 new String[] 13751 { 13752 "generate-self-signed-certificate", 13753 "--keystore", keystorePath, 13754 "--keystore-type", "PKCS12", 13755 "--keystore-password-file", keystorePWPath, 13756 "--alias", "ca-cert", 13757 "--subject-dn", "CN=Example Authority,O=Example Corporation,C=US", 13758 "--days-valid", "7300", 13759 "--validity-start-time", "20170101000000", 13760 "--key-algorithm", "RSA", 13761 "--key-size-bits", "4096", 13762 "--signature-algorithm", "SHA256withRSA", 13763 "--basic-constraints-is-ca", "true", 13764 "--key-usage", "key-cert-sign", 13765 "--key-usage", "crl-sign", 13766 "--display-keytool-command" 13767 }, 13768 INFO_MANAGE_CERTS_EXAMPLE_GEN_CERT_1.get(keystorePath)); 13769 13770 examples.put( 13771 new String[] 13772 { 13773 "generate-certificate-signing-request", 13774 "--keystore", keystorePath, 13775 "--keystore-type", "PKCS12", 13776 "--keystore-password-file", keystorePWPath, 13777 "--output-file", genCSROutputFile, 13778 "--alias", "server-cert", 13779 "--subject-dn", "CN=ldap.example.com,O=Example Corporation,C=US", 13780 "--key-algorithm", "EC", 13781 "--key-size-bits", "256", 13782 "--signature-algorithm", "SHA256withECDSA", 13783 "--subject-alternative-name-dns", "ldap1.example.com", 13784 "--subject-alternative-name-dns", "ldap2.example.com", 13785 "--extended-key-usage", "server-auth", 13786 "--extended-key-usage", "client-auth", 13787 "--display-keytool-command" 13788 }, 13789 INFO_MANAGE_CERTS_EXAMPLE_GEN_CSR_1.get(keystorePath, 13790 genCSROutputFile)); 13791 13792 examples.put( 13793 new String[] 13794 { 13795 "generate-certificate-signing-request", 13796 "--keystore", keystorePath, 13797 "--keystore-password-file", keystorePWPath, 13798 "--alias", "server-cert", 13799 "--use-existing-key-pair", 13800 "--inherit-extensions", 13801 "--display-keytool-command" 13802 }, 13803 INFO_MANAGE_CERTS_EXAMPLE_GEN_CSR_2.get(keystorePath)); 13804 13805 examples.put( 13806 new String[] 13807 { 13808 "sign-certificate-signing-request", 13809 "--keystore", keystorePath, 13810 "--keystore-password-file", keystorePWPath, 13811 "--request-input-file", genCSROutputFile, 13812 "--certificate-output-file", exportCertOutputFile, 13813 "--alias", "ca-cert", 13814 "--days-valid", "730", 13815 "--include-requested-extensions", 13816 "--display-keytool-command" 13817 }, 13818 INFO_MANAGE_CERTS_EXAMPLE_SIGN_CERT_1.get(keystorePath, 13819 genCSROutputFile, exportCertOutputFile)); 13820 13821 examples.put( 13822 new String[] 13823 { 13824 "change-certificate-alias", 13825 "--keystore", keystorePath, 13826 "--keystore-password-file", keystorePWPath, 13827 "--current-alias", "server-cert", 13828 "--new-alias", "server-certificate", 13829 "--display-keytool-command" 13830 }, 13831 INFO_MANAGE_CERTS_EXAMPLE_CHANGE_ALIAS_1.get(keystorePath, 13832 genCSROutputFile, exportCertOutputFile)); 13833 13834 examples.put( 13835 new String[] 13836 { 13837 "change-keystore-password", 13838 "--keystore", getPlatformSpecificPath("config", "keystore"), 13839 "--current-keystore-password-file", 13840 getPlatformSpecificPath("config", "current.pin"), 13841 "--new-keystore-password-file", 13842 getPlatformSpecificPath("config", "new.pin"), 13843 "--display-keytool-command" 13844 }, 13845 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_EXAMPLE_1.get( 13846 getPlatformSpecificPath("config", "keystore"), 13847 getPlatformSpecificPath("config", "current.pin"), 13848 getPlatformSpecificPath("config", "new.pin"))); 13849 13850 examples.put( 13851 new String[] 13852 { 13853 "retrieve-server-certificate", 13854 "--hostname", "ds.example.com", 13855 "--port", "636" 13856 }, 13857 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_1.get( 13858 getPlatformSpecificPath("config", "truststore"))); 13859 13860 examples.put( 13861 new String[] 13862 { 13863 "copy-keystore", 13864 "--source-keystore", 13865 getPlatformSpecificPath("config", "keystore.jks"), 13866 "--source-keystore-password-file", 13867 getPlatformSpecificPath("config", "keystore.pin"), 13868 "--source-keystore-type", "JKS", 13869 "--destination-keystore", 13870 getPlatformSpecificPath("config", "keystore.p12"), 13871 "--destination-keystore-password-file", 13872 getPlatformSpecificPath("config", "keystore.pin"), 13873 "--destination-keystore-type", "PKCS12" 13874 }, 13875 INFO_MANAGE_CERTS_SC_COPY_KS_EXAMPLE_1.get("keystore.jks", 13876 "keystore.p12")); 13877 13878 examples.put( 13879 new String[] 13880 { 13881 "trust-server-certificate", 13882 "--hostname", "ldap.example.com", 13883 "--port", "636", 13884 "--keystore", truststorePath, 13885 "--keystore-password-file", truststorePWPath, 13886 "--alias", "ldap.example.com:636" 13887 }, 13888 INFO_MANAGE_CERTS_EXAMPLE_TRUST_SERVER_1.get(truststorePath)); 13889 13890 examples.put( 13891 new String[] 13892 { 13893 "check-certificate-usability", 13894 "--keystore", keystorePath, 13895 "--keystore-password-file", keystorePWPath, 13896 "--alias", "server-cert" 13897 }, 13898 INFO_MANAGE_CERTS_EXAMPLE_CHECK_USABILITY_1.get(keystorePath)); 13899 13900 examples.put( 13901 new String[] 13902 { 13903 "display-certificate-file", 13904 "--certificate-file", exportCertOutputFile, 13905 "--verbose", 13906 "--display-keytool-command" 13907 }, 13908 INFO_MANAGE_CERTS_EXAMPLE_DISPLAY_CERT_1.get(keystorePath)); 13909 13910 examples.put( 13911 new String[] 13912 { 13913 "display-certificate-signing-request-file", 13914 "--certificate-signing-request-file", genCSROutputFile, 13915 "--display-keytool-command" 13916 }, 13917 INFO_MANAGE_CERTS_EXAMPLE_DISPLAY_CSR_1.get(keystorePath)); 13918 13919 examples.put( 13920 new String[] 13921 { 13922 "--help-subcommands" 13923 }, 13924 INFO_MANAGE_CERTS_EXAMPLE_HELP_SUBCOMMANDS_1.get(keystorePath)); 13925 13926 return examples; 13927 } 13928}