001/* 002 * Copyright 2017-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2017-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2017-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.util.ssl.cert; 037 038 039 040import java.io.BufferedInputStream; 041import java.io.BufferedReader; 042import java.io.ByteArrayInputStream; 043import java.io.File; 044import java.io.FileInputStream; 045import java.io.FileOutputStream; 046import java.io.InputStream; 047import java.io.InputStreamReader; 048import java.io.IOException; 049import java.io.OutputStream; 050import java.io.PrintStream; 051import java.nio.file.Files; 052import java.net.InetAddress; 053import java.security.Key; 054import java.security.KeyPair; 055import java.security.KeyStore; 056import java.security.PrivateKey; 057import java.security.Provider; 058import java.security.PublicKey; 059import java.security.UnrecoverableKeyException; 060import java.security.cert.Certificate; 061import java.text.SimpleDateFormat; 062import java.util.ArrayList; 063import java.util.Arrays; 064import java.util.Collections; 065import java.util.Date; 066import java.util.Enumeration; 067import java.util.Iterator; 068import java.util.LinkedHashMap; 069import java.util.LinkedHashSet; 070import java.util.List; 071import java.util.Map; 072import java.util.Set; 073import java.util.concurrent.LinkedBlockingQueue; 074import java.util.concurrent.TimeUnit; 075import java.util.concurrent.atomic.AtomicReference; 076 077import com.unboundid.asn1.ASN1BitString; 078import com.unboundid.asn1.ASN1Element; 079import com.unboundid.ldap.sdk.DN; 080import com.unboundid.ldap.sdk.LDAPConnectionOptions; 081import com.unboundid.ldap.sdk.LDAPException; 082import com.unboundid.ldap.sdk.ResultCode; 083import com.unboundid.ldap.sdk.Version; 084import com.unboundid.util.Base64; 085import com.unboundid.util.BouncyCastleFIPSHelper; 086import com.unboundid.util.ByteStringBuffer; 087import com.unboundid.util.CommandLineTool; 088import com.unboundid.util.CryptoHelper; 089import com.unboundid.util.Debug; 090import com.unboundid.util.NotNull; 091import com.unboundid.util.Nullable; 092import com.unboundid.util.OID; 093import com.unboundid.util.ObjectPair; 094import com.unboundid.util.PasswordReader; 095import com.unboundid.util.StaticUtils; 096import com.unboundid.util.ThreadSafety; 097import com.unboundid.util.ThreadSafetyLevel; 098import com.unboundid.util.Validator; 099import com.unboundid.util.args.ArgumentException; 100import com.unboundid.util.args.ArgumentParser; 101import com.unboundid.util.args.BooleanArgument; 102import com.unboundid.util.args.BooleanValueArgument; 103import com.unboundid.util.args.DNArgument; 104import com.unboundid.util.args.FileArgument; 105import com.unboundid.util.args.IA5StringArgumentValueValidator; 106import com.unboundid.util.args.IPAddressArgumentValueValidator; 107import com.unboundid.util.args.IntegerArgument; 108import com.unboundid.util.args.OIDArgumentValueValidator; 109import com.unboundid.util.args.StringArgument; 110import com.unboundid.util.args.TimestampArgument; 111import com.unboundid.util.args.SubCommand; 112import com.unboundid.util.ssl.JVMDefaultTrustManager; 113import com.unboundid.util.ssl.PKCS11KeyManager; 114 115import static com.unboundid.util.ssl.cert.CertMessages.*; 116 117 118 119/** 120 * This class provides a tool that can be used to manage X.509 certificates for 121 * use in TLS communication. 122 */ 123@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 124public final class ManageCertificates 125 extends CommandLineTool 126{ 127 /** 128 * The path to the keystore with the JVM's set of default trusted issuer 129 * certificates. 130 */ 131 @Nullable private static final File JVM_DEFAULT_CACERTS_FILE; 132 static 133 { 134 File caCertsFile; 135 try 136 { 137 caCertsFile = JVMDefaultTrustManager.getInstance().getCACertsFile(); 138 } 139 catch (final Exception e) 140 { 141 Debug.debugException(e); 142 caCertsFile = null; 143 } 144 145 JVM_DEFAULT_CACERTS_FILE = caCertsFile; 146 } 147 148 149 150 /** 151 * The name of the keystore type that should be used for the Bouncy Castle 152 * FIPS 140-2-compliant keystore. 153 */ 154 @NotNull private static final String BCFKS_KEYSTORE_TYPE = 155 BouncyCastleFIPSHelper.FIPS_KEY_STORE_TYPE; 156 157 158 159 /** 160 * The name of the BCFKS keystore type, formatted in all lowercase. 161 */ 162 @NotNull private static final String BCFKS_KEYSTORE_TYPE_LC = 163 BCFKS_KEYSTORE_TYPE.toLowerCase(); 164 165 166 167 /** 168 * The name of a system property that can be used to specify the default 169 * keystore type for new keystores. 170 */ 171 @NotNull private static final String PROPERTY_DEFAULT_KEYSTORE_TYPE = 172 ManageCertificates.class.getName() + ".defaultKeystoreType"; 173 174 175 176 /** 177 * The default keystore type that will be used for new keystores when the 178 * type is not specified. 179 */ 180 @NotNull private static final String DEFAULT_KEYSTORE_TYPE; 181 static 182 { 183 final String propertyValue = 184 StaticUtils.getSystemProperty(PROPERTY_DEFAULT_KEYSTORE_TYPE); 185 if (CryptoHelper.usingFIPSMode() || 186 ((propertyValue != null) && propertyValue.equalsIgnoreCase( 187 BCFKS_KEYSTORE_TYPE))) 188 { 189 DEFAULT_KEYSTORE_TYPE = BCFKS_KEYSTORE_TYPE; 190 } 191 else if ((propertyValue != null) && 192 (propertyValue.equalsIgnoreCase("PKCS12") || 193 propertyValue.equalsIgnoreCase("PKCS#12") || 194 propertyValue.equalsIgnoreCase("PKCS #12") || 195 propertyValue.equalsIgnoreCase("PKCS 12"))) 196 { 197 DEFAULT_KEYSTORE_TYPE = CryptoHelper.KEY_STORE_TYPE_PKCS_12; 198 } 199 else 200 { 201 DEFAULT_KEYSTORE_TYPE = CryptoHelper.KEY_STORE_TYPE_JKS; 202 } 203 } 204 205 206 207 /** 208 * The column at which to wrap long lines of output. 209 */ 210 private static final int WRAP_COLUMN = StaticUtils.TERMINAL_WIDTH_COLUMNS - 1; 211 212 213 214 /** 215 * The set of values that will be allowed for the keystore type argument. 216 */ 217 @NotNull private static final Set<String> ALLOWED_KEYSTORE_TYPE_VALUES = 218 StaticUtils.setOf("jks", 219 "pkcs11", "pkcs 11", "pkcs#11", "pkcs #11", 220 "pkcs12", "pkcs 12", "pkcs#12", "pkcs #12", 221 BCFKS_KEYSTORE_TYPE_LC); 222 223 224 225 // The global argument parser used by this tool. 226 @Nullable private volatile ArgumentParser globalParser = null; 227 228 // The argument parser for the selected subcommand. 229 @Nullable private volatile ArgumentParser subCommandParser = null; 230 231 // The input stream to use for standard input. 232 @NotNull private final InputStream in; 233 234 235 236 /** 237 * Invokes this tool with the default standard output and standard error and 238 * the provided set of arguments. 239 * 240 * @param args The command-line arguments provided to this program. 241 */ 242 public static void main(@NotNull final String... args) 243 { 244 final ResultCode resultCode = main(System.in, System.out, System.err, args); 245 if (resultCode != ResultCode.SUCCESS) 246 { 247 System.exit(Math.max(1, Math.min(resultCode.intValue(), 255))); 248 } 249 } 250 251 252 253 /** 254 * Invokes this tool with the provided output and error streams and set of 255 * arguments. 256 * 257 * @param in The input stream to use for standard input. It may be 258 * {@code null} if no input stream should be available. 259 * @param out The output stream to use for standard output. It may be 260 * {@code null} if standard output should be suppressed. 261 * @param err The output stream to use for standard error. It may be 262 * {@code null} if standard error should be suppressed. 263 * @param args The command-line arguments provided to this program. 264 * 265 * @return The result code obtained from tool processing. 266 */ 267 @NotNull() 268 public static ResultCode main(@Nullable final InputStream in, 269 @Nullable final OutputStream out, 270 @Nullable final OutputStream err, 271 @NotNull final String... args) 272 { 273 final ManageCertificates manageCertificates = 274 new ManageCertificates(in, out, err); 275 return manageCertificates.runTool(args); 276 } 277 278 279 280 /** 281 * Creates a new instance of this tool with the provided output and error 282 * streams. Standard input will bot be available. 283 * 284 * @param out The output stream to use for standard output. It may be 285 * {@code null} if standard output should be suppressed. 286 * @param err The output stream to use for standard error. It may be 287 * {@code null} if standard error should be suppressed. 288 */ 289 public ManageCertificates(@Nullable final OutputStream out, 290 @Nullable final OutputStream err) 291 { 292 this(null, out, err); 293 } 294 295 296 297 /** 298 * Creates a new instance of this tool with the provided output and error 299 * streams. 300 * 301 * @param in The input stream to use for standard input. It may be 302 * {@code null} if no input stream should be available. 303 * @param out The output stream to use for standard output. It may be 304 * {@code null} if standard output should be suppressed. 305 * @param err The output stream to use for standard error. It may be 306 * {@code null} if standard error should be suppressed. 307 */ 308 public ManageCertificates(@Nullable final InputStream in, 309 @Nullable final OutputStream out, 310 @Nullable final OutputStream err) 311 { 312 super(out, err); 313 314 if (in == null) 315 { 316 this.in = new ByteArrayInputStream(StaticUtils.NO_BYTES); 317 } 318 else 319 { 320 this.in = in; 321 } 322 } 323 324 325 326 /** 327 * Retrieves the name of this tool. It should be the name of the command used 328 * to invoke this tool. 329 * 330 * @return The name for this tool. 331 */ 332 @Override() 333 @NotNull() 334 public String getToolName() 335 { 336 return "manage-certificates"; 337 } 338 339 340 341 /** 342 * Retrieves a human-readable description for this tool. 343 * 344 * @return A human-readable description for this tool. 345 */ 346 @Override() 347 @NotNull() 348 public String getToolDescription() 349 { 350 return INFO_MANAGE_CERTS_TOOL_DESC.get(); 351 } 352 353 354 355 /** 356 * Retrieves a version string for this tool, if available. 357 * 358 * @return A version string for this tool, or {@code null} if none is 359 * available. 360 */ 361 @Override() 362 @NotNull() 363 public String getToolVersion() 364 { 365 return Version.NUMERIC_VERSION_STRING; 366 } 367 368 369 370 /** 371 * Indicates whether this tool should provide support for an interactive mode, 372 * in which the tool offers a mode in which the arguments can be provided in 373 * a text-driven menu rather than requiring them to be given on the command 374 * line. If interactive mode is supported, it may be invoked using the 375 * "--interactive" argument. Alternately, if interactive mode is supported 376 * and {@link #defaultsToInteractiveMode()} returns {@code true}, then 377 * interactive mode may be invoked by simply launching the tool without any 378 * arguments. 379 * 380 * @return {@code true} if this tool supports interactive mode, or 381 * {@code false} if not. 382 */ 383 @Override() 384 public boolean supportsInteractiveMode() 385 { 386 return true; 387 } 388 389 390 391 /** 392 * Indicates whether this tool defaults to launching in interactive mode if 393 * the tool is invoked without any command-line arguments. This will only be 394 * used if {@link #supportsInteractiveMode()} returns {@code true}. 395 * 396 * @return {@code true} if this tool defaults to using interactive mode if 397 * launched without any command-line arguments, or {@code false} if 398 * not. 399 */ 400 @Override() 401 public boolean defaultsToInteractiveMode() 402 { 403 return true; 404 } 405 406 407 408 /** 409 * Indicates whether this tool supports the use of a properties file for 410 * specifying default values for arguments that aren't specified on the 411 * command line. 412 * 413 * @return {@code true} if this tool supports the use of a properties file 414 * for specifying default values for arguments that aren't specified 415 * on the command line, or {@code false} if not. 416 */ 417 @Override() 418 public boolean supportsPropertiesFile() 419 { 420 return true; 421 } 422 423 424 425 /** 426 * Indicates whether this tool should provide arguments for redirecting output 427 * to a file. If this method returns {@code true}, then the tool will offer 428 * an "--outputFile" argument that will specify the path to a file to which 429 * all standard output and standard error content will be written, and it will 430 * also offer a "--teeToStandardOut" argument that can only be used if the 431 * "--outputFile" argument is present and will cause all output to be written 432 * to both the specified output file and to standard output. 433 * 434 * @return {@code true} if this tool should provide arguments for redirecting 435 * output to a file, or {@code false} if not. 436 */ 437 @Override() 438 protected boolean supportsOutputFile() 439 { 440 return false; 441 } 442 443 444 445 /** 446 * {@inheritDoc} 447 */ 448 @Override() 449 protected boolean supportsDebugLogging() 450 { 451 return true; 452 } 453 454 455 456 /** 457 * Indicates whether to log messages about the launch and completion of this 458 * tool into the invocation log of Ping Identity server products that may 459 * include it. This method is not needed for tools that are not expected to 460 * be part of the Ping Identity server products suite. Further, this value 461 * may be overridden by settings in the server's 462 * tool-invocation-logging.properties file. 463 * <BR><BR> 464 * This method should generally return {@code true} for tools that may alter 465 * the server configuration, data, or other state information, and 466 * {@code false} for tools that do not make any changes. 467 * 468 * @return {@code true} if Ping Identity server products should include 469 * messages about the launch and completion of this tool in tool 470 * invocation log files by default, or {@code false} if not. 471 */ 472 @Override() 473 protected boolean logToolInvocationByDefault() 474 { 475 return true; 476 } 477 478 479 480 /** 481 * Adds the command-line arguments supported for use with this tool to the 482 * provided argument parser. The tool may need to retain references to the 483 * arguments (and/or the argument parser, if trailing arguments are allowed) 484 * to it in order to obtain their values for use in later processing. 485 * 486 * @param parser The argument parser to which the arguments are to be added. 487 * 488 * @throws ArgumentException If a problem occurs while adding any of the 489 * tool-specific arguments to the provided 490 * argument parser. 491 */ 492 @Override() 493 public void addToolArguments(@NotNull final ArgumentParser parser) 494 throws ArgumentException 495 { 496 globalParser = parser; 497 498 499 // Define the "list-certificates" subcommand and all of its arguments. 500 final ArgumentParser listCertsParser = new ArgumentParser( 501 "list-certificates", INFO_MANAGE_CERTS_SC_LIST_CERTS_DESC.get()); 502 503 final FileArgument listCertsKeystore = new FileArgument(null, "keystore", 504 (JVM_DEFAULT_CACERTS_FILE == null), 1, null, 505 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_DESC.get(), true, true, true, 506 false); 507 listCertsKeystore.addLongIdentifier("keystore-path", true); 508 listCertsKeystore.addLongIdentifier("keystorePath", true); 509 listCertsKeystore.addLongIdentifier("keystore-file", true); 510 listCertsKeystore.addLongIdentifier("keystoreFile", true); 511 listCertsParser.addArgument(listCertsKeystore); 512 513 if (JVM_DEFAULT_CACERTS_FILE != null) 514 { 515 final BooleanArgument listCertsUseJVMDefault = new BooleanArgument(null, 516 "use-jvm-default-trust-store", 1, 517 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_JVM_DEFAULT_DESC.get( 518 JVM_DEFAULT_CACERTS_FILE.getAbsolutePath())); 519 listCertsUseJVMDefault.addLongIdentifier("useJVMDefaultTrustStore", true); 520 listCertsUseJVMDefault.addLongIdentifier("jvm-default", true); 521 listCertsUseJVMDefault.addLongIdentifier("jvmDefault", true); 522 listCertsParser.addArgument(listCertsUseJVMDefault); 523 524 listCertsParser.addRequiredArgumentSet(listCertsUseJVMDefault, 525 listCertsKeystore); 526 listCertsParser.addExclusiveArgumentSet(listCertsUseJVMDefault, 527 listCertsKeystore); 528 } 529 530 final StringArgument listCertsKeystorePassword = new StringArgument(null, 531 "keystore-password", false, 1, 532 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 533 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_PW_DESC.get()); 534 listCertsKeystorePassword.addLongIdentifier("keystorePassword", true); 535 listCertsKeystorePassword.addLongIdentifier("keystore-passphrase", true); 536 listCertsKeystorePassword.addLongIdentifier("keystorePassphrase", true); 537 listCertsKeystorePassword.addLongIdentifier("keystore-pin", true); 538 listCertsKeystorePassword.addLongIdentifier("keystorePIN", true); 539 listCertsKeystorePassword.addLongIdentifier("storepass", true); 540 listCertsKeystorePassword.setSensitive(true); 541 listCertsParser.addArgument(listCertsKeystorePassword); 542 543 final FileArgument listCertsKeystorePasswordFile = new FileArgument(null, 544 "keystore-password-file", false, 1, null, 545 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_PW_FILE_DESC.get(), true, true, 546 true, false); 547 listCertsKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 548 true); 549 listCertsKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 550 true); 551 listCertsKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 552 true); 553 listCertsKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 554 true); 555 listCertsKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 556 listCertsParser.addArgument(listCertsKeystorePasswordFile); 557 558 final BooleanArgument listCertsPromptForKeystorePassword = 559 new BooleanArgument(null, "prompt-for-keystore-password", 560 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_PROMPT_FOR_KS_PW_DESC.get()); 561 listCertsPromptForKeystorePassword.addLongIdentifier( 562 "promptForKeystorePassword", true); 563 listCertsPromptForKeystorePassword.addLongIdentifier( 564 "prompt-for-keystore-passphrase", true); 565 listCertsPromptForKeystorePassword.addLongIdentifier( 566 "promptForKeystorePassphrase", true); 567 listCertsPromptForKeystorePassword.addLongIdentifier( 568 "prompt-for-keystore-pin", true); 569 listCertsPromptForKeystorePassword.addLongIdentifier( 570 "promptForKeystorePIN", true); 571 listCertsParser.addArgument(listCertsPromptForKeystorePassword); 572 573 final StringArgument listCertsKeystoreType = new StringArgument(null, 574 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 575 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_TYPE_DESC.get(), 576 ALLOWED_KEYSTORE_TYPE_VALUES); 577 listCertsKeystoreType.addLongIdentifier("key-store-type", true); 578 listCertsKeystoreType.addLongIdentifier("keystoreType", true); 579 listCertsKeystoreType.addLongIdentifier("keystore-format", true); 580 listCertsKeystoreType.addLongIdentifier("key-store-format", true); 581 listCertsKeystoreType.addLongIdentifier("keystoreFormat", true); 582 listCertsKeystoreType.addLongIdentifier("storetype", true); 583 listCertsParser.addArgument(listCertsKeystoreType); 584 585 final StringArgument listCertsAlias = new StringArgument(null, "alias", 586 false, 0, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 587 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_ALIAS_DESC.get()); 588 listCertsAlias.addLongIdentifier("nickname", true); 589 listCertsParser.addArgument(listCertsAlias); 590 591 final BooleanArgument listCertsDisplayPEM = new BooleanArgument(null, 592 "display-pem-certificate", 1, 593 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_DISPLAY_PEM_DESC.get()); 594 listCertsDisplayPEM.addLongIdentifier("displayPEMCertificate", true); 595 listCertsDisplayPEM.addLongIdentifier("display-pem", true); 596 listCertsDisplayPEM.addLongIdentifier("displayPEM", true); 597 listCertsDisplayPEM.addLongIdentifier("show-pem-certificate", true); 598 listCertsDisplayPEM.addLongIdentifier("showPEMCertificate", true); 599 listCertsDisplayPEM.addLongIdentifier("show-pem", true); 600 listCertsDisplayPEM.addLongIdentifier("showPEM", true); 601 listCertsDisplayPEM.addLongIdentifier("pem", true); 602 listCertsDisplayPEM.addLongIdentifier("rfc", true); 603 listCertsParser.addArgument(listCertsDisplayPEM); 604 605 final BooleanArgument listCertsVerbose = new BooleanArgument(null, 606 "verbose", 1, INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_VERBOSE_DESC.get()); 607 listCertsParser.addArgument(listCertsVerbose); 608 609 final BooleanArgument listCertsDisplayCommand = new BooleanArgument(null, 610 "display-keytool-command", 1, 611 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_DISPLAY_COMMAND_DESC.get()); 612 listCertsDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 613 listCertsDisplayCommand.addLongIdentifier("show-keytool-command", true); 614 listCertsDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 615 listCertsParser.addArgument(listCertsDisplayCommand); 616 617 listCertsParser.addExclusiveArgumentSet(listCertsKeystorePassword, 618 listCertsKeystorePasswordFile, listCertsPromptForKeystorePassword); 619 620 final LinkedHashMap<String[],String> listCertsExamples = 621 new LinkedHashMap<>(StaticUtils.computeMapCapacity(3)); 622 listCertsExamples.put( 623 new String[] 624 { 625 "list-certificates", 626 "--keystore", getPlatformSpecificPath("config", "keystore") 627 }, 628 INFO_MANAGE_CERTS_SC_LIST_CERTS_EXAMPLE_1.get( 629 getPlatformSpecificPath("config", "keystore"))); 630 listCertsExamples.put( 631 new String[] 632 { 633 "list-certificates", 634 "--keystore", getPlatformSpecificPath("config", "keystore.p12"), 635 "--keystore-password-file", 636 getPlatformSpecificPath("config", "keystore.pin"), 637 "--alias", "server-cert", 638 "--verbose", 639 "--display-pem-certificate", 640 "--display-keytool-command" 641 }, 642 INFO_MANAGE_CERTS_SC_LIST_CERTS_EXAMPLE_2.get( 643 getPlatformSpecificPath("config", "keystore.p12"), 644 getPlatformSpecificPath("config", "keystore.pin"))); 645 if (JVM_DEFAULT_CACERTS_FILE != null) 646 { 647 listCertsExamples.put( 648 new String[] 649 { 650 "list-certificates", 651 "--use-jvm-default-trust-store" 652 }, 653 INFO_MANAGE_CERTS_SC_LIST_CERTS_EXAMPLE_3.get()); 654 } 655 656 final SubCommand listCertsSubCommand = new SubCommand("list-certificates", 657 INFO_MANAGE_CERTS_SC_LIST_CERTS_DESC.get(), listCertsParser, 658 listCertsExamples); 659 listCertsSubCommand.addName("listCertificates", true); 660 listCertsSubCommand.addName("list-certs", true); 661 listCertsSubCommand.addName("listCerts", true); 662 listCertsSubCommand.addName("list", true); 663 664 parser.addSubCommand(listCertsSubCommand); 665 666 667 // Define the "export-certificate" subcommand and all of its arguments. 668 final ArgumentParser exportCertParser = new ArgumentParser( 669 "export-certificate", INFO_MANAGE_CERTS_SC_EXPORT_CERT_DESC.get()); 670 671 final FileArgument exportCertKeystore = new FileArgument(null, "keystore", 672 (JVM_DEFAULT_CACERTS_FILE == null), 1, null, 673 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_KS_DESC.get(), true, true, true, 674 false); 675 exportCertKeystore.addLongIdentifier("keystore-path", true); 676 exportCertKeystore.addLongIdentifier("keystorePath", true); 677 exportCertKeystore.addLongIdentifier("keystore-file", true); 678 exportCertKeystore.addLongIdentifier("keystoreFile", true); 679 exportCertParser.addArgument(exportCertKeystore); 680 681 if (JVM_DEFAULT_CACERTS_FILE != null) 682 { 683 final BooleanArgument exportCertUseJVMDefault = new BooleanArgument(null, 684 "use-jvm-default-trust-store", 1, 685 INFO_MANAGE_CERTS_SC_EXPORT_CERTS_ARG_JVM_DEFAULT_DESC.get( 686 JVM_DEFAULT_CACERTS_FILE.getAbsolutePath())); 687 exportCertUseJVMDefault.addLongIdentifier("useJVMDefaultTrustStore", 688 true); 689 exportCertUseJVMDefault.addLongIdentifier("jvm-default", true); 690 exportCertUseJVMDefault.addLongIdentifier("jvmDefault", true); 691 exportCertParser.addArgument(exportCertUseJVMDefault); 692 693 exportCertParser.addRequiredArgumentSet(exportCertUseJVMDefault, 694 exportCertKeystore); 695 exportCertParser.addExclusiveArgumentSet(exportCertUseJVMDefault, 696 exportCertKeystore); 697 } 698 699 final StringArgument exportCertKeystorePassword = new StringArgument(null, 700 "keystore-password", false, 1, 701 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 702 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_KS_PW_DESC.get()); 703 exportCertKeystorePassword.addLongIdentifier("keystorePassword", true); 704 exportCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 705 exportCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 706 exportCertKeystorePassword.addLongIdentifier("keystore-pin", true); 707 exportCertKeystorePassword.addLongIdentifier("keystorePIN", true); 708 exportCertKeystorePassword.addLongIdentifier("storepass", true); 709 exportCertKeystorePassword.setSensitive(true); 710 exportCertParser.addArgument(exportCertKeystorePassword); 711 712 final FileArgument exportCertKeystorePasswordFile = new FileArgument(null, 713 "keystore-password-file", false, 1, null, 714 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 715 true, false); 716 exportCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 717 true); 718 exportCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 719 true); 720 exportCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 721 true); 722 exportCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 723 true); 724 exportCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 725 exportCertParser.addArgument(exportCertKeystorePasswordFile); 726 727 final BooleanArgument exportCertPromptForKeystorePassword = 728 new BooleanArgument(null, "prompt-for-keystore-password", 729 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 730 exportCertPromptForKeystorePassword.addLongIdentifier( 731 "promptForKeystorePassword", true); 732 exportCertPromptForKeystorePassword.addLongIdentifier( 733 "prompt-for-keystore-passphrase", true); 734 exportCertPromptForKeystorePassword.addLongIdentifier( 735 "promptForKeystorePassphrase", true); 736 exportCertPromptForKeystorePassword.addLongIdentifier( 737 "prompt-for-keystore-pin", true); 738 exportCertPromptForKeystorePassword.addLongIdentifier( 739 "promptForKeystorePIN", true); 740 exportCertParser.addArgument(exportCertPromptForKeystorePassword); 741 742 final StringArgument exportCertKeystoreType = new StringArgument(null, 743 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 744 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_KS_TYPE_DESC.get(), 745 ALLOWED_KEYSTORE_TYPE_VALUES); 746 exportCertKeystoreType.addLongIdentifier("key-store-type", true); 747 exportCertKeystoreType.addLongIdentifier("keystoreType", true); 748 exportCertKeystoreType.addLongIdentifier("keystore-format", true); 749 exportCertKeystoreType.addLongIdentifier("key-store-format", true); 750 exportCertKeystoreType.addLongIdentifier("keystoreFormat", true); 751 exportCertKeystoreType.addLongIdentifier("storetype", true); 752 exportCertParser.addArgument(exportCertKeystoreType); 753 754 final StringArgument exportCertAlias = new StringArgument(null, "alias", 755 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 756 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_ALIAS_DESC.get()); 757 exportCertAlias.addLongIdentifier("nickname", true); 758 exportCertParser.addArgument(exportCertAlias); 759 760 final BooleanArgument exportCertChain = new BooleanArgument(null, 761 "export-certificate-chain", 1, 762 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_CHAIN_DESC.get()); 763 exportCertChain.addLongIdentifier("exportCertificateChain", true); 764 exportCertChain.addLongIdentifier("export-chain", true); 765 exportCertChain.addLongIdentifier("exportChain", true); 766 exportCertChain.addLongIdentifier("certificate-chain", true); 767 exportCertChain.addLongIdentifier("certificateChain", true); 768 exportCertChain.addLongIdentifier("chain", true); 769 exportCertParser.addArgument(exportCertChain); 770 771 final Set<String> exportCertOutputFormatAllowedValues = StaticUtils.setOf( 772 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 773 final StringArgument exportCertOutputFormat = new StringArgument(null, 774 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 775 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_FORMAT_DESC.get(), 776 exportCertOutputFormatAllowedValues, "PEM"); 777 exportCertOutputFormat.addLongIdentifier("outputFormat", true); 778 exportCertParser.addArgument(exportCertOutputFormat); 779 780 final FileArgument exportCertOutputFile = new FileArgument(null, 781 "output-file", false, 1, null, 782 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_FILE_DESC.get(), false, true, 783 true, false); 784 exportCertOutputFile.addLongIdentifier("outputFile", true); 785 exportCertOutputFile.addLongIdentifier("export-file", true); 786 exportCertOutputFile.addLongIdentifier("exportFile", true); 787 exportCertOutputFile.addLongIdentifier("certificate-file", true); 788 exportCertOutputFile.addLongIdentifier("certificateFile", true); 789 exportCertOutputFile.addLongIdentifier("file", true); 790 exportCertOutputFile.addLongIdentifier("filename", true); 791 exportCertParser.addArgument(exportCertOutputFile); 792 793 final BooleanArgument exportCertSeparateFile = new BooleanArgument(null, 794 "separate-file-per-certificate", 1, 795 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_SEPARATE_FILE_DESC.get()); 796 exportCertSeparateFile.addLongIdentifier("separateFilePerCertificate", 797 true); 798 exportCertSeparateFile.addLongIdentifier("separate-files", true); 799 exportCertSeparateFile.addLongIdentifier("separateFiles", true); 800 exportCertParser.addArgument(exportCertSeparateFile); 801 802 final BooleanArgument exportCertDisplayCommand = new BooleanArgument(null, 803 "display-keytool-command", 1, 804 INFO_MANAGE_CERTS_SC_EXPORT_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 805 exportCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 806 exportCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 807 exportCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 808 exportCertParser.addArgument(exportCertDisplayCommand); 809 810 exportCertParser.addExclusiveArgumentSet(exportCertKeystorePassword, 811 exportCertKeystorePasswordFile, exportCertPromptForKeystorePassword); 812 exportCertParser.addDependentArgumentSet(exportCertSeparateFile, 813 exportCertChain); 814 exportCertParser.addDependentArgumentSet(exportCertSeparateFile, 815 exportCertOutputFile); 816 817 final LinkedHashMap<String[],String> exportCertExamples = 818 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 819 exportCertExamples.put( 820 new String[] 821 { 822 "export-certificate", 823 "--keystore", getPlatformSpecificPath("config", "keystore"), 824 "--alias", "server-cert" 825 }, 826 INFO_MANAGE_CERTS_SC_EXPORT_CERT_EXAMPLE_1.get()); 827 exportCertExamples.put( 828 new String[] 829 { 830 "export-certificate", 831 "--keystore", getPlatformSpecificPath("config", "keystore.p12"), 832 "--keystore-password-file", 833 getPlatformSpecificPath("config", "keystore.pin"), 834 "--alias", "server-cert", 835 "--export-certificate-chain", 836 "--output-format", "DER", 837 "--output-file", "certificate-chain.der", 838 "--display-keytool-command" 839 }, 840 INFO_MANAGE_CERTS_SC_EXPORT_CERT_EXAMPLE_2.get()); 841 842 final SubCommand exportCertSubCommand = new SubCommand("export-certificate", 843 INFO_MANAGE_CERTS_SC_EXPORT_CERT_DESC.get(), exportCertParser, 844 exportCertExamples); 845 exportCertSubCommand.addName("exportCertificate", true); 846 exportCertSubCommand.addName("export-cert", true); 847 exportCertSubCommand.addName("exportCert", true); 848 exportCertSubCommand.addName("export", true); 849 850 parser.addSubCommand(exportCertSubCommand); 851 852 853 // Define the "export-private-key" subcommand and all of its arguments. 854 final ArgumentParser exportKeyParser = new ArgumentParser( 855 "export-private-key", INFO_MANAGE_CERTS_SC_EXPORT_KEY_DESC.get()); 856 857 final FileArgument exportKeyKeystore = new FileArgument(null, "keystore", 858 true, 1, null, INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_KS_DESC.get(), 859 true, true, true, false); 860 exportKeyKeystore.addLongIdentifier("keystore-path", true); 861 exportKeyKeystore.addLongIdentifier("keystorePath", true); 862 exportKeyKeystore.addLongIdentifier("keystore-file", true); 863 exportKeyKeystore.addLongIdentifier("keystoreFile", true); 864 exportKeyParser.addArgument(exportKeyKeystore); 865 866 final StringArgument exportKeyKeystorePassword = new StringArgument(null, 867 "keystore-password", false, 1, 868 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 869 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_KS_PW_DESC.get()); 870 exportKeyKeystorePassword.addLongIdentifier("keystorePassword", true); 871 exportKeyKeystorePassword.addLongIdentifier("keystore-passphrase", true); 872 exportKeyKeystorePassword.addLongIdentifier("keystorePassphrase", true); 873 exportKeyKeystorePassword.addLongIdentifier("keystore-pin", true); 874 exportKeyKeystorePassword.addLongIdentifier("keystorePIN", true); 875 exportKeyKeystorePassword.addLongIdentifier("storepass", true); 876 exportKeyKeystorePassword.setSensitive(true); 877 exportKeyParser.addArgument(exportKeyKeystorePassword); 878 879 final FileArgument exportKeyKeystorePasswordFile = new FileArgument(null, 880 "keystore-password-file", false, 1, null, 881 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_KS_PW_FILE_DESC.get(), true, true, 882 true, false); 883 exportKeyKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 884 true); 885 exportKeyKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 886 true); 887 exportKeyKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 888 true); 889 exportKeyKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 890 true); 891 exportKeyKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 892 exportKeyParser.addArgument(exportKeyKeystorePasswordFile); 893 894 final BooleanArgument exportKeyPromptForKeystorePassword = 895 new BooleanArgument(null, "prompt-for-keystore-password", 896 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PROMPT_FOR_KS_PW_DESC.get()); 897 exportKeyPromptForKeystorePassword.addLongIdentifier( 898 "promptForKeystorePassword", true); 899 exportKeyPromptForKeystorePassword.addLongIdentifier( 900 "prompt-for-keystore-passphrase", true); 901 exportKeyPromptForKeystorePassword.addLongIdentifier( 902 "promptForKeystorePassphrase", true); 903 exportKeyPromptForKeystorePassword.addLongIdentifier( 904 "prompt-for-keystore-pin", true); 905 exportKeyPromptForKeystorePassword.addLongIdentifier( 906 "promptForKeystorePIN", true); 907 exportKeyParser.addArgument(exportKeyPromptForKeystorePassword); 908 909 final StringArgument exportKeyPKPassword = new StringArgument(null, 910 "private-key-password", false, 1, 911 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 912 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PK_PW_DESC.get()); 913 exportKeyPKPassword.addLongIdentifier("privateKeyPassword", true); 914 exportKeyPKPassword.addLongIdentifier("private-key-passphrase", true); 915 exportKeyPKPassword.addLongIdentifier("privateKeyPassphrase", true); 916 exportKeyPKPassword.addLongIdentifier("private-key-pin", true); 917 exportKeyPKPassword.addLongIdentifier("privateKeyPIN", true); 918 exportKeyPKPassword.addLongIdentifier("key-password", true); 919 exportKeyPKPassword.addLongIdentifier("keyPassword", true); 920 exportKeyPKPassword.addLongIdentifier("key-passphrase", true); 921 exportKeyPKPassword.addLongIdentifier("keyPassphrase", true); 922 exportKeyPKPassword.addLongIdentifier("key-pin", true); 923 exportKeyPKPassword.addLongIdentifier("keyPIN", true); 924 exportKeyPKPassword.addLongIdentifier("keypass", true); 925 exportKeyPKPassword.setSensitive(true); 926 exportKeyParser.addArgument(exportKeyPKPassword); 927 928 final FileArgument exportKeyPKPasswordFile = new FileArgument(null, 929 "private-key-password-file", false, 1, null, 930 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PK_PW_FILE_DESC.get(), true, true, 931 true, false); 932 exportKeyPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 933 exportKeyPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 934 true); 935 exportKeyPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 936 true); 937 exportKeyPKPasswordFile.addLongIdentifier("private-key-pin-file", 938 true); 939 exportKeyPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 940 exportKeyPKPasswordFile.addLongIdentifier("key-password-file", true); 941 exportKeyPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 942 exportKeyPKPasswordFile.addLongIdentifier("key-passphrase-file", 943 true); 944 exportKeyPKPasswordFile.addLongIdentifier("keyPassphraseFile", 945 true); 946 exportKeyPKPasswordFile.addLongIdentifier("key-pin-file", 947 true); 948 exportKeyPKPasswordFile.addLongIdentifier("keyPINFile", true); 949 exportKeyParser.addArgument(exportKeyPKPasswordFile); 950 951 final BooleanArgument exportKeyPromptForPKPassword = 952 new BooleanArgument(null, "prompt-for-private-key-password", 953 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PROMPT_FOR_PK_PW_DESC.get()); 954 exportKeyPromptForPKPassword.addLongIdentifier( 955 "promptForPrivateKeyPassword", true); 956 exportKeyPromptForPKPassword.addLongIdentifier( 957 "prompt-for-private-key-passphrase", true); 958 exportKeyPromptForPKPassword.addLongIdentifier( 959 "promptForPrivateKeyPassphrase", true); 960 exportKeyPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 961 true); 962 exportKeyPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 963 true); 964 exportKeyPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 965 true); 966 exportKeyPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 967 true); 968 exportKeyPromptForPKPassword.addLongIdentifier( 969 "prompt-for-key-passphrase", true); 970 exportKeyPromptForPKPassword.addLongIdentifier( 971 "promptForKeyPassphrase", true); 972 exportKeyPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 973 exportKeyPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 974 exportKeyParser.addArgument(exportKeyPromptForPKPassword); 975 976 final StringArgument exportKeyKeystoreType = new StringArgument(null, 977 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 978 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_KS_TYPE_DESC.get(), 979 ALLOWED_KEYSTORE_TYPE_VALUES); 980 exportKeyKeystoreType.addLongIdentifier("key-store-type", true); 981 exportKeyKeystoreType.addLongIdentifier("keystoreType", true); 982 exportKeyKeystoreType.addLongIdentifier("keystore-format", true); 983 exportKeyKeystoreType.addLongIdentifier("key-store-format", true); 984 exportKeyKeystoreType.addLongIdentifier("keystoreFormat", true); 985 exportKeyKeystoreType.addLongIdentifier("storetype", true); 986 exportKeyParser.addArgument(exportKeyKeystoreType); 987 988 final StringArgument exportKeyAlias = new StringArgument(null, "alias", 989 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 990 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_ALIAS_DESC.get()); 991 exportKeyAlias.addLongIdentifier("nickname", true); 992 exportKeyParser.addArgument(exportKeyAlias); 993 994 final Set<String> exportKeyOutputFormatAllowedValues = StaticUtils.setOf( 995 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 996 final StringArgument exportKeyOutputFormat = new StringArgument(null, 997 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 998 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_FORMAT_DESC.get(), 999 exportKeyOutputFormatAllowedValues, "PEM"); 1000 exportKeyOutputFormat.addLongIdentifier("outputFormat", true); 1001 exportKeyParser.addArgument(exportKeyOutputFormat); 1002 1003 final FileArgument exportKeyOutputFile = new FileArgument(null, 1004 "output-file", false, 1, null, 1005 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_FILE_DESC.get(), false, true, 1006 true, false); 1007 exportKeyOutputFile.addLongIdentifier("outputFile", true); 1008 exportKeyOutputFile.addLongIdentifier("export-file", true); 1009 exportKeyOutputFile.addLongIdentifier("exportFile", true); 1010 exportKeyOutputFile.addLongIdentifier("private-key-file", true); 1011 exportKeyOutputFile.addLongIdentifier("privateKeyFile", true); 1012 exportKeyOutputFile.addLongIdentifier("key-file", true); 1013 exportKeyOutputFile.addLongIdentifier("keyFile", true); 1014 exportKeyOutputFile.addLongIdentifier("file", true); 1015 exportKeyOutputFile.addLongIdentifier("filename", true); 1016 exportKeyParser.addArgument(exportKeyOutputFile); 1017 1018 final StringArgument exportKeyEncryptionPassword = new StringArgument(null, 1019 "encryption-password", false, 1, 1020 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1021 INFO_MANAGE_CERTS_SC_EXPIRT_KEY_ARG_ENC_PW_DESC.get()); 1022 exportKeyEncryptionPassword.addLongIdentifier("encryptionPassword", true); 1023 exportKeyParser.addArgument(exportKeyEncryptionPassword); 1024 1025 final FileArgument exportKeyEncryptionPasswordFile = new FileArgument(null, 1026 "encryption-password-file", false, 1, null, 1027 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_ENC_PW_FILE_DESC.get(), true, true, 1028 true, false); 1029 exportKeyEncryptionPasswordFile.addLongIdentifier("encryptionPasswordFile", 1030 true); 1031 exportKeyParser.addArgument(exportKeyEncryptionPasswordFile); 1032 1033 final BooleanArgument exportKeyPromptForEncryptionPassword = 1034 new BooleanArgument(null, "prompt-for-encryption-password", 1, 1035 INFO_MANAGE_CERTS_SC_EXPORT_KEY_ARG_PROMPT_FOR_ENC_PW.get()); 1036 exportKeyPromptForEncryptionPassword.addLongIdentifier( 1037 "promptForEncryptionPassword", true); 1038 exportKeyParser.addArgument(exportKeyPromptForEncryptionPassword); 1039 1040 exportKeyParser.addRequiredArgumentSet(exportKeyKeystorePassword, 1041 exportKeyKeystorePasswordFile, exportKeyPromptForKeystorePassword); 1042 exportKeyParser.addExclusiveArgumentSet(exportKeyKeystorePassword, 1043 exportKeyKeystorePasswordFile, exportKeyPromptForKeystorePassword); 1044 exportKeyParser.addExclusiveArgumentSet(exportKeyPKPassword, 1045 exportKeyPKPasswordFile, exportKeyPromptForPKPassword); 1046 exportKeyParser.addExclusiveArgumentSet(exportKeyEncryptionPassword, 1047 exportKeyEncryptionPasswordFile, exportKeyPromptForEncryptionPassword); 1048 1049 final LinkedHashMap<String[],String> exportKeyExamples = 1050 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 1051 exportKeyExamples.put( 1052 new String[] 1053 { 1054 "export-private-key", 1055 "--keystore", getPlatformSpecificPath("config", "keystore"), 1056 "--keystore-password-file", 1057 getPlatformSpecificPath("config", "keystore.pin"), 1058 "--alias", "server-cert" 1059 }, 1060 INFO_MANAGE_CERTS_SC_EXPORT_KEY_EXAMPLE_1.get()); 1061 exportKeyExamples.put( 1062 new String[] 1063 { 1064 "export-private-key", 1065 "--keystore", getPlatformSpecificPath("config", "keystore.p12"), 1066 "--keystore-password-file", 1067 getPlatformSpecificPath("config", "keystore.pin"), 1068 "--private-key-password-file", 1069 getPlatformSpecificPath("config", "server-cert-key.pin"), 1070 "--alias", "server-cert", 1071 "--output-format", "DER", 1072 "--output-file", "server-cert-key.der" 1073 }, 1074 INFO_MANAGE_CERTS_SC_EXPORT_KEY_EXAMPLE_2.get()); 1075 1076 final SubCommand exportKeySubCommand = new SubCommand("export-private-key", 1077 INFO_MANAGE_CERTS_SC_EXPORT_CERT_DESC.get(), exportKeyParser, 1078 exportKeyExamples); 1079 exportKeySubCommand.addName("exportPrivateKey", true); 1080 exportKeySubCommand.addName("export-key", true); 1081 exportKeySubCommand.addName("exportKey", true); 1082 1083 parser.addSubCommand(exportKeySubCommand); 1084 1085 1086 // Define the "import-certificate" subcommand and all of its arguments. 1087 final ArgumentParser importCertParser = new ArgumentParser( 1088 "import-certificate", INFO_MANAGE_CERTS_SC_IMPORT_CERT_DESC.get()); 1089 1090 final FileArgument importCertKeystore = new FileArgument(null, "keystore", 1091 true, 1, null, INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KS_DESC.get(), 1092 false, true, true, false); 1093 importCertKeystore.addLongIdentifier("keystore-path", true); 1094 importCertKeystore.addLongIdentifier("keystorePath", true); 1095 importCertKeystore.addLongIdentifier("keystore-file", true); 1096 importCertKeystore.addLongIdentifier("keystoreFile", true); 1097 importCertParser.addArgument(importCertKeystore); 1098 1099 final StringArgument importCertKeystorePassword = new StringArgument(null, 1100 "keystore-password", false, 1, 1101 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1102 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KS_PW_DESC.get()); 1103 importCertKeystorePassword.addLongIdentifier("keystorePassword", true); 1104 importCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 1105 importCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 1106 importCertKeystorePassword.addLongIdentifier("keystore-pin", true); 1107 importCertKeystorePassword.addLongIdentifier("keystorePIN", true); 1108 importCertKeystorePassword.addLongIdentifier("storepass", true); 1109 importCertKeystorePassword.setSensitive(true); 1110 importCertParser.addArgument(importCertKeystorePassword); 1111 1112 final FileArgument importCertKeystorePasswordFile = new FileArgument(null, 1113 "keystore-password-file", false, 1, null, 1114 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 1115 true, false); 1116 importCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 1117 true); 1118 importCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 1119 true); 1120 importCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 1121 true); 1122 importCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 1123 true); 1124 importCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 1125 importCertParser.addArgument(importCertKeystorePasswordFile); 1126 1127 final BooleanArgument importCertPromptForKeystorePassword = 1128 new BooleanArgument(null, "prompt-for-keystore-password", 1129 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 1130 importCertPromptForKeystorePassword.addLongIdentifier( 1131 "promptForKeystorePassword", true); 1132 importCertPromptForKeystorePassword.addLongIdentifier( 1133 "prompt-for-keystore-passphrase", true); 1134 importCertPromptForKeystorePassword.addLongIdentifier( 1135 "promptForKeystorePassphrase", true); 1136 importCertPromptForKeystorePassword.addLongIdentifier( 1137 "prompt-for-keystore-pin", true); 1138 importCertPromptForKeystorePassword.addLongIdentifier( 1139 "promptForKeystorePIN", true); 1140 importCertParser.addArgument(importCertPromptForKeystorePassword); 1141 1142 final StringArgument importCertKeystoreType = new StringArgument(null, 1143 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 1144 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KS_TYPE_DESC.get(), 1145 ALLOWED_KEYSTORE_TYPE_VALUES); 1146 importCertKeystoreType.addLongIdentifier("key-store-type", true); 1147 importCertKeystoreType.addLongIdentifier("keystoreType", true); 1148 importCertKeystoreType.addLongIdentifier("keystore-format", true); 1149 importCertKeystoreType.addLongIdentifier("key-store-format", true); 1150 importCertKeystoreType.addLongIdentifier("keystoreFormat", true); 1151 importCertKeystoreType.addLongIdentifier("storetype", true); 1152 importCertParser.addArgument(importCertKeystoreType); 1153 1154 final StringArgument importCertAlias = new StringArgument(null, "alias", 1155 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 1156 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_ALIAS_DESC.get()); 1157 importCertAlias.addLongIdentifier("nickname", true); 1158 importCertParser.addArgument(importCertAlias); 1159 1160 final FileArgument importCertCertificateFile = new FileArgument(null, 1161 "certificate-file", true, 0, null, 1162 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_CERT_FILE_DESC.get(), true, true, 1163 true, false); 1164 importCertCertificateFile.addLongIdentifier("certificateFile", true); 1165 importCertCertificateFile.addLongIdentifier("certificate-chain-file", true); 1166 importCertCertificateFile.addLongIdentifier("certificateChainFile", true); 1167 importCertCertificateFile.addLongIdentifier("input-file", true); 1168 importCertCertificateFile.addLongIdentifier("inputFile", true); 1169 importCertCertificateFile.addLongIdentifier("import-file", true); 1170 importCertCertificateFile.addLongIdentifier("importFile", true); 1171 importCertCertificateFile.addLongIdentifier("file", true); 1172 importCertCertificateFile.addLongIdentifier("filename", true); 1173 importCertParser.addArgument(importCertCertificateFile); 1174 1175 final FileArgument importCertPKFile = new FileArgument(null, 1176 "private-key-file", false, 1, null, 1177 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_KEY_FILE_DESC.get(), true, true, 1178 true, false); 1179 importCertPKFile.addLongIdentifier("privateKeyFile", true); 1180 importCertPKFile.addLongIdentifier("key-file", true); 1181 importCertPKFile.addLongIdentifier("keyFile", true); 1182 importCertParser.addArgument(importCertPKFile); 1183 1184 final StringArgument importCertPKPassword = new StringArgument(null, 1185 "private-key-password", false, 1, 1186 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1187 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PK_PW_DESC.get()); 1188 importCertPKPassword.addLongIdentifier("privateKeyPassword", true); 1189 importCertPKPassword.addLongIdentifier("private-key-passphrase", true); 1190 importCertPKPassword.addLongIdentifier("privateKeyPassphrase", true); 1191 importCertPKPassword.addLongIdentifier("private-key-pin", true); 1192 importCertPKPassword.addLongIdentifier("privateKeyPIN", true); 1193 importCertPKPassword.addLongIdentifier("key-password", true); 1194 importCertPKPassword.addLongIdentifier("keyPassword", true); 1195 importCertPKPassword.addLongIdentifier("key-passphrase", true); 1196 importCertPKPassword.addLongIdentifier("keyPassphrase", true); 1197 importCertPKPassword.addLongIdentifier("key-pin", true); 1198 importCertPKPassword.addLongIdentifier("keyPIN", true); 1199 importCertPKPassword.addLongIdentifier("keypass", true); 1200 importCertPKPassword.setSensitive(true); 1201 importCertParser.addArgument(importCertPKPassword); 1202 1203 final FileArgument importCertPKPasswordFile = new FileArgument(null, 1204 "private-key-password-file", false, 1, null, 1205 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PK_PW_FILE_DESC.get(), true, true, 1206 true, false); 1207 importCertPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 1208 importCertPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 1209 true); 1210 importCertPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 1211 true); 1212 importCertPKPasswordFile.addLongIdentifier("private-key-pin-file", 1213 true); 1214 importCertPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 1215 importCertPKPasswordFile.addLongIdentifier("key-password-file", true); 1216 importCertPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 1217 importCertPKPasswordFile.addLongIdentifier("key-passphrase-file", 1218 true); 1219 importCertPKPasswordFile.addLongIdentifier("keyPassphraseFile", 1220 true); 1221 importCertPKPasswordFile.addLongIdentifier("key-pin-file", 1222 true); 1223 importCertPKPasswordFile.addLongIdentifier("keyPINFile", true); 1224 importCertParser.addArgument(importCertPKPasswordFile); 1225 1226 final BooleanArgument importCertPromptForPKPassword = 1227 new BooleanArgument(null, "prompt-for-private-key-password", 1228 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PROMPT_FOR_PK_PW_DESC.get()); 1229 importCertPromptForPKPassword.addLongIdentifier( 1230 "promptForPrivateKeyPassword", true); 1231 importCertPromptForPKPassword.addLongIdentifier( 1232 "prompt-for-private-key-passphrase", true); 1233 importCertPromptForPKPassword.addLongIdentifier( 1234 "promptForPrivateKeyPassphrase", true); 1235 importCertPromptForPKPassword.addLongIdentifier( 1236 "prompt-for-private-key-pin", true); 1237 importCertPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 1238 true); 1239 importCertPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 1240 true); 1241 importCertPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 1242 true); 1243 importCertPromptForPKPassword.addLongIdentifier( 1244 "prompt-for-key-passphrase", true); 1245 importCertPromptForPKPassword.addLongIdentifier( 1246 "promptForKeyPassphrase", true); 1247 importCertPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 1248 importCertPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 1249 importCertParser.addArgument(importCertPromptForPKPassword); 1250 1251 final StringArgument importCertEncryptionPassword = new StringArgument(null, 1252 "encryption-password", false, 1, 1253 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1254 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_ENC_PW_DESC.get()); 1255 importCertEncryptionPassword.addLongIdentifier("encryptionPassword", true); 1256 importCertEncryptionPassword.setSensitive(true); 1257 importCertParser.addArgument(importCertEncryptionPassword); 1258 1259 final FileArgument importCertEncryptionPasswordFile = new FileArgument(null, 1260 "encryption-password-file", false, 1, null, 1261 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_ENC_PW_FILE_DESC.get(), true, 1262 true, true, false); 1263 importCertEncryptionPasswordFile.addLongIdentifier("encryptionPasswordFile", 1264 true); 1265 importCertParser.addArgument(importCertEncryptionPasswordFile); 1266 1267 final BooleanArgument importCertPromptForEncryptionPassword = 1268 new BooleanArgument(null, "prompt-for-encryption-password", 1269 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_PROMPT_FOR_ENC_PW_DESC.get()); 1270 importCertPromptForEncryptionPassword.addLongIdentifier( 1271 "promptForEncryptionPassword", true); 1272 importCertParser.addArgument(importCertPromptForEncryptionPassword); 1273 1274 final BooleanArgument importCertNoPrompt = new BooleanArgument(null, 1275 "no-prompt", 1, 1276 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_NO_PROMPT_DESC.get()); 1277 importCertNoPrompt.addLongIdentifier("noPrompt", true); 1278 importCertParser.addArgument(importCertNoPrompt); 1279 1280 final BooleanArgument importCertDisplayCommand = new BooleanArgument(null, 1281 "display-keytool-command", 1, 1282 INFO_MANAGE_CERTS_SC_IMPORT_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1283 importCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1284 importCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1285 importCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1286 importCertParser.addArgument(importCertDisplayCommand); 1287 1288 importCertParser.addRequiredArgumentSet(importCertKeystorePassword, 1289 importCertKeystorePasswordFile, importCertPromptForKeystorePassword); 1290 importCertParser.addExclusiveArgumentSet(importCertKeystorePassword, 1291 importCertKeystorePasswordFile, importCertPromptForKeystorePassword); 1292 importCertParser.addExclusiveArgumentSet(importCertPKPassword, 1293 importCertPKPasswordFile, importCertPromptForPKPassword); 1294 importCertParser.addExclusiveArgumentSet(importCertEncryptionPassword, 1295 importCertEncryptionPasswordFile, 1296 importCertPromptForEncryptionPassword); 1297 1298 final LinkedHashMap<String[],String> importCertExamples = 1299 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 1300 importCertExamples.put( 1301 new String[] 1302 { 1303 "import-certificate", 1304 "--keystore", getPlatformSpecificPath("config", "keystore"), 1305 "--keystore-password-file", 1306 getPlatformSpecificPath("config", "keystore.pin"), 1307 "--alias", "server-cert", 1308 "--certificate-file", "server-cert.crt" 1309 }, 1310 INFO_MANAGE_CERTS_SC_IMPORT_CERT_EXAMPLE_1.get("server-cert.crt")); 1311 importCertExamples.put( 1312 new String[] 1313 { 1314 "import-certificate", 1315 "--keystore", getPlatformSpecificPath("config", "keystore"), 1316 "--keystore-password-file", 1317 getPlatformSpecificPath("config", "keystore.pin"), 1318 "--alias", "server-cert", 1319 "--certificate-file", "server-cert.crt", 1320 "--certificate-file", "server-cert-issuer.crt", 1321 "--private-key-file", "server-cert.key", 1322 "--display-keytool-command" 1323 }, 1324 INFO_MANAGE_CERTS_SC_IMPORT_CERT_EXAMPLE_2.get()); 1325 1326 final SubCommand importCertSubCommand = new SubCommand("import-certificate", 1327 INFO_MANAGE_CERTS_SC_IMPORT_CERT_DESC.get(), importCertParser, 1328 importCertExamples); 1329 importCertSubCommand.addName("importCertificate", true); 1330 importCertSubCommand.addName("import-certificates", true); 1331 importCertSubCommand.addName("importCertificates", true); 1332 importCertSubCommand.addName("import-cert", true); 1333 importCertSubCommand.addName("importCert", true); 1334 importCertSubCommand.addName("import-certs", true); 1335 importCertSubCommand.addName("importCerts", true); 1336 importCertSubCommand.addName("import-certificate-chain", true); 1337 importCertSubCommand.addName("importCertificateChain", true); 1338 importCertSubCommand.addName("import-chain", true); 1339 importCertSubCommand.addName("importChain", true); 1340 importCertSubCommand.addName("import", true); 1341 1342 parser.addSubCommand(importCertSubCommand); 1343 1344 1345 // Define the "delete-certificate" subcommand and all of its arguments. 1346 final ArgumentParser deleteCertParser = new ArgumentParser( 1347 "delete-certificate", INFO_MANAGE_CERTS_SC_DELETE_CERT_DESC.get()); 1348 1349 final FileArgument deleteCertKeystore = new FileArgument(null, "keystore", 1350 true, 1, null, INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_DESC.get(), 1351 true, true, true, false); 1352 deleteCertKeystore.addLongIdentifier("keystore-path", true); 1353 deleteCertKeystore.addLongIdentifier("keystorePath", true); 1354 deleteCertKeystore.addLongIdentifier("keystore-file", true); 1355 deleteCertKeystore.addLongIdentifier("keystoreFile", true); 1356 deleteCertParser.addArgument(deleteCertKeystore); 1357 1358 final StringArgument deleteCertKeystorePassword = new StringArgument(null, 1359 "keystore-password", false, 1, 1360 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1361 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_PW_DESC.get()); 1362 deleteCertKeystorePassword.addLongIdentifier("keystorePassword", true); 1363 deleteCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 1364 deleteCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 1365 deleteCertKeystorePassword.addLongIdentifier("keystore-pin", true); 1366 deleteCertKeystorePassword.addLongIdentifier("keystorePIN", true); 1367 deleteCertKeystorePassword.addLongIdentifier("storepass", true); 1368 deleteCertKeystorePassword.setSensitive(true); 1369 deleteCertParser.addArgument(deleteCertKeystorePassword); 1370 1371 final FileArgument deleteCertKeystorePasswordFile = new FileArgument(null, 1372 "keystore-password-file", false, 1, null, 1373 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 1374 true, false); 1375 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 1376 true); 1377 deleteCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 1378 true); 1379 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 1380 true); 1381 deleteCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 1382 true); 1383 deleteCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 1384 deleteCertParser.addArgument(deleteCertKeystorePasswordFile); 1385 1386 final BooleanArgument deleteCertPromptForKeystorePassword = 1387 new BooleanArgument(null, "prompt-for-keystore-password", 1388 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 1389 deleteCertPromptForKeystorePassword.addLongIdentifier( 1390 "promptForKeystorePassword", true); 1391 deleteCertPromptForKeystorePassword.addLongIdentifier( 1392 "prompt-for-keystore-passphrase", true); 1393 deleteCertPromptForKeystorePassword.addLongIdentifier( 1394 "promptForKeystorePassphrase", true); 1395 deleteCertPromptForKeystorePassword.addLongIdentifier( 1396 "prompt-for-keystore-pin", true); 1397 deleteCertPromptForKeystorePassword.addLongIdentifier( 1398 "promptForKeystorePIN", true); 1399 deleteCertParser.addArgument(deleteCertPromptForKeystorePassword); 1400 1401 final StringArgument deleteCertKeystoreType = new StringArgument(null, 1402 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 1403 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_KS_TYPE_DESC.get(), 1404 ALLOWED_KEYSTORE_TYPE_VALUES); 1405 deleteCertKeystoreType.addLongIdentifier("key-store-type", true); 1406 deleteCertKeystoreType.addLongIdentifier("keystoreType", true); 1407 deleteCertKeystoreType.addLongIdentifier("keystore-format", true); 1408 deleteCertKeystoreType.addLongIdentifier("key-store-format", true); 1409 deleteCertKeystoreType.addLongIdentifier("keystoreFormat", true); 1410 deleteCertKeystoreType.addLongIdentifier("storetype", true); 1411 deleteCertParser.addArgument(deleteCertKeystoreType); 1412 1413 final StringArgument deleteCertAlias = new StringArgument(null, "alias", 1414 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 1415 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_ALIAS_DESC.get()); 1416 deleteCertAlias.addLongIdentifier("nickname", true); 1417 deleteCertParser.addArgument(deleteCertAlias); 1418 1419 final BooleanArgument deleteCertNoPrompt = new BooleanArgument(null, 1420 "no-prompt", 1, 1421 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_NO_PROMPT_DESC.get()); 1422 deleteCertNoPrompt.addLongIdentifier("noPrompt", true); 1423 deleteCertParser.addArgument(deleteCertNoPrompt); 1424 1425 final BooleanArgument deleteCertDisplayCommand = new BooleanArgument(null, 1426 "display-keytool-command", 1, 1427 INFO_MANAGE_CERTS_SC_DELETE_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1428 deleteCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1429 deleteCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1430 deleteCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1431 deleteCertParser.addArgument(deleteCertDisplayCommand); 1432 1433 deleteCertParser.addExclusiveArgumentSet(deleteCertKeystorePassword, 1434 deleteCertKeystorePasswordFile, deleteCertPromptForKeystorePassword); 1435 deleteCertParser.addRequiredArgumentSet(deleteCertKeystorePassword, 1436 deleteCertKeystorePasswordFile, deleteCertPromptForKeystorePassword); 1437 1438 final LinkedHashMap<String[],String> deleteCertExamples = 1439 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 1440 deleteCertExamples.put( 1441 new String[] 1442 { 1443 "delete-certificate", 1444 "--keystore", getPlatformSpecificPath("config", "keystore"), 1445 "--alias", "server-cert" 1446 }, 1447 INFO_MANAGE_CERTS_SC_DELETE_CERT_EXAMPLE_1.get( 1448 getPlatformSpecificPath("config", "keystore"))); 1449 1450 final SubCommand deleteCertSubCommand = new SubCommand("delete-certificate", 1451 INFO_MANAGE_CERTS_SC_DELETE_CERT_DESC.get(), deleteCertParser, 1452 deleteCertExamples); 1453 deleteCertSubCommand.addName("deleteCertificate", true); 1454 deleteCertSubCommand.addName("remove-certificate", true); 1455 deleteCertSubCommand.addName("removeCertificate", true); 1456 deleteCertSubCommand.addName("delete", true); 1457 deleteCertSubCommand.addName("remove", true); 1458 1459 parser.addSubCommand(deleteCertSubCommand); 1460 1461 1462 // Define the "generate-self-signed-certificate" subcommand and all of its 1463 // arguments. 1464 final ArgumentParser genCertParser = new ArgumentParser( 1465 "generate-self-signed-certificate", 1466 INFO_MANAGE_CERTS_SC_GEN_CERT_DESC.get()); 1467 1468 final FileArgument genCertKeystore = new FileArgument(null, "keystore", 1469 true, 1, null, INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_DESC.get(), false, 1470 true, true, false); 1471 genCertKeystore.addLongIdentifier("keystore-path", true); 1472 genCertKeystore.addLongIdentifier("keystorePath", true); 1473 genCertKeystore.addLongIdentifier("keystore-file", true); 1474 genCertKeystore.addLongIdentifier("keystoreFile", true); 1475 genCertParser.addArgument(genCertKeystore); 1476 1477 final StringArgument genCertKeystorePassword = new StringArgument(null, 1478 "keystore-password", false, 1, 1479 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1480 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_PW_DESC.get()); 1481 genCertKeystorePassword.addLongIdentifier("keystorePassword", true); 1482 genCertKeystorePassword.addLongIdentifier("keystore-passphrase", true); 1483 genCertKeystorePassword.addLongIdentifier("keystorePassphrase", true); 1484 genCertKeystorePassword.addLongIdentifier("keystore-pin", true); 1485 genCertKeystorePassword.addLongIdentifier("keystorePIN", true); 1486 genCertKeystorePassword.addLongIdentifier("storepass", true); 1487 genCertKeystorePassword.setSensitive(true); 1488 genCertParser.addArgument(genCertKeystorePassword); 1489 1490 final FileArgument genCertKeystorePasswordFile = new FileArgument(null, 1491 "keystore-password-file", false, 1, null, 1492 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_PW_FILE_DESC.get(), true, true, 1493 true, false); 1494 genCertKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 1495 true); 1496 genCertKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 1497 true); 1498 genCertKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 1499 true); 1500 genCertKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 1501 true); 1502 genCertKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 1503 genCertParser.addArgument(genCertKeystorePasswordFile); 1504 1505 final BooleanArgument genCertPromptForKeystorePassword = 1506 new BooleanArgument(null, "prompt-for-keystore-password", 1507 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PROMPT_FOR_KS_PW_DESC.get()); 1508 genCertPromptForKeystorePassword.addLongIdentifier( 1509 "promptForKeystorePassword", true); 1510 genCertPromptForKeystorePassword.addLongIdentifier( 1511 "prompt-for-keystore-passphrase", true); 1512 genCertPromptForKeystorePassword.addLongIdentifier( 1513 "promptForKeystorePassphrase", true); 1514 genCertPromptForKeystorePassword.addLongIdentifier( 1515 "prompt-for-keystore-pin", true); 1516 genCertPromptForKeystorePassword.addLongIdentifier( 1517 "promptForKeystorePIN", true); 1518 genCertParser.addArgument(genCertPromptForKeystorePassword); 1519 1520 final StringArgument genCertPKPassword = new StringArgument(null, 1521 "private-key-password", false, 1, 1522 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 1523 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PK_PW_DESC.get()); 1524 genCertPKPassword.addLongIdentifier("privateKeyPassword", true); 1525 genCertPKPassword.addLongIdentifier("private-key-passphrase", true); 1526 genCertPKPassword.addLongIdentifier("privateKeyPassphrase", true); 1527 genCertPKPassword.addLongIdentifier("private-key-pin", true); 1528 genCertPKPassword.addLongIdentifier("privateKeyPIN", true); 1529 genCertPKPassword.addLongIdentifier("key-password", true); 1530 genCertPKPassword.addLongIdentifier("keyPassword", true); 1531 genCertPKPassword.addLongIdentifier("key-passphrase", true); 1532 genCertPKPassword.addLongIdentifier("keyPassphrase", true); 1533 genCertPKPassword.addLongIdentifier("key-pin", true); 1534 genCertPKPassword.addLongIdentifier("keyPIN", true); 1535 genCertPKPassword.addLongIdentifier("keypass", true); 1536 genCertPKPassword.setSensitive(true); 1537 genCertParser.addArgument(genCertPKPassword); 1538 1539 final FileArgument genCertPKPasswordFile = new FileArgument(null, 1540 "private-key-password-file", false, 1, null, 1541 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PK_PW_FILE_DESC.get(), true, true, 1542 true, false); 1543 genCertPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 1544 genCertPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 1545 true); 1546 genCertPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 1547 true); 1548 genCertPKPasswordFile.addLongIdentifier("private-key-pin-file", 1549 true); 1550 genCertPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 1551 genCertPKPasswordFile.addLongIdentifier("key-password-file", true); 1552 genCertPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 1553 genCertPKPasswordFile.addLongIdentifier("key-passphrase-file", 1554 true); 1555 genCertPKPasswordFile.addLongIdentifier("keyPassphraseFile", 1556 true); 1557 genCertPKPasswordFile.addLongIdentifier("key-pin-file", 1558 true); 1559 genCertPKPasswordFile.addLongIdentifier("keyPINFile", true); 1560 genCertParser.addArgument(genCertPKPasswordFile); 1561 1562 final BooleanArgument genCertPromptForPKPassword = 1563 new BooleanArgument(null, "prompt-for-private-key-password", 1564 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_PROMPT_FOR_PK_PW_DESC.get()); 1565 genCertPromptForPKPassword.addLongIdentifier( 1566 "promptForPrivateKeyPassword", true); 1567 genCertPromptForPKPassword.addLongIdentifier( 1568 "prompt-for-private-key-passphrase", true); 1569 genCertPromptForPKPassword.addLongIdentifier( 1570 "promptForPrivateKeyPassphrase", true); 1571 genCertPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 1572 true); 1573 genCertPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 1574 true); 1575 genCertPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 1576 true); 1577 genCertPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 1578 true); 1579 genCertPromptForPKPassword.addLongIdentifier( 1580 "prompt-for-key-passphrase", true); 1581 genCertPromptForPKPassword.addLongIdentifier( 1582 "promptForKeyPassphrase", true); 1583 genCertPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 1584 genCertPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 1585 genCertParser.addArgument(genCertPromptForPKPassword); 1586 1587 final StringArgument genCertKeystoreType = new StringArgument(null, 1588 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 1589 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KS_TYPE_DESC.get(), 1590 ALLOWED_KEYSTORE_TYPE_VALUES); 1591 genCertKeystoreType.addLongIdentifier("key-store-type", true); 1592 genCertKeystoreType.addLongIdentifier("keystoreType", true); 1593 genCertKeystoreType.addLongIdentifier("keystore-format", true); 1594 genCertKeystoreType.addLongIdentifier("key-store-format", true); 1595 genCertKeystoreType.addLongIdentifier("keystoreFormat", true); 1596 genCertKeystoreType.addLongIdentifier("storetype", true); 1597 genCertParser.addArgument(genCertKeystoreType); 1598 1599 final StringArgument genCertAlias = new StringArgument(null, "alias", 1600 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 1601 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_ALIAS_DESC.get()); 1602 genCertAlias.addLongIdentifier("nickname", true); 1603 genCertParser.addArgument(genCertAlias); 1604 1605 final BooleanArgument genCertUseExistingKeyPair = new BooleanArgument(null, 1606 "use-existing-key-pair", 1, 1607 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_USE_EXISTING_KP_DESC.get()); 1608 genCertUseExistingKeyPair.addLongIdentifier("use-existing-keypair", true); 1609 genCertUseExistingKeyPair.addLongIdentifier("useExistingKeypair", true); 1610 genCertUseExistingKeyPair.addLongIdentifier("replace-existing-certificate", 1611 true); 1612 genCertUseExistingKeyPair.addLongIdentifier("replaceExistingCertificate", 1613 true); 1614 genCertUseExistingKeyPair.addLongIdentifier("replace-certificate", true); 1615 genCertUseExistingKeyPair.addLongIdentifier("replaceCertificate", true); 1616 genCertUseExistingKeyPair.addLongIdentifier("replace-existing", true); 1617 genCertUseExistingKeyPair.addLongIdentifier("replaceExisting", true); 1618 genCertUseExistingKeyPair.addLongIdentifier("replace", true); 1619 genCertParser.addArgument(genCertUseExistingKeyPair); 1620 1621 final DNArgument genCertSubjectDN = new DNArgument(null, "subject-dn", 1622 false, 1, null, 1623 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SUBJECT_DN_DESC.get()); 1624 genCertSubjectDN.addLongIdentifier("subjectDN", true); 1625 genCertSubjectDN.addLongIdentifier("subject", true); 1626 genCertSubjectDN.addLongIdentifier("dname", true); 1627 genCertParser.addArgument(genCertSubjectDN); 1628 1629 final IntegerArgument genCertDaysValid = new IntegerArgument(null, 1630 "days-valid", false, 1, null, 1631 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_DAYS_VALID_DESC.get(), 1, 1632 Integer.MAX_VALUE); 1633 genCertDaysValid.addLongIdentifier("daysValid", true); 1634 genCertDaysValid.addLongIdentifier("validity", true); 1635 genCertParser.addArgument(genCertDaysValid); 1636 1637 final TimestampArgument genCertNotBefore = new TimestampArgument(null, 1638 "validity-start-time", false, 1, 1639 INFO_MANAGE_CERTS_PLACEHOLDER_TIMESTAMP.get(), 1640 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_VALIDITY_START_TIME_DESC.get( 1641 "20180102123456")); 1642 genCertNotBefore.addLongIdentifier("validityStartTime", true); 1643 genCertNotBefore.addLongIdentifier("not-before", true); 1644 genCertNotBefore.addLongIdentifier("notBefore", true); 1645 genCertParser.addArgument(genCertNotBefore); 1646 1647 final StringArgument genCertKeyAlgorithm = new StringArgument(null, 1648 "key-algorithm", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1649 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KEY_ALGORITHM_DESC.get()); 1650 genCertKeyAlgorithm.addLongIdentifier("keyAlgorithm", true); 1651 genCertKeyAlgorithm.addLongIdentifier("key-alg", true); 1652 genCertKeyAlgorithm.addLongIdentifier("keyAlg", true); 1653 genCertParser.addArgument(genCertKeyAlgorithm); 1654 1655 final IntegerArgument genCertKeySizeBits = new IntegerArgument(null, 1656 "key-size-bits", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_BITS.get(), 1657 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KEY_SIZE_BITS_DESC.get(), 1, 1658 Integer.MAX_VALUE); 1659 genCertKeySizeBits.addLongIdentifier("keySizeBits", true); 1660 genCertKeySizeBits.addLongIdentifier("key-length-bits", true); 1661 genCertKeySizeBits.addLongIdentifier("keyLengthBits", true); 1662 genCertKeySizeBits.addLongIdentifier("key-size", true); 1663 genCertKeySizeBits.addLongIdentifier("keySize", true); 1664 genCertKeySizeBits.addLongIdentifier("key-length", true); 1665 genCertKeySizeBits.addLongIdentifier("keyLength", true); 1666 genCertParser.addArgument(genCertKeySizeBits); 1667 1668 final StringArgument genCertSignatureAlgorithm = new StringArgument(null, 1669 "signature-algorithm", false, 1, 1670 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1671 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SIG_ALG_DESC.get()); 1672 genCertSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 1673 genCertSignatureAlgorithm.addLongIdentifier("signature-alg", true); 1674 genCertSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 1675 genCertSignatureAlgorithm.addLongIdentifier("sig-alg", true); 1676 genCertSignatureAlgorithm.addLongIdentifier("sigAlg", true); 1677 genCertParser.addArgument(genCertSignatureAlgorithm); 1678 1679 final BooleanArgument genCertInheritExtensions = new BooleanArgument(null, 1680 "inherit-extensions", 1, 1681 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_INHERIT_EXT_DESC.get()); 1682 genCertInheritExtensions.addLongIdentifier("inheritExtensions", true); 1683 genCertParser.addArgument(genCertInheritExtensions); 1684 1685 final StringArgument genCertSubjectAltDNS = new StringArgument(null, 1686 "subject-alternative-name-dns", false, 0, 1687 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1688 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_DNS_DESC.get()); 1689 genCertSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 1690 genCertSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 1691 genCertSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 1692 genCertSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 1693 genCertSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 1694 genCertSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 1695 genCertSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 1696 genCertSubjectAltDNS.addLongIdentifier("san-dns", true); 1697 genCertSubjectAltDNS.addLongIdentifier("sanDNS", true); 1698 genCertSubjectAltDNS.addValueValidator( 1699 new IA5StringArgumentValueValidator(false)); 1700 genCertParser.addArgument(genCertSubjectAltDNS); 1701 1702 final StringArgument genCertSubjectAltIP = new StringArgument(null, 1703 "subject-alternative-name-ip-address", false, 0, 1704 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1705 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_IP_DESC.get()); 1706 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 1707 true); 1708 genCertSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 1709 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 1710 genCertSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 1711 genCertSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 1712 genCertSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 1713 genCertSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 1714 genCertSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 1715 true); 1716 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 1717 genCertSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 1718 genCertSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 1719 genCertSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 1720 genCertSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 1721 genCertSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 1722 genCertSubjectAltIP.addLongIdentifier("subjectAltIP", true); 1723 genCertSubjectAltIP.addLongIdentifier("san-ip-address", true); 1724 genCertSubjectAltIP.addLongIdentifier("sanIPAddress", true); 1725 genCertSubjectAltIP.addLongIdentifier("san-ip", true); 1726 genCertSubjectAltIP.addLongIdentifier("sanIP", true); 1727 genCertSubjectAltIP.addValueValidator( 1728 new IPAddressArgumentValueValidator(true, true)); 1729 genCertParser.addArgument(genCertSubjectAltIP); 1730 1731 final StringArgument genCertSubjectAltEmail = new StringArgument(null, 1732 "subject-alternative-name-email-address", false, 0, 1733 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 1734 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_EMAIL_DESC.get()); 1735 genCertSubjectAltEmail.addLongIdentifier( 1736 "subjectAlternativeNameEmailAddress", true); 1737 genCertSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 1738 true); 1739 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 1740 true); 1741 genCertSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 1742 true); 1743 genCertSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 1744 true); 1745 genCertSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 1746 genCertSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 1747 genCertSubjectAltEmail.addLongIdentifier( 1748 "subject-alternative-email-address", true); 1749 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 1750 true); 1751 genCertSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 1752 genCertSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 1753 genCertSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 1754 genCertSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 1755 genCertSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 1756 genCertSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 1757 genCertSubjectAltEmail.addLongIdentifier("san-email-address", true); 1758 genCertSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 1759 genCertSubjectAltEmail.addLongIdentifier("san-email", true); 1760 genCertSubjectAltEmail.addLongIdentifier("sanEmail", true); 1761 genCertSubjectAltEmail.addValueValidator( 1762 new IA5StringArgumentValueValidator(false)); 1763 genCertParser.addArgument(genCertSubjectAltEmail); 1764 1765 final StringArgument genCertSubjectAltURI = new StringArgument(null, 1766 "subject-alternative-name-uri", false, 0, 1767 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 1768 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_URI_DESC.get()); 1769 genCertSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 1770 genCertSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 1771 genCertSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 1772 genCertSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 1773 genCertSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 1774 genCertSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 1775 genCertSubjectAltURI.addLongIdentifier("subjectAltURI", true); 1776 genCertSubjectAltURI.addLongIdentifier("san-uri", true); 1777 genCertSubjectAltURI.addLongIdentifier("sanURI", true); 1778 genCertParser.addArgument(genCertSubjectAltURI); 1779 1780 final StringArgument genCertSubjectAltOID = new StringArgument(null, 1781 "subject-alternative-name-oid", false, 0, 1782 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 1783 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_SAN_OID_DESC.get()); 1784 genCertSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 1785 genCertSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 1786 genCertSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 1787 genCertSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 1788 genCertSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 1789 genCertSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 1790 genCertSubjectAltOID.addLongIdentifier("subjectAltOID", true); 1791 genCertSubjectAltOID.addLongIdentifier("san-oid", true); 1792 genCertSubjectAltOID.addLongIdentifier("sanOID", true); 1793 genCertSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 1794 genCertParser.addArgument(genCertSubjectAltOID); 1795 1796 final BooleanValueArgument genCertBasicConstraintsIsCA = 1797 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 1798 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_IS_CA_DESC.get()); 1799 genCertBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 1800 genCertBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 1801 genCertBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 1802 genCertParser.addArgument(genCertBasicConstraintsIsCA); 1803 1804 final IntegerArgument genCertBasicConstraintsPathLength = 1805 new IntegerArgument(null, "basic-constraints-maximum-path-length", 1806 false, 1, null, 1807 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 1808 Integer.MAX_VALUE); 1809 genCertBasicConstraintsPathLength.addLongIdentifier( 1810 "basicConstraintsMaximumPathLength", true); 1811 genCertBasicConstraintsPathLength.addLongIdentifier( 1812 "basic-constraints-max-path-length", true); 1813 genCertBasicConstraintsPathLength.addLongIdentifier( 1814 "basicConstraintsMaxPathLength", true); 1815 genCertBasicConstraintsPathLength.addLongIdentifier( 1816 "basic-constraints-path-length", true); 1817 genCertBasicConstraintsPathLength.addLongIdentifier( 1818 "basicConstraintsPathLength", true); 1819 genCertBasicConstraintsPathLength.addLongIdentifier( 1820 "bc-maximum-path-length", true); 1821 genCertBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 1822 true); 1823 genCertBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 1824 true); 1825 genCertBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 1826 true); 1827 genCertBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 1828 genCertBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 1829 genCertParser.addArgument(genCertBasicConstraintsPathLength); 1830 1831 final StringArgument genCertKeyUsage = new StringArgument(null, "key-usage", 1832 false, 0, null, INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_KU_DESC.get()); 1833 genCertKeyUsage.addLongIdentifier("keyUsage", true); 1834 genCertParser.addArgument(genCertKeyUsage); 1835 1836 final StringArgument genCertExtendedKeyUsage = new StringArgument(null, 1837 "extended-key-usage", false, 0, null, 1838 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_EKU_DESC.get()); 1839 genCertExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 1840 genCertParser.addArgument(genCertExtendedKeyUsage); 1841 1842 final StringArgument genCertExtension = new StringArgument(null, 1843 "extension", false, 0, null, 1844 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_EXT_DESC.get()); 1845 genCertExtension.addLongIdentifier("ext", true); 1846 genCertParser.addArgument(genCertExtension); 1847 1848 final FileArgument genCertOutputFile = new FileArgument(null, "output-file", 1849 false, 1, null, 1850 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_OUTPUT_FILE_DESC.get(), false, true, 1851 true, false); 1852 genCertOutputFile.addLongIdentifier("outputFile", true); 1853 genCertOutputFile.addLongIdentifier("filename", true); 1854 genCertOutputFile.addLongIdentifier("file", true); 1855 genCertParser.addArgument(genCertOutputFile); 1856 1857 final Set<String> genCertOutputFormatAllowedValues = StaticUtils.setOf( 1858 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 1859 final StringArgument genCertOutputFormat = new StringArgument(null, 1860 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 1861 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_FORMAT_DESC.get(), 1862 genCertOutputFormatAllowedValues, "PEM"); 1863 genCertOutputFormat.addLongIdentifier("outputFormat", true); 1864 genCertParser.addArgument(genCertOutputFormat); 1865 1866 final BooleanArgument genCertDisplayCommand = new BooleanArgument(null, 1867 "display-keytool-command", 1, 1868 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 1869 genCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 1870 genCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 1871 genCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 1872 genCertParser.addArgument(genCertDisplayCommand); 1873 1874 genCertParser.addRequiredArgumentSet(genCertKeystorePassword, 1875 genCertKeystorePasswordFile, genCertPromptForKeystorePassword); 1876 genCertParser.addExclusiveArgumentSet(genCertKeystorePassword, 1877 genCertKeystorePasswordFile, genCertPromptForKeystorePassword); 1878 genCertParser.addExclusiveArgumentSet(genCertPKPassword, 1879 genCertPKPasswordFile, genCertPromptForPKPassword); 1880 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1881 genCertKeyAlgorithm); 1882 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1883 genCertKeySizeBits); 1884 genCertParser.addExclusiveArgumentSet(genCertUseExistingKeyPair, 1885 genCertSignatureAlgorithm); 1886 genCertParser.addDependentArgumentSet(genCertBasicConstraintsPathLength, 1887 genCertBasicConstraintsIsCA); 1888 genCertParser.addDependentArgumentSet(genCertOutputFormat, 1889 genCertOutputFile); 1890 1891 final LinkedHashMap<String[],String> genCertExamples = 1892 new LinkedHashMap<>(StaticUtils.computeMapCapacity(4)); 1893 genCertExamples.put( 1894 new String[] 1895 { 1896 "generate-self-signed-certificate", 1897 "--keystore", getPlatformSpecificPath("config", "keystore"), 1898 "--keystore-password-file", 1899 getPlatformSpecificPath("config", "keystore.pin"), 1900 "--alias", "server-cert", 1901 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US" 1902 }, 1903 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_1.get()); 1904 genCertExamples.put( 1905 new String[] 1906 { 1907 "generate-self-signed-certificate", 1908 "--keystore", getPlatformSpecificPath("config", "keystore"), 1909 "--keystore-password-file", 1910 getPlatformSpecificPath("config", "keystore.pin"), 1911 "--alias", "server-cert", 1912 "--use-existing-key-pair", 1913 "--inherit-extensions" 1914 }, 1915 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_2.get()); 1916 genCertExamples.put( 1917 new String[] 1918 { 1919 "generate-self-signed-certificate", 1920 "--keystore", getPlatformSpecificPath("config", "keystore"), 1921 "--keystore-password-file", 1922 getPlatformSpecificPath("config", "keystore.pin"), 1923 "--alias", "server-cert", 1924 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US", 1925 "--days-valid", "3650", 1926 "--validity-start-time", "20170101000000", 1927 "--key-algorithm", "RSA", 1928 "--key-size-bits", "4096", 1929 "--signature-algorithm", "SHA256withRSA", 1930 "--subject-alternative-name-dns", "ldap1.example.com", 1931 "--subject-alternative-name-dns", "ldap2.example.com", 1932 "--subject-alternative-name-ip-address", "1.2.3.4", 1933 "--subject-alternative-name-ip-address", "1.2.3.5", 1934 "--extended-key-usage", "server-auth", 1935 "--extended-key-usage", "client-auth", 1936 "--display-keytool-command" 1937 }, 1938 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_3.get()); 1939 genCertExamples.put( 1940 new String[] 1941 { 1942 "generate-self-signed-certificate", 1943 "--keystore", getPlatformSpecificPath("config", "keystore"), 1944 "--keystore-password-file", 1945 getPlatformSpecificPath("config", "keystore.pin"), 1946 "--alias", "ca-cert", 1947 "--subject-dn", 1948 "CN=Example Certification Authority,O=Example Corp,C=US", 1949 "--days-valid", "7300", 1950 "--validity-start-time", "20170101000000", 1951 "--key-algorithm", "EC", 1952 "--key-size-bits", "256", 1953 "--signature-algorithm", "SHA256withECDSA", 1954 "--basic-constraints-is-ca", "true", 1955 "--key-usage", "key-cert-sign", 1956 "--key-usage", "crl-sign", 1957 "--display-keytool-command" 1958 }, 1959 INFO_MANAGE_CERTS_SC_GEN_CERT_EXAMPLE_4.get()); 1960 1961 final SubCommand genCertSubCommand = new SubCommand( 1962 "generate-self-signed-certificate", 1963 INFO_MANAGE_CERTS_SC_GEN_CERT_DESC.get(), genCertParser, 1964 genCertExamples); 1965 genCertSubCommand.addName("generateSelfSignedCertificate", true); 1966 genCertSubCommand.addName("generate-certificate", true); 1967 genCertSubCommand.addName("generateCertificate", true); 1968 genCertSubCommand.addName("self-signed-certificate", true); 1969 genCertSubCommand.addName("selfSignedCertificate", true); 1970 genCertSubCommand.addName("selfcert", true); 1971 1972 parser.addSubCommand(genCertSubCommand); 1973 1974 1975 // Define the "generate-certificate-signing-request" subcommand and all of 1976 // its arguments. 1977 final ArgumentParser genCSRParser = new ArgumentParser( 1978 "generate-certificate-signing-request", 1979 INFO_MANAGE_CERTS_SC_GEN_CSR_DESC.get()); 1980 1981 final Set<String> genCSROutputFormatAllowedValues = StaticUtils.setOf( 1982 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 1983 final StringArgument genCSROutputFormat = new StringArgument(null, 1984 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 1985 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_FORMAT_DESC.get(), 1986 genCSROutputFormatAllowedValues, "PEM"); 1987 genCSROutputFormat.addLongIdentifier("outputFormat", true); 1988 genCSRParser.addArgument(genCSROutputFormat); 1989 1990 final FileArgument genCSROutputFile = new FileArgument(null, "output-file", 1991 false, 1, null, 1992 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_OUTPUT_FILE_DESC.get(), false, true, 1993 true, false); 1994 genCSROutputFile.addLongIdentifier("outputFile", true); 1995 genCSROutputFile.addLongIdentifier("filename", true); 1996 genCSROutputFile.addLongIdentifier("file", true); 1997 genCSRParser.addArgument(genCSROutputFile); 1998 1999 final FileArgument genCSRKeystore = new FileArgument(null, "keystore", 2000 true, 1, null, INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_DESC.get(), false, 2001 true, true, false); 2002 genCSRKeystore.addLongIdentifier("keystore-path", true); 2003 genCSRKeystore.addLongIdentifier("keystorePath", true); 2004 genCSRKeystore.addLongIdentifier("keystore-file", true); 2005 genCSRKeystore.addLongIdentifier("keystoreFile", true); 2006 genCSRParser.addArgument(genCSRKeystore); 2007 2008 final StringArgument genCSRKeystorePassword = new StringArgument(null, 2009 "keystore-password", false, 1, 2010 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2011 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_PW_DESC.get()); 2012 genCSRKeystorePassword.addLongIdentifier("keystorePassword", true); 2013 genCSRKeystorePassword.addLongIdentifier("keystore-passphrase", true); 2014 genCSRKeystorePassword.addLongIdentifier("keystorePassphrase", true); 2015 genCSRKeystorePassword.addLongIdentifier("keystore-pin", true); 2016 genCSRKeystorePassword.addLongIdentifier("keystorePIN", true); 2017 genCSRKeystorePassword.addLongIdentifier("storepass", true); 2018 genCSRKeystorePassword.setSensitive(true); 2019 genCSRParser.addArgument(genCSRKeystorePassword); 2020 2021 final FileArgument genCSRKeystorePasswordFile = new FileArgument(null, 2022 "keystore-password-file", false, 1, null, 2023 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_PW_FILE_DESC.get(), true, true, 2024 true, false); 2025 genCSRKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 2026 true); 2027 genCSRKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 2028 true); 2029 genCSRKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 2030 true); 2031 genCSRKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 2032 true); 2033 genCSRKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 2034 genCSRParser.addArgument(genCSRKeystorePasswordFile); 2035 2036 final BooleanArgument genCSRPromptForKeystorePassword = 2037 new BooleanArgument(null, "prompt-for-keystore-password", 2038 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PROMPT_FOR_KS_PW_DESC.get()); 2039 genCSRPromptForKeystorePassword.addLongIdentifier( 2040 "promptForKeystorePassword", true); 2041 genCSRPromptForKeystorePassword.addLongIdentifier( 2042 "prompt-for-keystore-passphrase", true); 2043 genCSRPromptForKeystorePassword.addLongIdentifier( 2044 "promptForKeystorePassphrase", true); 2045 genCSRPromptForKeystorePassword.addLongIdentifier( 2046 "prompt-for-keystore-pin", true); 2047 genCSRPromptForKeystorePassword.addLongIdentifier( 2048 "promptForKeystorePIN", true); 2049 genCSRParser.addArgument(genCSRPromptForKeystorePassword); 2050 2051 final StringArgument genCSRPKPassword = new StringArgument(null, 2052 "private-key-password", false, 1, 2053 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2054 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PK_PW_DESC.get()); 2055 genCSRPKPassword.addLongIdentifier("privateKeyPassword", true); 2056 genCSRPKPassword.addLongIdentifier("private-key-passphrase", true); 2057 genCSRPKPassword.addLongIdentifier("privateKeyPassphrase", true); 2058 genCSRPKPassword.addLongIdentifier("private-key-pin", true); 2059 genCSRPKPassword.addLongIdentifier("privateKeyPIN", true); 2060 genCSRPKPassword.addLongIdentifier("key-password", true); 2061 genCSRPKPassword.addLongIdentifier("keyPassword", true); 2062 genCSRPKPassword.addLongIdentifier("key-passphrase", true); 2063 genCSRPKPassword.addLongIdentifier("keyPassphrase", true); 2064 genCSRPKPassword.addLongIdentifier("key-pin", true); 2065 genCSRPKPassword.addLongIdentifier("keyPIN", true); 2066 genCSRPKPassword.addLongIdentifier("keypass", true); 2067 genCSRPKPassword.setSensitive(true); 2068 genCSRParser.addArgument(genCSRPKPassword); 2069 2070 final FileArgument genCSRPKPasswordFile = new FileArgument(null, 2071 "private-key-password-file", false, 1, null, 2072 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PK_PW_FILE_DESC.get(), true, true, 2073 true, false); 2074 genCSRPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 2075 genCSRPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 2076 true); 2077 genCSRPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 2078 true); 2079 genCSRPKPasswordFile.addLongIdentifier("private-key-pin-file", 2080 true); 2081 genCSRPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 2082 genCSRPKPasswordFile.addLongIdentifier("key-password-file", true); 2083 genCSRPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 2084 genCSRPKPasswordFile.addLongIdentifier("key-passphrase-file", 2085 true); 2086 genCSRPKPasswordFile.addLongIdentifier("keyPassphraseFile", 2087 true); 2088 genCSRPKPasswordFile.addLongIdentifier("key-pin-file", 2089 true); 2090 genCSRPKPasswordFile.addLongIdentifier("keyPINFile", true); 2091 genCSRParser.addArgument(genCSRPKPasswordFile); 2092 2093 final BooleanArgument genCSRPromptForPKPassword = 2094 new BooleanArgument(null, "prompt-for-private-key-password", 2095 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_PROMPT_FOR_PK_PW_DESC.get()); 2096 genCSRPromptForPKPassword.addLongIdentifier( 2097 "promptForPrivateKeyPassword", true); 2098 genCSRPromptForPKPassword.addLongIdentifier( 2099 "prompt-for-private-key-passphrase", true); 2100 genCSRPromptForPKPassword.addLongIdentifier( 2101 "promptForPrivateKeyPassphrase", true); 2102 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 2103 true); 2104 genCSRPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 2105 true); 2106 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 2107 true); 2108 genCSRPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 2109 true); 2110 genCSRPromptForPKPassword.addLongIdentifier( 2111 "prompt-for-key-passphrase", true); 2112 genCSRPromptForPKPassword.addLongIdentifier( 2113 "promptForKeyPassphrase", true); 2114 genCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 2115 genCSRPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 2116 genCSRParser.addArgument(genCSRPromptForPKPassword); 2117 2118 final StringArgument genCSRKeystoreType = new StringArgument(null, 2119 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 2120 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KS_TYPE_DESC.get(), 2121 ALLOWED_KEYSTORE_TYPE_VALUES); 2122 genCSRKeystoreType.addLongIdentifier("key-store-type", true); 2123 genCSRKeystoreType.addLongIdentifier("keystoreType", true); 2124 genCSRKeystoreType.addLongIdentifier("keystore-format", true); 2125 genCSRKeystoreType.addLongIdentifier("key-store-format", true); 2126 genCSRKeystoreType.addLongIdentifier("keystoreFormat", true); 2127 genCSRKeystoreType.addLongIdentifier("storetype", true); 2128 genCSRParser.addArgument(genCSRKeystoreType); 2129 2130 final StringArgument genCSRAlias = new StringArgument(null, "alias", 2131 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 2132 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_ALIAS_DESC.get()); 2133 genCSRAlias.addLongIdentifier("nickname", true); 2134 genCSRParser.addArgument(genCSRAlias); 2135 2136 final BooleanArgument genCSRUseExistingKeyPair = new BooleanArgument(null, 2137 "use-existing-key-pair", 1, 2138 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_USE_EXISTING_KP_DESC.get()); 2139 genCSRUseExistingKeyPair.addLongIdentifier("use-existing-keypair", true); 2140 genCSRUseExistingKeyPair.addLongIdentifier("useExistingKeyPair", true); 2141 genCSRUseExistingKeyPair.addLongIdentifier("replace-existing-certificate", 2142 true); 2143 genCSRUseExistingKeyPair.addLongIdentifier("replaceExistingCertificate", 2144 true); 2145 genCSRUseExistingKeyPair.addLongIdentifier("replace-certificate", true); 2146 genCSRUseExistingKeyPair.addLongIdentifier("replaceCertificate", true); 2147 genCSRUseExistingKeyPair.addLongIdentifier("replace-existing", true); 2148 genCSRUseExistingKeyPair.addLongIdentifier("replaceExisting", true); 2149 genCSRUseExistingKeyPair.addLongIdentifier("replace", true); 2150 genCSRParser.addArgument(genCSRUseExistingKeyPair); 2151 2152 final DNArgument genCSRSubjectDN = new DNArgument(null, "subject-dn", 2153 false, 1, null, 2154 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SUBJECT_DN_DESC.get()); 2155 genCSRSubjectDN.addLongIdentifier("subjectDN", true); 2156 genCSRSubjectDN.addLongIdentifier("subject", true); 2157 genCSRSubjectDN.addLongIdentifier("dname", true); 2158 genCSRParser.addArgument(genCSRSubjectDN); 2159 2160 final StringArgument genCSRKeyAlgorithm = new StringArgument(null, 2161 "key-algorithm", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2162 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KEY_ALGORITHM_DESC.get()); 2163 genCSRKeyAlgorithm.addLongIdentifier("keyAlgorithm", true); 2164 genCSRKeyAlgorithm.addLongIdentifier("key-alg", true); 2165 genCSRKeyAlgorithm.addLongIdentifier("keyAlg", true); 2166 genCSRParser.addArgument(genCSRKeyAlgorithm); 2167 2168 final IntegerArgument genCSRKeySizeBits = new IntegerArgument(null, 2169 "key-size-bits", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_BITS.get(), 2170 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KEY_SIZE_BITS_DESC.get(), 1, 2171 Integer.MAX_VALUE); 2172 genCSRKeySizeBits.addLongIdentifier("keySizeBits", true); 2173 genCSRKeySizeBits.addLongIdentifier("key-length-bits", true); 2174 genCSRKeySizeBits.addLongIdentifier("keyLengthBits", true); 2175 genCSRKeySizeBits.addLongIdentifier("key-size", true); 2176 genCSRKeySizeBits.addLongIdentifier("keySize", true); 2177 genCSRKeySizeBits.addLongIdentifier("key-length", true); 2178 genCSRKeySizeBits.addLongIdentifier("keyLength", true); 2179 genCSRParser.addArgument(genCSRKeySizeBits); 2180 2181 final StringArgument genCSRSignatureAlgorithm = new StringArgument(null, 2182 "signature-algorithm", false, 1, 2183 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2184 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SIG_ALG_DESC.get()); 2185 genCSRSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 2186 genCSRSignatureAlgorithm.addLongIdentifier("signature-alg", true); 2187 genCSRSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 2188 genCSRSignatureAlgorithm.addLongIdentifier("sig-alg", true); 2189 genCSRSignatureAlgorithm.addLongIdentifier("sigAlg", true); 2190 genCSRParser.addArgument(genCSRSignatureAlgorithm); 2191 2192 final BooleanArgument genCSRInheritExtensions = new BooleanArgument(null, 2193 "inherit-extensions", 1, 2194 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_INHERIT_EXT_DESC.get()); 2195 genCSRInheritExtensions.addLongIdentifier("inheritExtensions", true); 2196 genCSRParser.addArgument(genCSRInheritExtensions); 2197 2198 final StringArgument genCSRSubjectAltDNS = new StringArgument(null, 2199 "subject-alternative-name-dns", false, 0, 2200 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2201 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_DNS_DESC.get()); 2202 genCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 2203 genCSRSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 2204 genCSRSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 2205 genCSRSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 2206 genCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 2207 genCSRSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 2208 genCSRSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 2209 genCSRSubjectAltDNS.addLongIdentifier("san-dns", true); 2210 genCSRSubjectAltDNS.addLongIdentifier("sanDNS", true); 2211 genCSRSubjectAltDNS.addValueValidator( 2212 new IA5StringArgumentValueValidator(false)); 2213 genCSRParser.addArgument(genCSRSubjectAltDNS); 2214 2215 final StringArgument genCSRSubjectAltIP = new StringArgument(null, 2216 "subject-alternative-name-ip-address", false, 0, 2217 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2218 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_IP_DESC.get()); 2219 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 2220 true); 2221 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 2222 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 2223 genCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 2224 genCSRSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 2225 genCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 2226 genCSRSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 2227 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 2228 true); 2229 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 2230 genCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 2231 genCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 2232 genCSRSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 2233 genCSRSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 2234 genCSRSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 2235 genCSRSubjectAltIP.addLongIdentifier("subjectAltIP", true); 2236 genCSRSubjectAltIP.addLongIdentifier("san-ip-address", true); 2237 genCSRSubjectAltIP.addLongIdentifier("sanIPAddress", true); 2238 genCSRSubjectAltIP.addLongIdentifier("san-ip", true); 2239 genCSRSubjectAltIP.addLongIdentifier("sanIP", true); 2240 genCSRSubjectAltIP.addValueValidator( 2241 new IPAddressArgumentValueValidator(true, true)); 2242 genCSRParser.addArgument(genCSRSubjectAltIP); 2243 2244 final StringArgument genCSRSubjectAltEmail = new StringArgument(null, 2245 "subject-alternative-name-email-address", false, 0, 2246 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2247 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_EMAIL_DESC.get()); 2248 genCSRSubjectAltEmail.addLongIdentifier( 2249 "subjectAlternativeNameEmailAddress", true); 2250 genCSRSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 2251 true); 2252 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 2253 true); 2254 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 2255 true); 2256 genCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 2257 true); 2258 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 2259 genCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 2260 genCSRSubjectAltEmail.addLongIdentifier( 2261 "subject-alternative-email-address", true); 2262 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 2263 true); 2264 genCSRSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 2265 genCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 2266 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 2267 genCSRSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 2268 genCSRSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 2269 genCSRSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 2270 genCSRSubjectAltEmail.addLongIdentifier("san-email-address", true); 2271 genCSRSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 2272 genCSRSubjectAltEmail.addLongIdentifier("san-email", true); 2273 genCSRSubjectAltEmail.addLongIdentifier("sanEmail", true); 2274 genCSRSubjectAltEmail.addValueValidator( 2275 new IA5StringArgumentValueValidator(false)); 2276 genCSRParser.addArgument(genCSRSubjectAltEmail); 2277 2278 final StringArgument genCSRSubjectAltURI = new StringArgument(null, 2279 "subject-alternative-name-uri", false, 0, 2280 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2281 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_URI_DESC.get()); 2282 genCSRSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 2283 genCSRSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 2284 genCSRSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 2285 genCSRSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 2286 genCSRSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 2287 genCSRSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 2288 genCSRSubjectAltURI.addLongIdentifier("subjectAltURI", true); 2289 genCSRSubjectAltURI.addLongIdentifier("san-uri", true); 2290 genCSRSubjectAltURI.addLongIdentifier("sanURI", true); 2291 genCSRParser.addArgument(genCSRSubjectAltURI); 2292 2293 final StringArgument genCSRSubjectAltOID = new StringArgument(null, 2294 "subject-alternative-name-oid", false, 0, 2295 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2296 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_SAN_OID_DESC.get()); 2297 genCSRSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 2298 genCSRSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 2299 genCSRSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 2300 genCSRSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 2301 genCSRSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 2302 genCSRSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 2303 genCSRSubjectAltOID.addLongIdentifier("subjectAltOID", true); 2304 genCSRSubjectAltOID.addLongIdentifier("san-oid", true); 2305 genCSRSubjectAltOID.addLongIdentifier("sanOID", true); 2306 genCSRSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2307 genCSRParser.addArgument(genCSRSubjectAltOID); 2308 2309 final BooleanValueArgument genCSRBasicConstraintsIsCA = 2310 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 2311 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_BC_IS_CA_DESC.get()); 2312 genCSRBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 2313 genCSRBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 2314 genCSRBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 2315 genCSRParser.addArgument(genCSRBasicConstraintsIsCA); 2316 2317 final IntegerArgument genCSRBasicConstraintsPathLength = 2318 new IntegerArgument(null, "basic-constraints-maximum-path-length", 2319 false, 1, null, 2320 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 2321 Integer.MAX_VALUE); 2322 genCSRBasicConstraintsPathLength.addLongIdentifier( 2323 "basicConstraintsMaximumPathLength", true); 2324 genCSRBasicConstraintsPathLength.addLongIdentifier( 2325 "basic-constraints-max-path-length", true); 2326 genCSRBasicConstraintsPathLength.addLongIdentifier( 2327 "basicConstraintsMaxPathLength", true); 2328 genCSRBasicConstraintsPathLength.addLongIdentifier( 2329 "basic-constraints-path-length", true); 2330 genCSRBasicConstraintsPathLength.addLongIdentifier( 2331 "basicConstraintsPathLength", true); 2332 genCSRBasicConstraintsPathLength.addLongIdentifier( 2333 "bc-maximum-path-length", true); 2334 genCSRBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 2335 true); 2336 genCSRBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 2337 true); 2338 genCSRBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 2339 true); 2340 genCSRBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 2341 genCSRBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 2342 genCSRParser.addArgument(genCSRBasicConstraintsPathLength); 2343 2344 final StringArgument genCSRKeyUsage = new StringArgument(null, "key-usage", 2345 false, 0, null, INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_KU_DESC.get()); 2346 genCSRKeyUsage.addLongIdentifier("keyUsage", true); 2347 genCSRParser.addArgument(genCSRKeyUsage); 2348 2349 final StringArgument genCSRExtendedKeyUsage = new StringArgument(null, 2350 "extended-key-usage", false, 0, null, 2351 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_EKU_DESC.get()); 2352 genCSRExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 2353 genCSRParser.addArgument(genCSRExtendedKeyUsage); 2354 2355 final StringArgument genCSRExtension = new StringArgument(null, 2356 "extension", false, 0, null, 2357 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_EXT_DESC.get()); 2358 genCSRExtension.addLongIdentifier("ext", true); 2359 genCSRParser.addArgument(genCSRExtension); 2360 2361 final BooleanArgument genCSRDisplayCommand = new BooleanArgument(null, 2362 "display-keytool-command", 1, 2363 INFO_MANAGE_CERTS_SC_GEN_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 2364 genCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 2365 genCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 2366 genCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 2367 genCSRParser.addArgument(genCSRDisplayCommand); 2368 2369 genCSRParser.addRequiredArgumentSet(genCSRKeystorePassword, 2370 genCSRKeystorePasswordFile, genCSRPromptForKeystorePassword); 2371 genCSRParser.addExclusiveArgumentSet(genCSRKeystorePassword, 2372 genCSRKeystorePasswordFile, genCSRPromptForKeystorePassword); 2373 genCSRParser.addExclusiveArgumentSet(genCSRPKPassword, 2374 genCSRPKPasswordFile, genCSRPromptForPKPassword); 2375 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2376 genCSRKeyAlgorithm); 2377 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2378 genCSRKeySizeBits); 2379 genCSRParser.addExclusiveArgumentSet(genCSRUseExistingKeyPair, 2380 genCSRSignatureAlgorithm); 2381 genCSRParser.addDependentArgumentSet(genCSRBasicConstraintsPathLength, 2382 genCSRBasicConstraintsIsCA); 2383 2384 final LinkedHashMap<String[],String> genCSRExamples = 2385 new LinkedHashMap<>(StaticUtils.computeMapCapacity(3)); 2386 genCSRExamples.put( 2387 new String[] 2388 { 2389 "generate-certificate-signing-request", 2390 "--keystore", getPlatformSpecificPath("config", "keystore"), 2391 "--keystore-password-file", 2392 getPlatformSpecificPath("config", "keystore.pin"), 2393 "--alias", "server-cert", 2394 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US" 2395 }, 2396 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_1.get()); 2397 genCSRExamples.put( 2398 new String[] 2399 { 2400 "generate-certificate-signing-request", 2401 "--keystore", getPlatformSpecificPath("config", "keystore"), 2402 "--keystore-password-file", 2403 getPlatformSpecificPath("config", "keystore.pin"), 2404 "--alias", "server-cert", 2405 "--use-existing-key-pair", 2406 "--inherit-extensions", 2407 "--output-file", "server-cert.csr" 2408 }, 2409 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_2.get()); 2410 genCSRExamples.put( 2411 new String[] 2412 { 2413 "generate-certificate-signing-request", 2414 "--keystore", getPlatformSpecificPath("config", "keystore"), 2415 "--keystore-password-file", 2416 getPlatformSpecificPath("config", "keystore.pin"), 2417 "--alias", "server-cert", 2418 "--subject-dn", "CN=ldap.example.com,O=Example Corp,C=US", 2419 "--key-algorithm", "EC", 2420 "--key-size-bits", "256", 2421 "--signature-algorithm", "SHA256withECDSA", 2422 "--subject-alternative-name-dns", "ldap1.example.com", 2423 "--subject-alternative-name-dns", "ldap2.example.com", 2424 "--subject-alternative-name-ip-address", "1.2.3.4", 2425 "--subject-alternative-name-ip-address", "1.2.3.5", 2426 "--extended-key-usage", "server-auth", 2427 "--extended-key-usage", "client-auth", 2428 "--output-file", "server-cert.csr", 2429 "--display-keytool-command" 2430 }, 2431 INFO_MANAGE_CERTS_SC_GEN_CSR_EXAMPLE_3.get()); 2432 2433 final SubCommand genCSRSubCommand = new SubCommand( 2434 "generate-certificate-signing-request", 2435 INFO_MANAGE_CERTS_SC_GEN_CSR_DESC.get(), genCSRParser, 2436 genCSRExamples); 2437 genCSRSubCommand.addName("generateCertificateSigningRequest", true); 2438 genCSRSubCommand.addName("generate-certificate-request", true); 2439 genCSRSubCommand.addName("generateCertificateRequest", true); 2440 genCSRSubCommand.addName("generate-csr", true); 2441 genCSRSubCommand.addName("generateCSR", true); 2442 genCSRSubCommand.addName("certificate-signing-request", true); 2443 genCSRSubCommand.addName("certificateSigningRequest", true); 2444 genCSRSubCommand.addName("csr", true); 2445 genCSRSubCommand.addName("certreq", true); 2446 2447 parser.addSubCommand(genCSRSubCommand); 2448 2449 2450 // Define the "sign-certificate-signing-request" subcommand and all of its 2451 // arguments. 2452 final ArgumentParser signCSRParser = new ArgumentParser( 2453 "sign-certificate-signing-request", 2454 INFO_MANAGE_CERTS_SC_SIGN_CSR_DESC.get()); 2455 2456 final FileArgument signCSRInputFile = new FileArgument(null, 2457 "request-input-file", true, 1, null, 2458 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_INPUT_FILE_DESC.get(), true, true, 2459 true, false); 2460 signCSRInputFile.addLongIdentifier("requestInputFile", true); 2461 signCSRInputFile.addLongIdentifier("certificate-signing-request", true); 2462 signCSRInputFile.addLongIdentifier("certificateSigningRequest", true); 2463 signCSRInputFile.addLongIdentifier("input-file", false); 2464 signCSRInputFile.addLongIdentifier("inputFile", true); 2465 signCSRInputFile.addLongIdentifier("csr", true); 2466 signCSRParser.addArgument(signCSRInputFile); 2467 2468 final FileArgument signCSROutputFile = new FileArgument(null, 2469 "certificate-output-file", false, 1, null, 2470 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_OUTPUT_FILE_DESC.get(), false, true, 2471 true, false); 2472 signCSROutputFile.addLongIdentifier("certificateOutputFile", true); 2473 signCSROutputFile.addLongIdentifier("output-file", false); 2474 signCSROutputFile.addLongIdentifier("outputFile", true); 2475 signCSROutputFile.addLongIdentifier("certificate-file", true); 2476 signCSROutputFile.addLongIdentifier("certificateFile", true); 2477 signCSRParser.addArgument(signCSROutputFile); 2478 2479 final Set<String> signCSROutputFormatAllowedValues = StaticUtils.setOf( 2480 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 2481 final StringArgument signCSROutputFormat = new StringArgument(null, 2482 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 2483 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_FORMAT_DESC.get(), 2484 signCSROutputFormatAllowedValues, "PEM"); 2485 signCSROutputFormat.addLongIdentifier("outputFormat", true); 2486 signCSRParser.addArgument(signCSROutputFormat); 2487 2488 final FileArgument signCSRKeystore = new FileArgument(null, "keystore", 2489 true, 1, null, INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_DESC.get(), true, 2490 true, true, false); 2491 signCSRKeystore.addLongIdentifier("keystore-path", true); 2492 signCSRKeystore.addLongIdentifier("keystorePath", true); 2493 signCSRKeystore.addLongIdentifier("keystore-file", true); 2494 signCSRKeystore.addLongIdentifier("keystoreFile", true); 2495 signCSRParser.addArgument(signCSRKeystore); 2496 2497 final StringArgument signCSRKeystorePassword = new StringArgument(null, 2498 "keystore-password", false, 1, 2499 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2500 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_PW_DESC.get()); 2501 signCSRKeystorePassword.addLongIdentifier("keystorePassword", true); 2502 signCSRKeystorePassword.addLongIdentifier("keystore-passphrase", true); 2503 signCSRKeystorePassword.addLongIdentifier("keystorePassphrase", true); 2504 signCSRKeystorePassword.addLongIdentifier("keystore-pin", true); 2505 signCSRKeystorePassword.addLongIdentifier("keystorePIN", true); 2506 signCSRKeystorePassword.addLongIdentifier("storepass", true); 2507 signCSRKeystorePassword.setSensitive(true); 2508 signCSRParser.addArgument(signCSRKeystorePassword); 2509 2510 final FileArgument signCSRKeystorePasswordFile = new FileArgument(null, 2511 "keystore-password-file", false, 1, null, 2512 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_PW_FILE_DESC.get(), true, true, 2513 true, false); 2514 signCSRKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 2515 true); 2516 signCSRKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 2517 true); 2518 signCSRKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 2519 true); 2520 signCSRKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 2521 true); 2522 signCSRKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 2523 signCSRParser.addArgument(signCSRKeystorePasswordFile); 2524 2525 final BooleanArgument signCSRPromptForKeystorePassword = 2526 new BooleanArgument(null, "prompt-for-keystore-password", 2527 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PROMPT_FOR_KS_PW_DESC.get()); 2528 signCSRPromptForKeystorePassword.addLongIdentifier( 2529 "promptForKeystorePassword", true); 2530 signCSRPromptForKeystorePassword.addLongIdentifier( 2531 "prompt-for-keystore-passphrase", true); 2532 signCSRPromptForKeystorePassword.addLongIdentifier( 2533 "promptForKeystorePassphrase", true); 2534 signCSRPromptForKeystorePassword.addLongIdentifier( 2535 "prompt-for-keystore-pin", true); 2536 signCSRPromptForKeystorePassword.addLongIdentifier( 2537 "promptForKeystorePIN", true); 2538 signCSRParser.addArgument(signCSRPromptForKeystorePassword); 2539 2540 final StringArgument signCSRPKPassword = new StringArgument(null, 2541 "private-key-password", false, 1, 2542 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 2543 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PK_PW_DESC.get()); 2544 signCSRPKPassword.addLongIdentifier("privateKeyPassword", true); 2545 signCSRPKPassword.addLongIdentifier("private-key-passphrase", true); 2546 signCSRPKPassword.addLongIdentifier("privateKeyPassphrase", true); 2547 signCSRPKPassword.addLongIdentifier("private-key-pin", true); 2548 signCSRPKPassword.addLongIdentifier("privateKeyPIN", true); 2549 signCSRPKPassword.addLongIdentifier("key-password", true); 2550 signCSRPKPassword.addLongIdentifier("keyPassword", true); 2551 signCSRPKPassword.addLongIdentifier("key-passphrase", true); 2552 signCSRPKPassword.addLongIdentifier("keyPassphrase", true); 2553 signCSRPKPassword.addLongIdentifier("key-pin", true); 2554 signCSRPKPassword.addLongIdentifier("keyPIN", true); 2555 signCSRPKPassword.addLongIdentifier("keypass", true); 2556 signCSRPKPassword.setSensitive(true); 2557 signCSRParser.addArgument(signCSRPKPassword); 2558 2559 final FileArgument signCSRPKPasswordFile = new FileArgument(null, 2560 "private-key-password-file", false, 1, null, 2561 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PK_PW_FILE_DESC.get(), true, true, 2562 true, false); 2563 signCSRPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 2564 signCSRPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 2565 true); 2566 signCSRPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 2567 true); 2568 signCSRPKPasswordFile.addLongIdentifier("private-key-pin-file", 2569 true); 2570 signCSRPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 2571 signCSRPKPasswordFile.addLongIdentifier("key-password-file", true); 2572 signCSRPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 2573 signCSRPKPasswordFile.addLongIdentifier("key-passphrase-file", 2574 true); 2575 signCSRPKPasswordFile.addLongIdentifier("keyPassphraseFile", 2576 true); 2577 signCSRPKPasswordFile.addLongIdentifier("key-pin-file", 2578 true); 2579 signCSRPKPasswordFile.addLongIdentifier("keyPINFile", true); 2580 signCSRParser.addArgument(signCSRPKPasswordFile); 2581 2582 final BooleanArgument signCSRPromptForPKPassword = 2583 new BooleanArgument(null, "prompt-for-private-key-password", 2584 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_PROMPT_FOR_PK_PW_DESC.get()); 2585 signCSRPromptForPKPassword.addLongIdentifier( 2586 "promptForPrivateKeyPassword", true); 2587 signCSRPromptForPKPassword.addLongIdentifier( 2588 "prompt-for-private-key-passphrase", true); 2589 signCSRPromptForPKPassword.addLongIdentifier( 2590 "promptForPrivateKeyPassphrase", true); 2591 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-private-key-pin", 2592 true); 2593 signCSRPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 2594 true); 2595 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 2596 true); 2597 signCSRPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 2598 true); 2599 signCSRPromptForPKPassword.addLongIdentifier( 2600 "prompt-for-key-passphrase", true); 2601 signCSRPromptForPKPassword.addLongIdentifier( 2602 "promptForKeyPassphrase", true); 2603 signCSRPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", true); 2604 signCSRPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 2605 signCSRParser.addArgument(signCSRPromptForPKPassword); 2606 2607 final StringArgument signCSRKeystoreType = new StringArgument(null, 2608 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 2609 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KS_TYPE_DESC.get(), 2610 ALLOWED_KEYSTORE_TYPE_VALUES); 2611 signCSRKeystoreType.addLongIdentifier("key-store-type", true); 2612 signCSRKeystoreType.addLongIdentifier("keystoreType", true); 2613 signCSRKeystoreType.addLongIdentifier("keystore-format", true); 2614 signCSRKeystoreType.addLongIdentifier("key-store-format", true); 2615 signCSRKeystoreType.addLongIdentifier("keystoreFormat", true); 2616 signCSRKeystoreType.addLongIdentifier("storetype", true); 2617 signCSRParser.addArgument(signCSRKeystoreType); 2618 2619 final StringArgument signCSRAlias = new StringArgument(null, 2620 "signing-certificate-alias", 2621 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 2622 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_ALIAS_DESC.get()); 2623 signCSRAlias.addLongIdentifier("signingCertificateAlias", true); 2624 signCSRAlias.addLongIdentifier("signing-certificate-nickname", true); 2625 signCSRAlias.addLongIdentifier("signingCertificateNickname", true); 2626 signCSRAlias.addLongIdentifier("alias", true); 2627 signCSRAlias.addLongIdentifier("nickname", true); 2628 signCSRParser.addArgument(signCSRAlias); 2629 2630 final DNArgument signCSRSubjectDN = new DNArgument(null, "subject-dn", 2631 false, 1, null, 2632 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SUBJECT_DN_DESC.get()); 2633 signCSRSubjectDN.addLongIdentifier("subjectDN", true); 2634 signCSRSubjectDN.addLongIdentifier("subject", true); 2635 signCSRSubjectDN.addLongIdentifier("dname", true); 2636 signCSRParser.addArgument(signCSRSubjectDN); 2637 2638 final IntegerArgument signCSRDaysValid = new IntegerArgument(null, 2639 "days-valid", false, 1, null, 2640 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_DAYS_VALID_DESC.get(), 1, 2641 Integer.MAX_VALUE); 2642 signCSRDaysValid.addLongIdentifier("daysValid", true); 2643 signCSRDaysValid.addLongIdentifier("validity", true); 2644 signCSRParser.addArgument(signCSRDaysValid); 2645 2646 final TimestampArgument signCSRNotBefore = new TimestampArgument(null, 2647 "validity-start-time", false, 1, 2648 INFO_MANAGE_CERTS_PLACEHOLDER_TIMESTAMP.get(), 2649 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_VALIDITY_START_TIME_DESC.get( 2650 "20180102123456")); 2651 signCSRNotBefore.addLongIdentifier("validityStartTime", true); 2652 signCSRNotBefore.addLongIdentifier("not-before", true); 2653 signCSRNotBefore.addLongIdentifier("notBefore", true); 2654 signCSRParser.addArgument(signCSRNotBefore); 2655 2656 final StringArgument signCSRSignatureAlgorithm = new StringArgument(null, 2657 "signature-algorithm", false, 1, 2658 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2659 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SIG_ALG_DESC.get()); 2660 signCSRSignatureAlgorithm.addLongIdentifier("signatureAlgorithm", true); 2661 signCSRSignatureAlgorithm.addLongIdentifier("signature-alg", true); 2662 signCSRSignatureAlgorithm.addLongIdentifier("signatureAlg", true); 2663 signCSRSignatureAlgorithm.addLongIdentifier("sig-alg", true); 2664 signCSRSignatureAlgorithm.addLongIdentifier("sigAlg", true); 2665 signCSRParser.addArgument(signCSRSignatureAlgorithm); 2666 2667 final BooleanArgument signCSRIncludeExtensions = new BooleanArgument(null, 2668 "include-requested-extensions", 1, 2669 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_INCLUDE_EXT_DESC.get()); 2670 signCSRIncludeExtensions.addLongIdentifier("includeRequestedExtensions", 2671 true); 2672 signCSRParser.addArgument(signCSRIncludeExtensions); 2673 2674 final StringArgument signCSRSubjectAltDNS = new StringArgument(null, 2675 "subject-alternative-name-dns", false, 0, 2676 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2677 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_DNS_DESC.get()); 2678 signCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeNameDNS", true); 2679 signCSRSubjectAltDNS.addLongIdentifier("subject-alt-name-dns", true); 2680 signCSRSubjectAltDNS.addLongIdentifier("subjectAltNameDNS", true); 2681 signCSRSubjectAltDNS.addLongIdentifier("subject-alternative-dns", true); 2682 signCSRSubjectAltDNS.addLongIdentifier("subjectAlternativeDNS", true); 2683 signCSRSubjectAltDNS.addLongIdentifier("subject-alt-dns", true); 2684 signCSRSubjectAltDNS.addLongIdentifier("subjectAltDNS", true); 2685 signCSRSubjectAltDNS.addLongIdentifier("san-dns", true); 2686 signCSRSubjectAltDNS.addLongIdentifier("sanDNS", true); 2687 signCSRSubjectAltDNS.addValueValidator( 2688 new IA5StringArgumentValueValidator(false)); 2689 signCSRParser.addArgument(signCSRSubjectAltDNS); 2690 2691 final StringArgument signCSRSubjectAltIP = new StringArgument(null, 2692 "subject-alternative-name-ip-address", false, 0, 2693 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2694 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_IP_DESC.get()); 2695 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIPAddress", 2696 true); 2697 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-name-ip", true); 2698 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeNameIP", true); 2699 signCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip-address", true); 2700 signCSRSubjectAltIP.addLongIdentifier("subjectAltNameIPAddress", true); 2701 signCSRSubjectAltIP.addLongIdentifier("subject-alt-name-ip", true); 2702 signCSRSubjectAltIP.addLongIdentifier("subjectAltNameIP", true); 2703 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip-address", 2704 true); 2705 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIPAddress", true); 2706 signCSRSubjectAltIP.addLongIdentifier("subject-alternative-ip", true); 2707 signCSRSubjectAltIP.addLongIdentifier("subjectAlternativeIP", true); 2708 signCSRSubjectAltIP.addLongIdentifier("subject-alt-ip-address", true); 2709 signCSRSubjectAltIP.addLongIdentifier("subjectAltIPAddress", true); 2710 signCSRSubjectAltIP.addLongIdentifier("subject-alt-ip", true); 2711 signCSRSubjectAltIP.addLongIdentifier("subjectAltIP", true); 2712 signCSRSubjectAltIP.addLongIdentifier("san-ip-address", true); 2713 signCSRSubjectAltIP.addLongIdentifier("sanIPAddress", true); 2714 signCSRSubjectAltIP.addLongIdentifier("san-ip", true); 2715 signCSRSubjectAltIP.addLongIdentifier("sanIP", true); 2716 signCSRSubjectAltIP.addValueValidator( 2717 new IPAddressArgumentValueValidator(true, true)); 2718 signCSRParser.addArgument(signCSRSubjectAltIP); 2719 2720 final StringArgument signCSRSubjectAltEmail = new StringArgument(null, 2721 "subject-alternative-name-email-address", false, 0, 2722 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2723 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_EMAIL_DESC.get()); 2724 signCSRSubjectAltEmail.addLongIdentifier( 2725 "subjectAlternativeNameEmailAddress", true); 2726 signCSRSubjectAltEmail.addLongIdentifier("subject-alternative-name-email", 2727 true); 2728 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeNameEmail", 2729 true); 2730 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email-address", 2731 true); 2732 signCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmailAddress", 2733 true); 2734 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-name-email", true); 2735 signCSRSubjectAltEmail.addLongIdentifier("subjectAltNameEmail", true); 2736 signCSRSubjectAltEmail.addLongIdentifier( 2737 "subject-alternative-email-address", true); 2738 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmailAddress", 2739 true); 2740 signCSRSubjectAltEmail.addLongIdentifier("subject-alternative-email", true); 2741 signCSRSubjectAltEmail.addLongIdentifier("subjectAlternativeEmail", true); 2742 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-email-address", true); 2743 signCSRSubjectAltEmail.addLongIdentifier("subjectAltEmailAddress", true); 2744 signCSRSubjectAltEmail.addLongIdentifier("subject-alt-email", true); 2745 signCSRSubjectAltEmail.addLongIdentifier("subjectAltEmail", true); 2746 signCSRSubjectAltEmail.addLongIdentifier("san-email-address", true); 2747 signCSRSubjectAltEmail.addLongIdentifier("sanEmailAddress", true); 2748 signCSRSubjectAltEmail.addLongIdentifier("san-email", true); 2749 signCSRSubjectAltEmail.addLongIdentifier("sanEmail", true); 2750 signCSRSubjectAltEmail.addValueValidator( 2751 new IA5StringArgumentValueValidator(false)); 2752 signCSRParser.addArgument(signCSRSubjectAltEmail); 2753 2754 final StringArgument signCSRSubjectAltURI = new StringArgument(null, 2755 "subject-alternative-name-uri", false, 0, 2756 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2757 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_URI_DESC.get()); 2758 signCSRSubjectAltURI.addLongIdentifier("subjectAlternativeNameURI", true); 2759 signCSRSubjectAltURI.addLongIdentifier("subject-alt-name-uri", true); 2760 signCSRSubjectAltURI.addLongIdentifier("subjectAltNameURI", true); 2761 signCSRSubjectAltURI.addLongIdentifier("subject-alternative-uri", true); 2762 signCSRSubjectAltURI.addLongIdentifier("subjectAlternativeURI", true); 2763 signCSRSubjectAltURI.addLongIdentifier("subject-alt-uri", true); 2764 signCSRSubjectAltURI.addLongIdentifier("subjectAltURI", true); 2765 signCSRSubjectAltURI.addLongIdentifier("san-uri", true); 2766 signCSRSubjectAltURI.addLongIdentifier("sanURI", true); 2767 signCSRParser.addArgument(signCSRSubjectAltURI); 2768 2769 final StringArgument signCSRSubjectAltOID = new StringArgument(null, 2770 "subject-alternative-name-oid", false, 0, 2771 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2772 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_SAN_OID_DESC.get()); 2773 signCSRSubjectAltOID.addLongIdentifier("subjectAlternativeNameOID", true); 2774 signCSRSubjectAltOID.addLongIdentifier("subject-alt-name-oid", true); 2775 signCSRSubjectAltOID.addLongIdentifier("subjectAltNameOID", true); 2776 signCSRSubjectAltOID.addLongIdentifier("subject-alternative-oid", true); 2777 signCSRSubjectAltOID.addLongIdentifier("subjectAlternativeOID", true); 2778 signCSRSubjectAltOID.addLongIdentifier("subject-alt-oid", true); 2779 signCSRSubjectAltOID.addLongIdentifier("subjectAltOID", true); 2780 signCSRSubjectAltOID.addLongIdentifier("san-oid", true); 2781 signCSRSubjectAltOID.addLongIdentifier("sanOID", true); 2782 signCSRSubjectAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2783 signCSRParser.addArgument(signCSRSubjectAltOID); 2784 2785 final StringArgument signCSRIssuerAltDNS = new StringArgument(null, 2786 "issuer-alternative-name-dns", false, 0, 2787 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2788 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_DNS_DESC.get()); 2789 signCSRIssuerAltDNS.addLongIdentifier("issuerAlternativeNameDNS", true); 2790 signCSRIssuerAltDNS.addLongIdentifier("issuer-alt-name-dns", true); 2791 signCSRIssuerAltDNS.addLongIdentifier("issuerAltNameDNS", true); 2792 signCSRIssuerAltDNS.addLongIdentifier("issuer-alternative-dns", true); 2793 signCSRIssuerAltDNS.addLongIdentifier("issuerAlternativeDNS", true); 2794 signCSRIssuerAltDNS.addLongIdentifier("issuer-alt-dns", true); 2795 signCSRIssuerAltDNS.addLongIdentifier("issuerAltDNS", true); 2796 signCSRIssuerAltDNS.addLongIdentifier("ian-dns", true); 2797 signCSRIssuerAltDNS.addLongIdentifier("ianDNS", true); 2798 signCSRIssuerAltDNS.addValueValidator( 2799 new IA5StringArgumentValueValidator(false)); 2800 signCSRParser.addArgument(signCSRIssuerAltDNS); 2801 2802 final StringArgument signCSRIssuerAltIP = new StringArgument(null, 2803 "issuer-alternative-name-ip-address", false, 0, 2804 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2805 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_IP_DESC.get()); 2806 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeNameIPAddress", 2807 true); 2808 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-name-ip", true); 2809 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeNameIP", true); 2810 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-name-ip-address", true); 2811 signCSRIssuerAltIP.addLongIdentifier("issuerAltNameIPAddress", true); 2812 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-name-ip", true); 2813 signCSRIssuerAltIP.addLongIdentifier("issuerAltNameIP", true); 2814 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-ip-address", 2815 true); 2816 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeIPAddress", true); 2817 signCSRIssuerAltIP.addLongIdentifier("issuer-alternative-ip", true); 2818 signCSRIssuerAltIP.addLongIdentifier("issuerAlternativeIP", true); 2819 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-ip-address", true); 2820 signCSRIssuerAltIP.addLongIdentifier("issuerAltIPAddress", true); 2821 signCSRIssuerAltIP.addLongIdentifier("issuer-alt-ip", true); 2822 signCSRIssuerAltIP.addLongIdentifier("issuerAltIP", true); 2823 signCSRIssuerAltIP.addLongIdentifier("ian-ip-address", true); 2824 signCSRIssuerAltIP.addLongIdentifier("ianIPAddress", true); 2825 signCSRIssuerAltIP.addLongIdentifier("ian-ip", true); 2826 signCSRIssuerAltIP.addLongIdentifier("ianIP", true); 2827 signCSRIssuerAltIP.addValueValidator( 2828 new IPAddressArgumentValueValidator(true, true)); 2829 signCSRParser.addArgument(signCSRIssuerAltIP); 2830 2831 final StringArgument signCSRIssuerAltEmail = new StringArgument(null, 2832 "issuer-alternative-name-email-address", false, 0, 2833 INFO_MANAGE_CERTS_PLACEHOLDER_NAME.get(), 2834 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_EMAIL_DESC.get()); 2835 signCSRIssuerAltEmail.addLongIdentifier( 2836 "issuerAlternativeNameEmailAddress", true); 2837 signCSRIssuerAltEmail.addLongIdentifier("issuer-alternative-name-email", 2838 true); 2839 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeNameEmail", 2840 true); 2841 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-name-email-address", 2842 true); 2843 signCSRIssuerAltEmail.addLongIdentifier("issuerAltNameEmailAddress", 2844 true); 2845 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-name-email", true); 2846 signCSRIssuerAltEmail.addLongIdentifier("issuerAltNameEmail", true); 2847 signCSRIssuerAltEmail.addLongIdentifier( 2848 "issuer-alternative-email-address", true); 2849 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeEmailAddress", 2850 true); 2851 signCSRIssuerAltEmail.addLongIdentifier("issuer-alternative-email", true); 2852 signCSRIssuerAltEmail.addLongIdentifier("issuerAlternativeEmail", true); 2853 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-email-address", true); 2854 signCSRIssuerAltEmail.addLongIdentifier("issuerAltEmailAddress", true); 2855 signCSRIssuerAltEmail.addLongIdentifier("issuer-alt-email", true); 2856 signCSRIssuerAltEmail.addLongIdentifier("issuerAltEmail", true); 2857 signCSRIssuerAltEmail.addLongIdentifier("ian-email-address", true); 2858 signCSRIssuerAltEmail.addLongIdentifier("ianEmailAddress", true); 2859 signCSRIssuerAltEmail.addLongIdentifier("ian-email", true); 2860 signCSRIssuerAltEmail.addLongIdentifier("ianEmail", true); 2861 signCSRIssuerAltEmail.addValueValidator( 2862 new IA5StringArgumentValueValidator(false)); 2863 signCSRParser.addArgument(signCSRIssuerAltEmail); 2864 2865 final StringArgument signCSRIssuerAltURI = new StringArgument(null, 2866 "issuer-alternative-name-uri", false, 0, 2867 INFO_MANAGE_CERTS_PLACEHOLDER_URI.get(), 2868 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_URI_DESC.get()); 2869 signCSRIssuerAltURI.addLongIdentifier("issuerAlternativeNameURI", true); 2870 signCSRIssuerAltURI.addLongIdentifier("issuer-alt-name-uri", true); 2871 signCSRIssuerAltURI.addLongIdentifier("issuerAltNameURI", true); 2872 signCSRIssuerAltURI.addLongIdentifier("issuer-alternative-uri", true); 2873 signCSRIssuerAltURI.addLongIdentifier("issuerAlternativeURI", true); 2874 signCSRIssuerAltURI.addLongIdentifier("issuer-alt-uri", true); 2875 signCSRIssuerAltURI.addLongIdentifier("issuerAltURI", true); 2876 signCSRIssuerAltURI.addLongIdentifier("ian-uri", true); 2877 signCSRIssuerAltURI.addLongIdentifier("ianURI", true); 2878 signCSRParser.addArgument(signCSRIssuerAltURI); 2879 2880 final StringArgument signCSRIssuerAltOID = new StringArgument(null, 2881 "issuer-alternative-name-oid", false, 0, 2882 INFO_MANAGE_CERTS_PLACEHOLDER_OID.get(), 2883 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_IAN_OID_DESC.get()); 2884 signCSRIssuerAltOID.addLongIdentifier("issuerAlternativeNameOID", true); 2885 signCSRIssuerAltOID.addLongIdentifier("issuer-alt-name-oid", true); 2886 signCSRIssuerAltOID.addLongIdentifier("issuerAltNameOID", true); 2887 signCSRIssuerAltOID.addLongIdentifier("issuer-alternative-oid", true); 2888 signCSRIssuerAltOID.addLongIdentifier("issuerAlternativeOID", true); 2889 signCSRIssuerAltOID.addLongIdentifier("issuer-alt-oid", true); 2890 signCSRIssuerAltOID.addLongIdentifier("issuerAltOID", true); 2891 signCSRIssuerAltOID.addLongIdentifier("ian-oid", true); 2892 signCSRIssuerAltOID.addLongIdentifier("ianOID", true); 2893 signCSRIssuerAltOID.addValueValidator(new OIDArgumentValueValidator(true)); 2894 signCSRParser.addArgument(signCSRIssuerAltOID); 2895 2896 final BooleanValueArgument signCSRBasicConstraintsIsCA = 2897 new BooleanValueArgument(null, "basic-constraints-is-ca", false, null, 2898 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_BC_IS_CA_DESC.get()); 2899 signCSRBasicConstraintsIsCA.addLongIdentifier("basicConstraintsIsCA", true); 2900 signCSRBasicConstraintsIsCA.addLongIdentifier("bc-is-ca", true); 2901 signCSRBasicConstraintsIsCA.addLongIdentifier("bcIsCA", true); 2902 signCSRParser.addArgument(signCSRBasicConstraintsIsCA); 2903 2904 final IntegerArgument signCSRBasicConstraintsPathLength = 2905 new IntegerArgument(null, "basic-constraints-maximum-path-length", 2906 false, 1, null, 2907 INFO_MANAGE_CERTS_SC_GEN_CERT_ARG_BC_PATH_LENGTH_DESC.get(), 0, 2908 Integer.MAX_VALUE); 2909 signCSRBasicConstraintsPathLength.addLongIdentifier( 2910 "basicConstraintsMaximumPathLength", true); 2911 signCSRBasicConstraintsPathLength.addLongIdentifier( 2912 "basic-constraints-max-path-length", true); 2913 signCSRBasicConstraintsPathLength.addLongIdentifier( 2914 "basicConstraintsMaxPathLength", true); 2915 signCSRBasicConstraintsPathLength.addLongIdentifier( 2916 "basic-constraints-path-length", true); 2917 signCSRBasicConstraintsPathLength.addLongIdentifier( 2918 "basicConstraintsPathLength", true); 2919 signCSRBasicConstraintsPathLength.addLongIdentifier( 2920 "bc-maximum-path-length", true); 2921 signCSRBasicConstraintsPathLength.addLongIdentifier("bcMaximumPathLength", 2922 true); 2923 signCSRBasicConstraintsPathLength.addLongIdentifier("bc-max-path-length", 2924 true); 2925 signCSRBasicConstraintsPathLength.addLongIdentifier("bcMaxPathLength", 2926 true); 2927 signCSRBasicConstraintsPathLength.addLongIdentifier("bc-path-length", true); 2928 signCSRBasicConstraintsPathLength.addLongIdentifier("bcPathLength", true); 2929 signCSRParser.addArgument(signCSRBasicConstraintsPathLength); 2930 2931 final StringArgument signCSRKeyUsage = new StringArgument(null, "key-usage", 2932 false, 0, null, INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_KU_DESC.get()); 2933 signCSRKeyUsage.addLongIdentifier("keyUsage", true); 2934 signCSRParser.addArgument(signCSRKeyUsage); 2935 2936 final StringArgument signCSRExtendedKeyUsage = new StringArgument(null, 2937 "extended-key-usage", false, 0, null, 2938 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_EKU_DESC.get()); 2939 signCSRExtendedKeyUsage.addLongIdentifier("extendedKeyUsage", true); 2940 signCSRParser.addArgument(signCSRExtendedKeyUsage); 2941 2942 final StringArgument signCSRExtension = new StringArgument(null, 2943 "extension", false, 0, null, 2944 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_EXT_DESC.get()); 2945 signCSRExtension.addLongIdentifier("ext", true); 2946 signCSRParser.addArgument(signCSRExtension); 2947 2948 final BooleanArgument signCSRNoPrompt = new BooleanArgument(null, 2949 "no-prompt", 1, 2950 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_NO_PROMPT_DESC.get()); 2951 signCSRNoPrompt.addLongIdentifier("noPrompt", true); 2952 signCSRParser.addArgument(signCSRNoPrompt); 2953 2954 final BooleanArgument signCSRDisplayCommand = new BooleanArgument(null, 2955 "display-keytool-command", 1, 2956 INFO_MANAGE_CERTS_SC_SIGN_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 2957 signCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 2958 signCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 2959 signCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 2960 signCSRParser.addArgument(signCSRDisplayCommand); 2961 2962 signCSRParser.addRequiredArgumentSet(signCSRKeystorePassword, 2963 signCSRKeystorePasswordFile, signCSRPromptForKeystorePassword); 2964 signCSRParser.addExclusiveArgumentSet(signCSRKeystorePassword, 2965 signCSRKeystorePasswordFile, signCSRPromptForKeystorePassword); 2966 signCSRParser.addExclusiveArgumentSet(signCSRPKPassword, 2967 signCSRPKPasswordFile, signCSRPromptForPKPassword); 2968 signCSRParser.addDependentArgumentSet(signCSRBasicConstraintsPathLength, 2969 signCSRBasicConstraintsIsCA); 2970 2971 final LinkedHashMap<String[],String> signCSRExamples = 2972 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 2973 signCSRExamples.put( 2974 new String[] 2975 { 2976 "sign-certificate-signing-request", 2977 "--request-input-file", "server-cert.csr", 2978 "--keystore", getPlatformSpecificPath("config", "keystore"), 2979 "--keystore-password-file", 2980 getPlatformSpecificPath("config", "keystore.pin"), 2981 "--signing-certificate-alias", "ca-cert", 2982 "--include-requested-extensions" 2983 }, 2984 INFO_MANAGE_CERTS_SC_SIGN_CSR_EXAMPLE_1.get( 2985 getPlatformSpecificPath("config", "keystore"))); 2986 signCSRExamples.put( 2987 new String[] 2988 { 2989 "sign-certificate-signing-request", 2990 "--request-input-file", "server-cert.csr", 2991 "--certificate-output-file", "server-cert.der", 2992 "--output-format", "DER", 2993 "--keystore", getPlatformSpecificPath("config", "keystore"), 2994 "--keystore-password-file", 2995 getPlatformSpecificPath("config", "keystore.pin"), 2996 "--signing-certificate-alias", "ca-cert", 2997 "--days-valid", "730", 2998 "--validity-start-time", "20170101000000", 2999 "--include-requested-extensions", 3000 "--issuer-alternative-name-email-address", "ca@example.com", 3001 }, 3002 INFO_MANAGE_CERTS_SC_SIGN_CSR_EXAMPLE_2.get( 3003 getPlatformSpecificPath("config", "keystore"))); 3004 3005 final SubCommand signCSRSubCommand = new SubCommand( 3006 "sign-certificate-signing-request", 3007 INFO_MANAGE_CERTS_SC_SIGN_CSR_DESC.get(), signCSRParser, 3008 signCSRExamples); 3009 signCSRSubCommand.addName("signCertificateSigningRequest", true); 3010 signCSRSubCommand.addName("sign-certificate-request", true); 3011 signCSRSubCommand.addName("signCertificateRequest", true); 3012 signCSRSubCommand.addName("sign-certificate", true); 3013 signCSRSubCommand.addName("signCertificate", true); 3014 signCSRSubCommand.addName("sign-csr", true); 3015 signCSRSubCommand.addName("signCSR", true); 3016 signCSRSubCommand.addName("sign", true); 3017 signCSRSubCommand.addName("gencert", true); 3018 3019 parser.addSubCommand(signCSRSubCommand); 3020 3021 3022 // Define the "change-certificate-alias" subcommand and all of its 3023 // arguments. 3024 final ArgumentParser changeAliasParser = new ArgumentParser( 3025 "change-certificate-alias", 3026 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_DESC.get()); 3027 3028 final FileArgument changeAliasKeystore = new FileArgument(null, "keystore", 3029 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_DESC.get(), 3030 true, true, true, false); 3031 changeAliasKeystore.addLongIdentifier("keystore-path", true); 3032 changeAliasKeystore.addLongIdentifier("keystorePath", true); 3033 changeAliasKeystore.addLongIdentifier("keystore-file", true); 3034 changeAliasKeystore.addLongIdentifier("keystoreFile", true); 3035 changeAliasParser.addArgument(changeAliasKeystore); 3036 3037 final StringArgument changeAliasKeystorePassword = new StringArgument(null, 3038 "keystore-password", false, 1, 3039 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3040 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_PW_DESC.get()); 3041 changeAliasKeystorePassword.addLongIdentifier("keystorePassword", true); 3042 changeAliasKeystorePassword.addLongIdentifier("keystore-passphrase", true); 3043 changeAliasKeystorePassword.addLongIdentifier("keystorePassphrase", true); 3044 changeAliasKeystorePassword.addLongIdentifier("keystore-pin", true); 3045 changeAliasKeystorePassword.addLongIdentifier("keystorePIN", true); 3046 changeAliasKeystorePassword.addLongIdentifier("storepass", true); 3047 changeAliasKeystorePassword.setSensitive(true); 3048 changeAliasParser.addArgument(changeAliasKeystorePassword); 3049 3050 final FileArgument changeAliasKeystorePasswordFile = new FileArgument(null, 3051 "keystore-password-file", false, 1, null, 3052 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_PW_FILE_DESC.get(), true, 3053 true, true, false); 3054 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 3055 true); 3056 changeAliasKeystorePasswordFile.addLongIdentifier( 3057 "keystore-passphrase-file", true); 3058 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 3059 true); 3060 changeAliasKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 3061 true); 3062 changeAliasKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 3063 changeAliasParser.addArgument(changeAliasKeystorePasswordFile); 3064 3065 final BooleanArgument changeAliasPromptForKeystorePassword = 3066 new BooleanArgument(null, "prompt-for-keystore-password", 3067 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PROMPT_FOR_KS_PW_DESC.get()); 3068 changeAliasPromptForKeystorePassword.addLongIdentifier( 3069 "promptForKeystorePassword", true); 3070 changeAliasPromptForKeystorePassword.addLongIdentifier( 3071 "prompt-for-keystore-passphrase", true); 3072 changeAliasPromptForKeystorePassword.addLongIdentifier( 3073 "promptForKeystorePassphrase", true); 3074 changeAliasPromptForKeystorePassword.addLongIdentifier( 3075 "prompt-for-keystore-pin", true); 3076 changeAliasPromptForKeystorePassword.addLongIdentifier( 3077 "promptForKeystorePIN", true); 3078 changeAliasParser.addArgument(changeAliasPromptForKeystorePassword); 3079 3080 final StringArgument changeAliasPKPassword = new StringArgument(null, 3081 "private-key-password", false, 1, 3082 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3083 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PK_PW_DESC.get()); 3084 changeAliasPKPassword.addLongIdentifier("privateKeyPassword", true); 3085 changeAliasPKPassword.addLongIdentifier("private-key-passphrase", true); 3086 changeAliasPKPassword.addLongIdentifier("privateKeyPassphrase", true); 3087 changeAliasPKPassword.addLongIdentifier("private-key-pin", true); 3088 changeAliasPKPassword.addLongIdentifier("privateKeyPIN", true); 3089 changeAliasPKPassword.addLongIdentifier("key-password", true); 3090 changeAliasPKPassword.addLongIdentifier("keyPassword", true); 3091 changeAliasPKPassword.addLongIdentifier("key-passphrase", true); 3092 changeAliasPKPassword.addLongIdentifier("keyPassphrase", true); 3093 changeAliasPKPassword.addLongIdentifier("key-pin", true); 3094 changeAliasPKPassword.addLongIdentifier("keyPIN", true); 3095 changeAliasPKPassword.addLongIdentifier("keypass", true); 3096 changeAliasPKPassword.setSensitive(true); 3097 changeAliasParser.addArgument(changeAliasPKPassword); 3098 3099 final FileArgument changeAliasPKPasswordFile = new FileArgument(null, 3100 "private-key-password-file", false, 1, null, 3101 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PK_PW_FILE_DESC.get(), true, 3102 true, true, false); 3103 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPasswordFile", true); 3104 changeAliasPKPasswordFile.addLongIdentifier("private-key-passphrase-file", 3105 true); 3106 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPassphraseFile", 3107 true); 3108 changeAliasPKPasswordFile.addLongIdentifier("private-key-pin-file", 3109 true); 3110 changeAliasPKPasswordFile.addLongIdentifier("privateKeyPINFile", true); 3111 changeAliasPKPasswordFile.addLongIdentifier("key-password-file", true); 3112 changeAliasPKPasswordFile.addLongIdentifier("keyPasswordFile", true); 3113 changeAliasPKPasswordFile.addLongIdentifier("key-passphrase-file", 3114 true); 3115 changeAliasPKPasswordFile.addLongIdentifier("keyPassphraseFile", 3116 true); 3117 changeAliasPKPasswordFile.addLongIdentifier("key-pin-file", 3118 true); 3119 changeAliasPKPasswordFile.addLongIdentifier("keyPINFile", true); 3120 changeAliasParser.addArgument(changeAliasPKPasswordFile); 3121 3122 final BooleanArgument changeAliasPromptForPKPassword = 3123 new BooleanArgument(null, "prompt-for-private-key-password", 3124 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_PROMPT_FOR_PK_PW_DESC.get()); 3125 changeAliasPromptForPKPassword.addLongIdentifier( 3126 "promptForPrivateKeyPassword", true); 3127 changeAliasPromptForPKPassword.addLongIdentifier( 3128 "prompt-for-private-key-passphrase", true); 3129 changeAliasPromptForPKPassword.addLongIdentifier( 3130 "promptForPrivateKeyPassphrase", true); 3131 changeAliasPromptForPKPassword.addLongIdentifier( 3132 "prompt-for-private-key-pin", true); 3133 changeAliasPromptForPKPassword.addLongIdentifier("promptForPrivateKeyPIN", 3134 true); 3135 changeAliasPromptForPKPassword.addLongIdentifier("prompt-for-key-password", 3136 true); 3137 changeAliasPromptForPKPassword.addLongIdentifier("promptForKeyPassword", 3138 true); 3139 changeAliasPromptForPKPassword.addLongIdentifier( 3140 "prompt-for-key-passphrase", true); 3141 changeAliasPromptForPKPassword.addLongIdentifier( 3142 "promptForKeyPassphrase", true); 3143 changeAliasPromptForPKPassword.addLongIdentifier("prompt-for-key-pin", 3144 true); 3145 changeAliasPromptForPKPassword.addLongIdentifier("promptForKeyPIN", true); 3146 changeAliasParser.addArgument(changeAliasPromptForPKPassword); 3147 3148 final StringArgument changeAliasKeystoreType = new StringArgument(null, 3149 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3150 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_KS_TYPE_DESC.get(), 3151 ALLOWED_KEYSTORE_TYPE_VALUES); 3152 changeAliasKeystoreType.addLongIdentifier("key-store-type", true); 3153 changeAliasKeystoreType.addLongIdentifier("keystoreType", true); 3154 changeAliasKeystoreType.addLongIdentifier("keystore-format", true); 3155 changeAliasKeystoreType.addLongIdentifier("key-store-format", true); 3156 changeAliasKeystoreType.addLongIdentifier("keystoreFormat", true); 3157 changeAliasKeystoreType.addLongIdentifier("storetype", true); 3158 changeAliasParser.addArgument(changeAliasKeystoreType); 3159 3160 final StringArgument changeAliasCurrentAlias = new StringArgument(null, 3161 "current-alias", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3162 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_CURRENT_ALIAS_DESC.get()); 3163 changeAliasCurrentAlias.addLongIdentifier("currentAlias", true); 3164 changeAliasCurrentAlias.addLongIdentifier("old-alias", true); 3165 changeAliasCurrentAlias.addLongIdentifier("oldAlias", true); 3166 changeAliasCurrentAlias.addLongIdentifier("source-alias", true); 3167 changeAliasCurrentAlias.addLongIdentifier("sourceAlias", true); 3168 changeAliasCurrentAlias.addLongIdentifier("alias", true); 3169 changeAliasCurrentAlias.addLongIdentifier("current-nickname", true); 3170 changeAliasCurrentAlias.addLongIdentifier("currentNickname", true); 3171 changeAliasCurrentAlias.addLongIdentifier("old-nickname", true); 3172 changeAliasCurrentAlias.addLongIdentifier("oldNickname", true); 3173 changeAliasCurrentAlias.addLongIdentifier("source-nickname", true); 3174 changeAliasCurrentAlias.addLongIdentifier("sourceNickname", true); 3175 changeAliasCurrentAlias.addLongIdentifier("nickname", true); 3176 changeAliasCurrentAlias.addLongIdentifier("from", false); 3177 changeAliasParser.addArgument(changeAliasCurrentAlias); 3178 3179 final StringArgument changeAliasNewAlias = new StringArgument(null, 3180 "new-alias", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3181 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_NEW_ALIAS_DESC.get()); 3182 changeAliasNewAlias.addLongIdentifier("newAlias", true); 3183 changeAliasNewAlias.addLongIdentifier("destination-alias", true); 3184 changeAliasNewAlias.addLongIdentifier("destinationAlias", true); 3185 changeAliasNewAlias.addLongIdentifier("new-nickname", true); 3186 changeAliasNewAlias.addLongIdentifier("newNickname", true); 3187 changeAliasNewAlias.addLongIdentifier("destination-nickname", true); 3188 changeAliasNewAlias.addLongIdentifier("destinationNickname", true); 3189 changeAliasNewAlias.addLongIdentifier("to", false); 3190 changeAliasParser.addArgument(changeAliasNewAlias); 3191 3192 final BooleanArgument changeAliasDisplayCommand = new BooleanArgument(null, 3193 "display-keytool-command", 1, 3194 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_ARG_DISPLAY_COMMAND_DESC.get()); 3195 changeAliasDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3196 changeAliasDisplayCommand.addLongIdentifier("show-keytool-command", true); 3197 changeAliasDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3198 changeAliasParser.addArgument(changeAliasDisplayCommand); 3199 3200 changeAliasParser.addRequiredArgumentSet(changeAliasKeystorePassword, 3201 changeAliasKeystorePasswordFile, changeAliasPromptForKeystorePassword); 3202 changeAliasParser.addExclusiveArgumentSet(changeAliasKeystorePassword, 3203 changeAliasKeystorePasswordFile, changeAliasPromptForKeystorePassword); 3204 changeAliasParser.addExclusiveArgumentSet(changeAliasPKPassword, 3205 changeAliasPKPasswordFile, changeAliasPromptForPKPassword); 3206 3207 final LinkedHashMap<String[],String> changeAliasExamples = 3208 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3209 changeAliasExamples.put( 3210 new String[] 3211 { 3212 "change-certificate-alias", 3213 "--keystore", getPlatformSpecificPath("config", "keystore"), 3214 "--keystore-password-file", 3215 getPlatformSpecificPath("config", "keystore.pin"), 3216 "--current-alias", "server-cert", 3217 "--new-alias", "server-certificate", 3218 "--display-keytool-command" 3219 }, 3220 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_EXAMPLE_1.get()); 3221 3222 final SubCommand changeAliasSubCommand = new SubCommand( 3223 "change-certificate-alias", 3224 INFO_MANAGE_CERTS_SC_CHANGE_ALIAS_DESC.get(), changeAliasParser, 3225 changeAliasExamples); 3226 changeAliasSubCommand.addName("changeCertificateAlias", true); 3227 changeAliasSubCommand.addName("change-alias", true); 3228 changeAliasSubCommand.addName("changeAlias", true); 3229 changeAliasSubCommand.addName("rename-certificate", true); 3230 changeAliasSubCommand.addName("renameCertificate", true); 3231 changeAliasSubCommand.addName("rename", true); 3232 3233 parser.addSubCommand(changeAliasSubCommand); 3234 3235 3236 // Define the "change-keystore-password" subcommand and all of its 3237 // arguments. 3238 final ArgumentParser changeKSPWParser = new ArgumentParser( 3239 "change-keystore-password", 3240 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_DESC.get()); 3241 3242 final FileArgument changeKSPWKeystore = new FileArgument(null, "keystore", 3243 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_KS_DESC.get(), 3244 true, true, true, false); 3245 changeKSPWKeystore.addLongIdentifier("keystore-path", true); 3246 changeKSPWKeystore.addLongIdentifier("keystorePath", true); 3247 changeKSPWKeystore.addLongIdentifier("keystore-file", true); 3248 changeKSPWKeystore.addLongIdentifier("keystoreFile", true); 3249 changeKSPWParser.addArgument(changeKSPWKeystore); 3250 3251 final StringArgument changeKSPWCurrentPassword = new StringArgument(null, 3252 "current-keystore-password", false, 1, 3253 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3254 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_CURRENT_PW_DESC.get()); 3255 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePassword", 3256 true); 3257 changeKSPWCurrentPassword.addLongIdentifier("current-keystore-passphrase", 3258 true); 3259 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePassphrase", 3260 true); 3261 changeKSPWCurrentPassword.addLongIdentifier("current-keystore-pin", true); 3262 changeKSPWCurrentPassword.addLongIdentifier("currentKeystorePIN", true); 3263 changeKSPWCurrentPassword.addLongIdentifier("storepass", true); 3264 changeKSPWCurrentPassword.setSensitive(true); 3265 changeKSPWParser.addArgument(changeKSPWCurrentPassword); 3266 3267 final FileArgument changeKSPWCurrentPasswordFile = new FileArgument(null, 3268 "current-keystore-password-file", false, 1, null, 3269 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_CURRENT_PW_FILE_DESC.get(), true, 3270 true, true, false); 3271 changeKSPWCurrentPasswordFile.addLongIdentifier( 3272 "currentKeystorePasswordFile", true); 3273 changeKSPWCurrentPasswordFile.addLongIdentifier( 3274 "current-keystore-passphrase-file", true); 3275 changeKSPWCurrentPasswordFile.addLongIdentifier( 3276 "currentKeystorePassphraseFile", true); 3277 changeKSPWCurrentPasswordFile.addLongIdentifier("current-keystore-pin-file", 3278 true); 3279 changeKSPWCurrentPasswordFile.addLongIdentifier("currentKeystorePINFile", 3280 true); 3281 changeKSPWParser.addArgument(changeKSPWCurrentPasswordFile); 3282 3283 final BooleanArgument changeKSPWPromptForCurrentPassword = 3284 new BooleanArgument(null, "prompt-for-current-keystore-password", 3285 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_PROMPT_FOR_CURRENT_PW_DESC.get()); 3286 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3287 "promptForCurrentKeystorePassword", true); 3288 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3289 "prompt-for-current-keystore-passphrase", true); 3290 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3291 "promptForCurrentKeystorePassphrase", true); 3292 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3293 "prompt-for-current-keystore-pin", true); 3294 changeKSPWPromptForCurrentPassword.addLongIdentifier( 3295 "promptForCurrentKeystorePIN", true); 3296 changeKSPWParser.addArgument(changeKSPWPromptForCurrentPassword); 3297 3298 final StringArgument changeKSPWNewPassword = new StringArgument(null, 3299 "new-keystore-password", false, 1, 3300 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3301 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_NEW_PW_DESC.get()); 3302 changeKSPWNewPassword.addLongIdentifier("newKeystorePassword", 3303 true); 3304 changeKSPWNewPassword.addLongIdentifier("new-keystore-passphrase", 3305 true); 3306 changeKSPWNewPassword.addLongIdentifier("newKeystorePassphrase", 3307 true); 3308 changeKSPWNewPassword.addLongIdentifier("new-keystore-pin", true); 3309 changeKSPWNewPassword.addLongIdentifier("newKeystorePIN", true); 3310 changeKSPWNewPassword.addLongIdentifier("new", true); 3311 changeKSPWNewPassword.setSensitive(true); 3312 changeKSPWParser.addArgument(changeKSPWNewPassword); 3313 3314 final FileArgument changeKSPWNewPasswordFile = new FileArgument(null, 3315 "new-keystore-password-file", false, 1, null, 3316 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_NEW_PW_FILE_DESC.get(), true, 3317 true, true, false); 3318 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePasswordFile", 3319 true); 3320 changeKSPWNewPasswordFile.addLongIdentifier("new-keystore-passphrase-file", 3321 true); 3322 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePassphraseFile", 3323 true); 3324 changeKSPWNewPasswordFile.addLongIdentifier("new-keystore-pin-file", true); 3325 changeKSPWNewPasswordFile.addLongIdentifier("newKeystorePINFile", true); 3326 changeKSPWParser.addArgument(changeKSPWNewPasswordFile); 3327 3328 final BooleanArgument changeKSPWPromptForNewPassword = 3329 new BooleanArgument(null, "prompt-for-new-keystore-password", 3330 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_PROMPT_FOR_NEW_PW_DESC.get()); 3331 changeKSPWPromptForNewPassword.addLongIdentifier( 3332 "promptForNewKeystorePassword", true); 3333 changeKSPWPromptForNewPassword.addLongIdentifier( 3334 "prompt-for-new-keystore-passphrase", true); 3335 changeKSPWPromptForNewPassword.addLongIdentifier( 3336 "promptForNewKeystorePassphrase", true); 3337 changeKSPWPromptForNewPassword.addLongIdentifier( 3338 "prompt-for-new-keystore-pin", true); 3339 changeKSPWPromptForNewPassword.addLongIdentifier( 3340 "promptForNewKeystorePIN", true); 3341 changeKSPWParser.addArgument(changeKSPWPromptForNewPassword); 3342 3343 final BooleanArgument changeKSPWDisplayCommand = new BooleanArgument(null, 3344 "display-keytool-command", 1, 3345 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_ARG_DISPLAY_COMMAND_DESC.get()); 3346 changeKSPWDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3347 changeKSPWDisplayCommand.addLongIdentifier("show-keytool-command", true); 3348 changeKSPWDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3349 changeKSPWParser.addArgument(changeKSPWDisplayCommand); 3350 3351 changeKSPWParser.addRequiredArgumentSet(changeKSPWCurrentPassword, 3352 changeKSPWCurrentPasswordFile, changeKSPWPromptForCurrentPassword); 3353 changeKSPWParser.addExclusiveArgumentSet(changeKSPWCurrentPassword, 3354 changeKSPWCurrentPasswordFile, changeKSPWPromptForCurrentPassword); 3355 changeKSPWParser.addRequiredArgumentSet(changeKSPWNewPassword, 3356 changeKSPWNewPasswordFile, changeKSPWPromptForNewPassword); 3357 changeKSPWParser.addExclusiveArgumentSet(changeKSPWNewPassword, 3358 changeKSPWNewPasswordFile, changeKSPWPromptForNewPassword); 3359 3360 final LinkedHashMap<String[],String> changeKSPWExamples = 3361 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3362 changeKSPWExamples.put( 3363 new String[] 3364 { 3365 "change-keystore-password", 3366 "--keystore", getPlatformSpecificPath("config", "keystore"), 3367 "--current-keystore-password-file", 3368 getPlatformSpecificPath("config", "current.pin"), 3369 "--new-keystore-password-file", 3370 getPlatformSpecificPath("config", "new.pin"), 3371 "--display-keytool-command" 3372 }, 3373 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_EXAMPLE_1.get( 3374 getPlatformSpecificPath("config", "keystore"), 3375 getPlatformSpecificPath("config", "current.pin"), 3376 getPlatformSpecificPath("config", "new.pin"))); 3377 3378 final SubCommand changeKSPWSubCommand = new SubCommand( 3379 "change-keystore-password", 3380 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_DESC.get(), changeKSPWParser, 3381 changeKSPWExamples); 3382 changeKSPWSubCommand.addName("changeKeystorePassword", true); 3383 changeKSPWSubCommand.addName("change-keystore-passphrase", true); 3384 changeKSPWSubCommand.addName("changeKeystorePassphrase", true); 3385 changeKSPWSubCommand.addName("change-keystore-pin", true); 3386 changeKSPWSubCommand.addName("changeKeystorePIN", true); 3387 changeKSPWSubCommand.addName("storepasswd", true); 3388 3389 parser.addSubCommand(changeKSPWSubCommand); 3390 3391 3392 // Define the "change-private-key-password" subcommand and all of its 3393 // arguments. 3394 final ArgumentParser changePKPWParser = new ArgumentParser( 3395 "change-private-key-password", 3396 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_DESC.get()); 3397 3398 final FileArgument changePKPWKeystore = new FileArgument(null, "keystore", 3399 true, 1, null, INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_DESC.get(), 3400 true, true, true, false); 3401 changePKPWKeystore.addLongIdentifier("keystore-path", true); 3402 changePKPWKeystore.addLongIdentifier("keystorePath", true); 3403 changePKPWKeystore.addLongIdentifier("keystore-file", true); 3404 changePKPWKeystore.addLongIdentifier("keystoreFile", true); 3405 changePKPWParser.addArgument(changePKPWKeystore); 3406 3407 final StringArgument changePKPWKeystorePassword = new StringArgument(null, 3408 "keystore-password", false, 1, 3409 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3410 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_PW_DESC.get()); 3411 changePKPWKeystorePassword.addLongIdentifier("keystorePassword", true); 3412 changePKPWKeystorePassword.addLongIdentifier("keystore-passphrase", true); 3413 changePKPWKeystorePassword.addLongIdentifier("keystorePassphrase", true); 3414 changePKPWKeystorePassword.addLongIdentifier("keystore-pin", true); 3415 changePKPWKeystorePassword.addLongIdentifier("keystorePIN", true); 3416 changePKPWKeystorePassword.addLongIdentifier("storepass", true); 3417 changePKPWKeystorePassword.setSensitive(true); 3418 changePKPWParser.addArgument(changePKPWKeystorePassword); 3419 3420 final FileArgument changePKPWKeystorePasswordFile = new FileArgument(null, 3421 "keystore-password-file", false, 1, null, 3422 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_PW_FILE_DESC.get(), true, 3423 true, true, false); 3424 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 3425 true); 3426 changePKPWKeystorePasswordFile.addLongIdentifier( 3427 "keystore-passphrase-file", true); 3428 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 3429 true); 3430 changePKPWKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 3431 true); 3432 changePKPWKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 3433 changePKPWParser.addArgument(changePKPWKeystorePasswordFile); 3434 3435 final BooleanArgument changePKPWPromptForKeystorePassword = 3436 new BooleanArgument(null, "prompt-for-keystore-password", 3437 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_KS_PW_DESC.get()); 3438 changePKPWPromptForKeystorePassword.addLongIdentifier( 3439 "promptForKeystorePassword", true); 3440 changePKPWPromptForKeystorePassword.addLongIdentifier( 3441 "prompt-for-keystore-passphrase", true); 3442 changePKPWPromptForKeystorePassword.addLongIdentifier( 3443 "promptForKeystorePassphrase", true); 3444 changePKPWPromptForKeystorePassword.addLongIdentifier( 3445 "prompt-for-keystore-pin", true); 3446 changePKPWPromptForKeystorePassword.addLongIdentifier( 3447 "promptForKeystorePIN", true); 3448 changePKPWParser.addArgument(changePKPWPromptForKeystorePassword); 3449 3450 final StringArgument changePKPWKeystoreType = new StringArgument(null, 3451 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3452 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_KS_TYPE_DESC.get(), 3453 ALLOWED_KEYSTORE_TYPE_VALUES); 3454 changePKPWKeystoreType.addLongIdentifier("key-store-type", true); 3455 changePKPWKeystoreType.addLongIdentifier("keystoreType", true); 3456 changePKPWKeystoreType.addLongIdentifier("keystore-format", true); 3457 changePKPWKeystoreType.addLongIdentifier("key-store-format", true); 3458 changePKPWKeystoreType.addLongIdentifier("keystoreFormat", true); 3459 changePKPWKeystoreType.addLongIdentifier("storetype", true); 3460 changePKPWParser.addArgument(changePKPWKeystoreType); 3461 3462 final StringArgument changePKPWAlias = new StringArgument(null, "alias", 3463 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3464 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_ALIAS_DESC.get()); 3465 changePKPWAlias.addLongIdentifier("nickname", true); 3466 changePKPWParser.addArgument(changePKPWAlias); 3467 3468 final StringArgument changePKPWCurrentPassword = new StringArgument(null, 3469 "current-private-key-password", false, 1, 3470 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3471 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_CURRENT_PW_DESC.get()); 3472 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPassword", 3473 true); 3474 changePKPWCurrentPassword.addLongIdentifier( 3475 "current-private-key-passphrase", true); 3476 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPassphrase", 3477 true); 3478 changePKPWCurrentPassword.addLongIdentifier("current-private-key-pin", 3479 true); 3480 changePKPWCurrentPassword.addLongIdentifier("currentPrivateKeyPIN", true); 3481 changePKPWCurrentPassword.addLongIdentifier("keypass", true); 3482 changePKPWCurrentPassword.setSensitive(true); 3483 changePKPWParser.addArgument(changePKPWCurrentPassword); 3484 3485 final FileArgument changePKPWCurrentPasswordFile = new FileArgument(null, 3486 "current-private-key-password-file", false, 1, null, 3487 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_CURRENT_PW_FILE_DESC.get(), true, 3488 true, true, false); 3489 changePKPWCurrentPasswordFile.addLongIdentifier( 3490 "currentPrivateKeyPasswordFile", true); 3491 changePKPWCurrentPasswordFile.addLongIdentifier( 3492 "current-private-key-passphrase-file", true); 3493 changePKPWCurrentPasswordFile.addLongIdentifier( 3494 "currentPrivateKeyPassphraseFile", true); 3495 changePKPWCurrentPasswordFile.addLongIdentifier( 3496 "current-private-key-pin-file", true); 3497 changePKPWCurrentPasswordFile.addLongIdentifier("currentPrivateKeyPINFile", 3498 true); 3499 changePKPWParser.addArgument(changePKPWCurrentPasswordFile); 3500 3501 final BooleanArgument changePKPWPromptForCurrentPassword = 3502 new BooleanArgument(null, "prompt-for-current-private-key-password", 3503 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_CURRENT_PW_DESC.get()); 3504 changePKPWPromptForCurrentPassword.addLongIdentifier( 3505 "promptForCurrentPrivateKeyPassword", true); 3506 changePKPWPromptForCurrentPassword.addLongIdentifier( 3507 "prompt-for-current-private-key-passphrase", true); 3508 changePKPWPromptForCurrentPassword.addLongIdentifier( 3509 "promptForCurrentPrivateKeyPassphrase", true); 3510 changePKPWPromptForCurrentPassword.addLongIdentifier( 3511 "prompt-for-current-private-key-pin", true); 3512 changePKPWPromptForCurrentPassword.addLongIdentifier( 3513 "promptForCurrentPrivateKeyPIN", true); 3514 changePKPWParser.addArgument(changePKPWPromptForCurrentPassword); 3515 3516 final StringArgument changePKPWNewPassword = new StringArgument(null, 3517 "new-private-key-password", false, 1, 3518 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3519 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_NEW_PW_DESC.get()); 3520 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPassword", 3521 true); 3522 changePKPWNewPassword.addLongIdentifier("new-private-key-passphrase", true); 3523 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPassphrase", true); 3524 changePKPWNewPassword.addLongIdentifier("new-private-key-pin", true); 3525 changePKPWNewPassword.addLongIdentifier("newPrivateKeyPIN", true); 3526 changePKPWNewPassword.addLongIdentifier("new", true); 3527 changePKPWNewPassword.setSensitive(true); 3528 changePKPWParser.addArgument(changePKPWNewPassword); 3529 3530 final FileArgument changePKPWNewPasswordFile = new FileArgument(null, 3531 "new-private-key-password-file", false, 1, null, 3532 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_NEW_PW_FILE_DESC.get(), true, 3533 true, true, false); 3534 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPasswordFile", 3535 true); 3536 changePKPWNewPasswordFile.addLongIdentifier( 3537 "new-private-key-passphrase-file", true); 3538 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPassphraseFile", 3539 true); 3540 changePKPWNewPasswordFile.addLongIdentifier("new-private-key-pin-file", 3541 true); 3542 changePKPWNewPasswordFile.addLongIdentifier("newPrivateKeyPINFile", true); 3543 changePKPWParser.addArgument(changePKPWNewPasswordFile); 3544 3545 final BooleanArgument changePKPWPromptForNewPassword = 3546 new BooleanArgument(null, "prompt-for-new-private-key-password", 3547 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_PROMPT_FOR_NEW_PW_DESC.get()); 3548 changePKPWPromptForNewPassword.addLongIdentifier( 3549 "promptForNewPrivateKeyPassword", true); 3550 changePKPWPromptForNewPassword.addLongIdentifier( 3551 "prompt-for-new-private-key-passphrase", true); 3552 changePKPWPromptForNewPassword.addLongIdentifier( 3553 "promptForNewPrivateKeyPassphrase", true); 3554 changePKPWPromptForNewPassword.addLongIdentifier( 3555 "prompt-for-new-private-key-pin", true); 3556 changePKPWPromptForNewPassword.addLongIdentifier( 3557 "promptForNewPrivateKeyPIN", true); 3558 changePKPWParser.addArgument(changePKPWPromptForNewPassword); 3559 3560 final BooleanArgument changePKPWDisplayCommand = new BooleanArgument(null, 3561 "display-keytool-command", 1, 3562 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_ARG_DISPLAY_COMMAND_DESC.get()); 3563 changePKPWDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 3564 changePKPWDisplayCommand.addLongIdentifier("show-keytool-command", true); 3565 changePKPWDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 3566 changePKPWParser.addArgument(changePKPWDisplayCommand); 3567 3568 changePKPWParser.addRequiredArgumentSet(changePKPWKeystorePassword, 3569 changePKPWKeystorePasswordFile, changePKPWPromptForKeystorePassword); 3570 changePKPWParser.addExclusiveArgumentSet(changePKPWKeystorePassword, 3571 changePKPWKeystorePasswordFile, changePKPWPromptForKeystorePassword); 3572 changePKPWParser.addRequiredArgumentSet(changePKPWCurrentPassword, 3573 changePKPWCurrentPasswordFile, changePKPWPromptForCurrentPassword); 3574 changePKPWParser.addExclusiveArgumentSet(changePKPWCurrentPassword, 3575 changePKPWCurrentPasswordFile, changePKPWPromptForCurrentPassword); 3576 changePKPWParser.addRequiredArgumentSet(changePKPWNewPassword, 3577 changePKPWNewPasswordFile, changePKPWPromptForNewPassword); 3578 changePKPWParser.addExclusiveArgumentSet(changePKPWNewPassword, 3579 changePKPWNewPasswordFile, changePKPWPromptForNewPassword); 3580 3581 final LinkedHashMap<String[],String> changePKPWExamples = 3582 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3583 changePKPWExamples.put( 3584 new String[] 3585 { 3586 "change-private-key-password", 3587 "--keystore", getPlatformSpecificPath("config", "keystore"), 3588 "--keystore-password-file", 3589 getPlatformSpecificPath("config", "keystore.pin"), 3590 "--alias", "server-cert", 3591 "--current-private-key-password-file", 3592 getPlatformSpecificPath("config", "current.pin"), 3593 "--new-private-key-password-file", 3594 getPlatformSpecificPath("config", "new.pin"), 3595 "--display-keytool-command" 3596 }, 3597 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_EXAMPLE_1.get( 3598 getPlatformSpecificPath("config", "keystore"), 3599 getPlatformSpecificPath("config", "current.pin"), 3600 getPlatformSpecificPath("config", "new.pin"))); 3601 3602 final SubCommand changePKPWSubCommand = new SubCommand( 3603 "change-private-key-password", 3604 INFO_MANAGE_CERTS_SC_CHANGE_PK_PW_DESC.get(), changePKPWParser, 3605 changePKPWExamples); 3606 changePKPWSubCommand.addName("changePrivateKeyPassword", true); 3607 changePKPWSubCommand.addName("change-private-key-passphrase", true); 3608 changePKPWSubCommand.addName("changePrivateKeyPassphrase", true); 3609 changePKPWSubCommand.addName("change-private-key-pin", true); 3610 changePKPWSubCommand.addName("changePrivateKeyPIN", true); 3611 changePKPWSubCommand.addName("change-key-password", true); 3612 changePKPWSubCommand.addName("changeKeyPassword", true); 3613 changePKPWSubCommand.addName("change-key-passphrase", true); 3614 changePKPWSubCommand.addName("changeKeyPassphrase", true); 3615 changePKPWSubCommand.addName("change-key-pin", true); 3616 changePKPWSubCommand.addName("changeKeyPIN", true); 3617 changePKPWSubCommand.addName("keypasswd", true); 3618 3619 parser.addSubCommand(changePKPWSubCommand); 3620 3621 3622 // Define the "copy-keystore" subcommand and all of its arguments. 3623 final ArgumentParser copyKSParser = new ArgumentParser("copy-keystore", 3624 INFO_MANAGE_CERTS_SC_COPY_KS_DESC.get()); 3625 3626 final FileArgument copyKSSourceKeystore = new FileArgument(null, 3627 "source-keystore", true, 1, null, 3628 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_DESC.get(), true, true, true, 3629 false); 3630 copyKSSourceKeystore.addLongIdentifier("sourceKeystore", true); 3631 copyKSSourceKeystore.addLongIdentifier("source-keystore-path", true); 3632 copyKSSourceKeystore.addLongIdentifier("sourceKeystorePath", true); 3633 copyKSSourceKeystore.addLongIdentifier("source-keystore-file", true); 3634 copyKSSourceKeystore.addLongIdentifier("sourceKeystoreFile", true); 3635 copyKSParser.addArgument(copyKSSourceKeystore); 3636 3637 final StringArgument copyKSSourceKeystorePassword = new StringArgument(null, 3638 "source-keystore-password", false, 1, 3639 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3640 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_PW_DESC.get()); 3641 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePassword", 3642 true); 3643 copyKSSourceKeystorePassword.addLongIdentifier("source-keystore-passphrase", 3644 true); 3645 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePassphrase", 3646 true); 3647 copyKSSourceKeystorePassword.addLongIdentifier("source-keystore-pin", true); 3648 copyKSSourceKeystorePassword.addLongIdentifier("sourceKeystorePIN", true); 3649 copyKSParser.addArgument(copyKSSourceKeystorePassword); 3650 3651 final FileArgument copyKSSourceKeystorePasswordFile = new FileArgument(null, 3652 "source-keystore-password-file", false, 1, null, 3653 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_PW_FILE_DESC.get(), true, true, 3654 true, false); 3655 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3656 "sourceKeystorePasswordFile", true); 3657 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3658 "source-keystore-passphrase-file", true); 3659 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3660 "sourceKeystorePassphraseFile", true); 3661 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3662 "source-keystore-pin-file", true); 3663 copyKSSourceKeystorePasswordFile.addLongIdentifier( 3664 "sourceKeystorePINFile", true); 3665 copyKSParser.addArgument(copyKSSourceKeystorePasswordFile); 3666 3667 final BooleanArgument copyKSPromptForSourceKeystorePassword = 3668 new BooleanArgument(null, "prompt-for-source-keystore-password", 1, 3669 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_SRC_KS_PW.get()); 3670 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3671 "promptForSourceKeystorePassword", true); 3672 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3673 "prompt-for-source-keystore-passphrase", true); 3674 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3675 "promptForSourceKeystorePassphrase", true); 3676 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3677 "prompt-for-source-keystore-pin", true); 3678 copyKSPromptForSourceKeystorePassword.addLongIdentifier( 3679 "promptForSourceKeystorePIN", true); 3680 copyKSParser.addArgument(copyKSPromptForSourceKeystorePassword); 3681 3682 final StringArgument copyKSSourcePKPassword = new StringArgument(null, 3683 "source-private-key-password", false, 1, 3684 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3685 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_PK_PW_DESC.get()); 3686 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPassword", true); 3687 copyKSSourcePKPassword.addLongIdentifier("source-private-key-passphrase", 3688 true); 3689 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPassphrase", 3690 true); 3691 copyKSSourcePKPassword.addLongIdentifier("source-private-key-pin", true); 3692 copyKSSourcePKPassword.addLongIdentifier("sourcePrivateKeyPIN", true); 3693 copyKSParser.addArgument(copyKSSourcePKPassword); 3694 3695 final FileArgument copyKSSourcePKPasswordFile = new FileArgument(null, 3696 "source-private-key-password-file", false, 1, null, 3697 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_PK_PW_FILE_DESC.get(), true, true, 3698 true, false); 3699 copyKSSourcePKPasswordFile.addLongIdentifier( 3700 "sourcePrivateKeyPasswordFile", true); 3701 copyKSSourcePKPasswordFile.addLongIdentifier( 3702 "source-private-key-passphrase-file", true); 3703 copyKSSourcePKPasswordFile.addLongIdentifier( 3704 "sourcePrivateKeyPassphraseFile", true); 3705 copyKSSourcePKPasswordFile.addLongIdentifier( 3706 "source-private-key-pin-file", true); 3707 copyKSSourcePKPasswordFile.addLongIdentifier( 3708 "sourcePrivateKeyPINFile", true); 3709 copyKSParser.addArgument(copyKSSourcePKPasswordFile); 3710 3711 final BooleanArgument copyKSPromptForSourcePKPassword = 3712 new BooleanArgument(null, "prompt-for-source-private-key-password", 1, 3713 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_SRC_PK_PW.get()); 3714 copyKSPromptForSourcePKPassword.addLongIdentifier( 3715 "promptForSourcePrivateKeyPassword", true); 3716 copyKSPromptForSourcePKPassword.addLongIdentifier( 3717 "prompt-for-source-private-key-passphrase", true); 3718 copyKSPromptForSourcePKPassword.addLongIdentifier( 3719 "promptForSourcePrivateKeyPassphrase", true); 3720 copyKSPromptForSourcePKPassword.addLongIdentifier( 3721 "prompt-for-source-private-key-pin", true); 3722 copyKSPromptForSourcePKPassword.addLongIdentifier( 3723 "promptForSourcePrivateKeyPIN", true); 3724 copyKSParser.addArgument(copyKSPromptForSourcePKPassword); 3725 3726 final StringArgument copyKSSourceKeystoreType = new StringArgument(null, 3727 "source-keystore-type", false, 1, 3728 INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3729 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_SRC_KS_TYPE.get(), 3730 ALLOWED_KEYSTORE_TYPE_VALUES); 3731 copyKSSourceKeystoreType.addLongIdentifier("source-key-store-type", true); 3732 copyKSSourceKeystoreType.addLongIdentifier("sourceKeystoreType", true); 3733 copyKSSourceKeystoreType.addLongIdentifier("source-keystore-format", true); 3734 copyKSSourceKeystoreType.addLongIdentifier("source-key-store-format", true); 3735 copyKSSourceKeystoreType.addLongIdentifier("sourceKeystoreFormat", true); 3736 copyKSParser.addArgument(copyKSSourceKeystoreType); 3737 3738 final FileArgument copyKSDestKeystore = new FileArgument(null, 3739 "destination-keystore", true, 1, null, 3740 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_DESC.get(), false, true, true, 3741 false); 3742 copyKSDestKeystore.addLongIdentifier("destinationKeystore", true); 3743 copyKSDestKeystore.addLongIdentifier("destination-keystore-path", true); 3744 copyKSDestKeystore.addLongIdentifier("destinationKeystorePath", true); 3745 copyKSDestKeystore.addLongIdentifier("destination-keystore-file", true); 3746 copyKSDestKeystore.addLongIdentifier("destinationKeystoreFile", true); 3747 copyKSDestKeystore.addLongIdentifier("target-keystore", true); 3748 copyKSDestKeystore.addLongIdentifier("targetKeystore", true); 3749 copyKSDestKeystore.addLongIdentifier("target-keystore-path", true); 3750 copyKSDestKeystore.addLongIdentifier("targetKeystorePath", true); 3751 copyKSDestKeystore.addLongIdentifier("target-keystore-file", true); 3752 copyKSDestKeystore.addLongIdentifier("targetKeystoreFile", true); 3753 copyKSParser.addArgument(copyKSDestKeystore); 3754 3755 final StringArgument copyKSDestKeystorePassword = new StringArgument(null, 3756 "destination-keystore-password", false, 1, 3757 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3758 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_PW_DESC.get()); 3759 copyKSDestKeystorePassword.addLongIdentifier("destinationKeystorePassword", 3760 true); 3761 copyKSDestKeystorePassword.addLongIdentifier( 3762 "destination-keystore-passphrase", true); 3763 copyKSDestKeystorePassword.addLongIdentifier( 3764 "destinationKeystorePassphrase", true); 3765 copyKSDestKeystorePassword.addLongIdentifier("destination-keystore-pin", 3766 true); 3767 copyKSDestKeystorePassword.addLongIdentifier("destinationKeystorePIN", 3768 true); 3769 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-password", 3770 true); 3771 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePassword", 3772 true); 3773 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-passphrase", 3774 true); 3775 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePassphrase", 3776 true); 3777 copyKSDestKeystorePassword.addLongIdentifier("target-keystore-pin", true); 3778 copyKSDestKeystorePassword.addLongIdentifier("targetKeystorePIN", true); 3779 copyKSParser.addArgument(copyKSDestKeystorePassword); 3780 3781 final FileArgument copyKSDestKeystorePasswordFile = new FileArgument(null, 3782 "destination-keystore-password-file", false, 1, null, 3783 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_PW_FILE_DESC.get(), true, true, 3784 true, false); 3785 copyKSDestKeystorePasswordFile.addLongIdentifier( 3786 "destinationKeystorePasswordFile", true); 3787 copyKSDestKeystorePasswordFile.addLongIdentifier( 3788 "destination-keystore-passphrase-file", true); 3789 copyKSDestKeystorePasswordFile.addLongIdentifier( 3790 "destinationKeystorePassphraseFile", true); 3791 copyKSDestKeystorePasswordFile.addLongIdentifier( 3792 "destination-keystore-pin-file", true); 3793 copyKSDestKeystorePasswordFile.addLongIdentifier( 3794 "destinationKeystorePINFile", true); 3795 copyKSDestKeystorePasswordFile.addLongIdentifier( 3796 "target-keystore-password-file", true); 3797 copyKSDestKeystorePasswordFile.addLongIdentifier( 3798 "targetKeystorePasswordFile", true); 3799 copyKSDestKeystorePasswordFile.addLongIdentifier( 3800 "target-keystore-passphrase-file", true); 3801 copyKSDestKeystorePasswordFile.addLongIdentifier( 3802 "targetKeystorePassphraseFile", true); 3803 copyKSDestKeystorePasswordFile.addLongIdentifier("target-keystore-pin-file", 3804 true); 3805 copyKSDestKeystorePasswordFile.addLongIdentifier("targetKeystorePINFile", 3806 true); 3807 copyKSParser.addArgument(copyKSDestKeystorePasswordFile); 3808 3809 final BooleanArgument copyKSPromptForDestKeystorePassword = 3810 new BooleanArgument(null, "prompt-for-destination-keystore-password", 3811 1, INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_DST_KS_PW.get()); 3812 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3813 "promptForDestinationKeystorePassword", true); 3814 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3815 "prompt-for-Destination-keystore-passphrase", true); 3816 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3817 "promptForDestinationKeystorePassphrase", true); 3818 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3819 "prompt-for-Destination-keystore-pin", true); 3820 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3821 "promptForDestinationKeystorePIN", true); 3822 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3823 "prompt-for-target-keystore-password", true); 3824 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3825 "promptForTargetKeystorePassword", true); 3826 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3827 "prompt-for-Target-keystore-passphrase", true); 3828 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3829 "promptForTargetKeystorePassphrase", true); 3830 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3831 "prompt-for-Target-keystore-pin", true); 3832 copyKSPromptForDestKeystorePassword.addLongIdentifier( 3833 "promptForTargetKeystorePIN", true); 3834 copyKSParser.addArgument(copyKSPromptForDestKeystorePassword); 3835 3836 final StringArgument copyKSDestPKPassword = new StringArgument(null, 3837 "destination-private-key-password", false, 1, 3838 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 3839 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_PK_PW_DESC.get()); 3840 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPassword", 3841 true); 3842 copyKSDestPKPassword.addLongIdentifier("destination-private-key-passphrase", 3843 true); 3844 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPassphrase", 3845 true); 3846 copyKSDestPKPassword.addLongIdentifier("destination-private-key-pin", true); 3847 copyKSDestPKPassword.addLongIdentifier("destinationPrivateKeyPIN", true); 3848 copyKSDestPKPassword.addLongIdentifier("target-private-key-password", 3849 true); 3850 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPassword", 3851 true); 3852 copyKSDestPKPassword.addLongIdentifier("target-private-key-passphrase", 3853 true); 3854 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPassphrase", 3855 true); 3856 copyKSDestPKPassword.addLongIdentifier("target-private-key-pin", true); 3857 copyKSDestPKPassword.addLongIdentifier("targetPrivateKeyPIN", true); 3858 copyKSParser.addArgument(copyKSDestPKPassword); 3859 3860 final FileArgument copyKSDestPKPasswordFile = new FileArgument(null, 3861 "destination-private-key-password-file", false, 1, null, 3862 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_PK_PW_FILE_DESC.get(), true, true, 3863 true, false); 3864 copyKSDestPKPasswordFile.addLongIdentifier( 3865 "destinationPrivateKeyPasswordFile", true); 3866 copyKSDestPKPasswordFile.addLongIdentifier( 3867 "destination-private-key-passphrase-file", true); 3868 copyKSDestPKPasswordFile.addLongIdentifier( 3869 "destinationPrivateKeyPassphraseFile", true); 3870 copyKSDestPKPasswordFile.addLongIdentifier( 3871 "destination-private-key-pin-file", true); 3872 copyKSDestPKPasswordFile.addLongIdentifier( 3873 "destinationPrivateKeyPINFile", true); 3874 copyKSDestPKPasswordFile.addLongIdentifier( 3875 "target-private-key-password-file", true); 3876 copyKSDestPKPasswordFile.addLongIdentifier( 3877 "targetPrivateKeyPasswordFile", true); 3878 copyKSDestPKPasswordFile.addLongIdentifier( 3879 "target-private-key-passphrase-file", true); 3880 copyKSDestPKPasswordFile.addLongIdentifier( 3881 "targetPrivateKeyPassphraseFile", true); 3882 copyKSDestPKPasswordFile.addLongIdentifier( 3883 "target-private-key-pin-file", true); 3884 copyKSDestPKPasswordFile.addLongIdentifier( 3885 "targetPrivateKeyPINFile", true); 3886 copyKSParser.addArgument(copyKSDestPKPasswordFile); 3887 3888 final BooleanArgument copyKSPromptForDestPKPassword = 3889 new BooleanArgument(null, 3890 "prompt-for-destination-private-key-password", 1, 3891 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_PROMPT_FOR_DST_PK_PW.get()); 3892 copyKSPromptForDestPKPassword.addLongIdentifier( 3893 "promptForDestinationPrivateKeyPassword", true); 3894 copyKSPromptForDestPKPassword.addLongIdentifier( 3895 "prompt-for-Destination-private-key-passphrase", true); 3896 copyKSPromptForDestPKPassword.addLongIdentifier( 3897 "promptForDestinationPrivateKeyPassphrase", true); 3898 copyKSPromptForDestPKPassword.addLongIdentifier( 3899 "prompt-for-Destination-private-key-pin", true); 3900 copyKSPromptForDestPKPassword.addLongIdentifier( 3901 "promptForDestinationPrivateKeyPIN", true); 3902 copyKSPromptForDestPKPassword.addLongIdentifier( 3903 "prompt-for-target-private-key-password", true); 3904 copyKSPromptForDestPKPassword.addLongIdentifier( 3905 "promptForTargetPrivateKeyPassword", true); 3906 copyKSPromptForDestPKPassword.addLongIdentifier( 3907 "prompt-for-Target-private-key-passphrase", true); 3908 copyKSPromptForDestPKPassword.addLongIdentifier( 3909 "promptForTargetPrivateKeyPassphrase", true); 3910 copyKSPromptForDestPKPassword.addLongIdentifier( 3911 "prompt-for-Target-private-key-pin", true); 3912 copyKSPromptForDestPKPassword.addLongIdentifier( 3913 "promptForTargetPrivateKeyPIN", true); 3914 copyKSParser.addArgument(copyKSPromptForDestPKPassword); 3915 3916 final StringArgument copyKSDestKeystoreType = new StringArgument(null, 3917 "destination-keystore-type", false, 1, 3918 INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 3919 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_DST_KS_TYPE.get(), 3920 ALLOWED_KEYSTORE_TYPE_VALUES); 3921 copyKSDestKeystoreType.addLongIdentifier("destination-key-store-type", 3922 true); 3923 copyKSDestKeystoreType.addLongIdentifier("destinationKeystoreType", true); 3924 copyKSDestKeystoreType.addLongIdentifier("destination-keystore-format", 3925 true); 3926 copyKSDestKeystoreType.addLongIdentifier("destination-key-store-format", 3927 true); 3928 copyKSDestKeystoreType.addLongIdentifier("destinationKeystoreFormat", true); 3929 copyKSDestKeystoreType.addLongIdentifier("target-key-store-type", true); 3930 copyKSDestKeystoreType.addLongIdentifier("targetKeystoreType", true); 3931 copyKSDestKeystoreType.addLongIdentifier("target-keystore-format", true); 3932 copyKSDestKeystoreType.addLongIdentifier("target-key-store-format", true); 3933 copyKSDestKeystoreType.addLongIdentifier("targetKeystoreFormat", true); 3934 copyKSParser.addArgument(copyKSDestKeystoreType); 3935 3936 final StringArgument copyKSAlias = new StringArgument(null, "alias", false, 3937 0, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 3938 INFO_MANAGE_CERTS_SC_COPY_KS_ARG_ALIAS.get()); 3939 copyKSAlias.addLongIdentifier("nickname", true); 3940 copyKSParser.addArgument(copyKSAlias); 3941 3942 copyKSParser.addRequiredArgumentSet(copyKSSourceKeystorePassword, 3943 copyKSSourceKeystorePasswordFile, 3944 copyKSPromptForSourceKeystorePassword); 3945 copyKSParser.addExclusiveArgumentSet(copyKSSourceKeystorePassword, 3946 copyKSSourceKeystorePasswordFile, 3947 copyKSPromptForSourceKeystorePassword); 3948 copyKSParser.addExclusiveArgumentSet(copyKSSourcePKPassword, 3949 copyKSSourcePKPasswordFile, copyKSPromptForDestPKPassword); 3950 copyKSParser.addExclusiveArgumentSet(copyKSDestKeystorePassword, 3951 copyKSDestKeystorePasswordFile, copyKSPromptForDestKeystorePassword); 3952 copyKSParser.addExclusiveArgumentSet(copyKSDestPKPassword, 3953 copyKSDestPKPasswordFile, copyKSPromptForDestPKPassword); 3954 3955 final LinkedHashMap<String[],String> copyKeyStoreExamples = 3956 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 3957 copyKeyStoreExamples.put( 3958 new String[] 3959 { 3960 "copy-keystore", 3961 "--source-keystore", 3962 getPlatformSpecificPath("config", "keystore.jks"), 3963 "--source-keystore-password-file", 3964 getPlatformSpecificPath("config", "keystore.pin"), 3965 "--source-keystore-type", "JKS", 3966 "--destination-keystore", 3967 getPlatformSpecificPath("config", "keystore.p12"), 3968 "--destination-keystore-password-file", 3969 getPlatformSpecificPath("config", "keystore.pin"), 3970 "--destination-keystore-type", "PKCS12" 3971 }, 3972 INFO_MANAGE_CERTS_SC_COPY_KS_EXAMPLE_1.get("keystore.jks", 3973 "keystore.p12")); 3974 3975 final SubCommand copyKeyStoreSubCommand = new SubCommand("copy-keystore", 3976 INFO_MANAGE_CERTS_SC_COPY_KS_DESC.get(), copyKSParser, 3977 copyKeyStoreExamples); 3978 copyKeyStoreSubCommand.addName("copy-key-store", true); 3979 copyKeyStoreSubCommand.addName("copyKeyStore", true); 3980 copyKeyStoreSubCommand.addName("import-keystore", true); 3981 copyKeyStoreSubCommand.addName("import-key-store", true); 3982 copyKeyStoreSubCommand.addName("importKeyStore", true); 3983 copyKeyStoreSubCommand.addName("convert-keystore", true); 3984 copyKeyStoreSubCommand.addName("convert-key-store", true); 3985 copyKeyStoreSubCommand.addName("convertKeyStore", true); 3986 3987 parser.addSubCommand(copyKeyStoreSubCommand); 3988 3989 // Define the "retrieve-server-certificate" subcommand and all of its 3990 // arguments. 3991 final ArgumentParser retrieveCertParser = new ArgumentParser( 3992 "retrieve-server-certificate", 3993 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_DESC.get()); 3994 3995 final StringArgument retrieveCertHostname = new StringArgument('h', 3996 "hostname", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_HOST.get(), 3997 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_HOSTNAME_DESC.get()); 3998 retrieveCertHostname.addLongIdentifier("server-address", true); 3999 retrieveCertHostname.addLongIdentifier("serverAddress", true); 4000 retrieveCertHostname.addLongIdentifier("address", true); 4001 retrieveCertParser.addArgument(retrieveCertHostname); 4002 4003 final IntegerArgument retrieveCertPort = new IntegerArgument('p', 4004 "port", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_PORT.get(), 4005 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_PORT_DESC.get(), 1, 65_535); 4006 retrieveCertPort.addLongIdentifier("server-port", true); 4007 retrieveCertPort.addLongIdentifier("serverPort", true); 4008 retrieveCertParser.addArgument(retrieveCertPort); 4009 4010 final BooleanArgument retrieveCertUseStartTLS = new BooleanArgument('q', 4011 "use-ldap-start-tls", 1, 4012 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_USE_START_TLS_DESC.get()); 4013 retrieveCertUseStartTLS.addLongIdentifier("use-ldap-starttls", true); 4014 retrieveCertUseStartTLS.addLongIdentifier("useLDAPStartTLS", true); 4015 retrieveCertUseStartTLS.addLongIdentifier("use-start-tls", true); 4016 retrieveCertUseStartTLS.addLongIdentifier("use-starttls", true); 4017 retrieveCertUseStartTLS.addLongIdentifier("useStartTLS", true); 4018 retrieveCertParser.addArgument(retrieveCertUseStartTLS); 4019 4020 final FileArgument retrieveCertOutputFile = new FileArgument(null, 4021 "output-file", false, 1, null, 4022 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_FILE_DESC.get(), false, true, 4023 true, false); 4024 retrieveCertOutputFile.addLongIdentifier("outputFile", true); 4025 retrieveCertOutputFile.addLongIdentifier("export-file", true); 4026 retrieveCertOutputFile.addLongIdentifier("exportFile", true); 4027 retrieveCertOutputFile.addLongIdentifier("certificate-file", true); 4028 retrieveCertOutputFile.addLongIdentifier("certificateFile", true); 4029 retrieveCertOutputFile.addLongIdentifier("file", true); 4030 retrieveCertOutputFile.addLongIdentifier("filename", true); 4031 retrieveCertParser.addArgument(retrieveCertOutputFile); 4032 4033 final Set<String> retrieveCertOutputFormatAllowedValues = StaticUtils.setOf( 4034 "PEM", "text", "txt", "RFC", "DER", "binary", "bin"); 4035 final StringArgument retrieveCertOutputFormat = new StringArgument(null, 4036 "output-format", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_FORMAT.get(), 4037 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_FORMAT_DESC.get(), 4038 retrieveCertOutputFormatAllowedValues, "PEM"); 4039 retrieveCertOutputFormat.addLongIdentifier("outputFormat", true); 4040 retrieveCertParser.addArgument(retrieveCertOutputFormat); 4041 4042 final BooleanArgument retrieveCertOnlyPeer = new BooleanArgument(null, 4043 "only-peer-certificate", 1, 4044 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_ONLY_PEER_DESC.get()); 4045 retrieveCertOnlyPeer.addLongIdentifier("onlyPeerCertificate", true); 4046 retrieveCertOnlyPeer.addLongIdentifier("only-peer", true); 4047 retrieveCertOnlyPeer.addLongIdentifier("onlyPeer", true); 4048 retrieveCertOnlyPeer.addLongIdentifier("peer-certificate-only", true); 4049 retrieveCertOnlyPeer.addLongIdentifier("peerCertificateOnly", true); 4050 retrieveCertOnlyPeer.addLongIdentifier("peer-only", true); 4051 retrieveCertOnlyPeer.addLongIdentifier("peerOnly", true); 4052 retrieveCertParser.addArgument(retrieveCertOnlyPeer); 4053 4054 final BooleanArgument retrieveCertEnableSSLDebugging = new BooleanArgument( 4055 null, "enableSSLDebugging", 1, 4056 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_ENABLE_SSL_DEBUGGING_DESC. 4057 get()); 4058 retrieveCertEnableSSLDebugging.addLongIdentifier("enableTLSDebugging", 4059 true); 4060 retrieveCertEnableSSLDebugging.addLongIdentifier("enableStartTLSDebugging", 4061 true); 4062 retrieveCertEnableSSLDebugging.addLongIdentifier("enable-ssl-debugging", 4063 true); 4064 retrieveCertEnableSSLDebugging.addLongIdentifier("enable-tls-debugging", 4065 true); 4066 retrieveCertEnableSSLDebugging.addLongIdentifier( 4067 "enable-starttls-debugging", true); 4068 retrieveCertEnableSSLDebugging.addLongIdentifier( 4069 "enable-start-tls-debugging", true); 4070 retrieveCertParser.addArgument(retrieveCertEnableSSLDebugging); 4071 addEnableSSLDebuggingArgument(retrieveCertEnableSSLDebugging); 4072 4073 final BooleanArgument retrieveCertVerbose = new BooleanArgument(null, 4074 "verbose", 1, 4075 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_ARG_VERBOSE_DESC.get()); 4076 retrieveCertParser.addArgument(retrieveCertVerbose); 4077 4078 retrieveCertParser.addDependentArgumentSet(retrieveCertOutputFormat, 4079 retrieveCertOutputFile); 4080 4081 final LinkedHashMap<String[],String> retrieveCertExamples = 4082 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4083 retrieveCertExamples.put( 4084 new String[] 4085 { 4086 "retrieve-server-certificate", 4087 "--hostname", "ds.example.com", 4088 "--port", "636" 4089 }, 4090 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_1.get( 4091 getPlatformSpecificPath("config", "truststore"))); 4092 retrieveCertExamples.put( 4093 new String[] 4094 { 4095 "retrieve-server-certificate", 4096 "--hostname", "ds.example.com", 4097 "--port", "389", 4098 "--use-ldap-start-tls", 4099 "--only-peer-certificate", 4100 "--output-file", "ds-cert.pem", 4101 "--output-format", "PEM", 4102 "--verbose" 4103 }, 4104 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_2.get( 4105 getPlatformSpecificPath("config", "truststore"))); 4106 4107 final SubCommand retrieveCertSubCommand = new SubCommand( 4108 "retrieve-server-certificate", 4109 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_DESC.get(), retrieveCertParser, 4110 retrieveCertExamples); 4111 retrieveCertSubCommand.addName("retrieveServerCertificate", true); 4112 retrieveCertSubCommand.addName("retrieve-certificate", true); 4113 retrieveCertSubCommand.addName("retrieveCertificate", true); 4114 retrieveCertSubCommand.addName("get-server-certificate", true); 4115 retrieveCertSubCommand.addName("getServerCertificate", true); 4116 retrieveCertSubCommand.addName("get-certificate", true); 4117 retrieveCertSubCommand.addName("getCertificate", true); 4118 retrieveCertSubCommand.addName("display-server-certificate", true); 4119 retrieveCertSubCommand.addName("displayServerCertificate", true); 4120 4121 parser.addSubCommand(retrieveCertSubCommand); 4122 4123 4124 // Define the "trust-server-certificate" subcommand and all of its 4125 // arguments. 4126 final ArgumentParser trustServerParser = new ArgumentParser( 4127 "trust-server-certificate", 4128 INFO_MANAGE_CERTS_SC_TRUST_SERVER_DESC.get()); 4129 4130 final StringArgument trustServerHostname = new StringArgument('h', 4131 "hostname", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_HOST.get(), 4132 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_HOSTNAME_DESC.get()); 4133 trustServerHostname.addLongIdentifier("server-address", true); 4134 trustServerHostname.addLongIdentifier("serverAddress", true); 4135 trustServerHostname.addLongIdentifier("address", true); 4136 trustServerParser.addArgument(trustServerHostname); 4137 4138 final IntegerArgument trustServerPort = new IntegerArgument('p', 4139 "port", true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_PORT.get(), 4140 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_PORT_DESC.get(), 1, 65_535); 4141 trustServerPort.addLongIdentifier("server-port", true); 4142 trustServerPort.addLongIdentifier("serverPort", true); 4143 trustServerParser.addArgument(trustServerPort); 4144 4145 final BooleanArgument trustServerUseStartTLS = new BooleanArgument('q', 4146 "use-ldap-start-tls", 1, 4147 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_USE_START_TLS_DESC.get()); 4148 trustServerUseStartTLS.addLongIdentifier("use-ldap-starttls", true); 4149 trustServerUseStartTLS.addLongIdentifier("useLDAPStartTLS", true); 4150 trustServerUseStartTLS.addLongIdentifier("use-start-tls", true); 4151 trustServerUseStartTLS.addLongIdentifier("use-starttls", true); 4152 trustServerUseStartTLS.addLongIdentifier("useStartTLS", true); 4153 trustServerParser.addArgument(trustServerUseStartTLS); 4154 4155 final FileArgument trustServerKeystore = new FileArgument(null, "keystore", 4156 true, 1, null, INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_DESC.get(), 4157 false, true, true, false); 4158 trustServerKeystore.addLongIdentifier("keystore-path", true); 4159 trustServerKeystore.addLongIdentifier("keystorePath", true); 4160 trustServerKeystore.addLongIdentifier("keystore-file", true); 4161 trustServerKeystore.addLongIdentifier("keystoreFile", true); 4162 trustServerParser.addArgument(trustServerKeystore); 4163 4164 final StringArgument trustServerKeystorePassword = new StringArgument(null, 4165 "keystore-password", false, 1, 4166 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 4167 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_PW_DESC.get()); 4168 trustServerKeystorePassword.addLongIdentifier("keystorePassword", true); 4169 trustServerKeystorePassword.addLongIdentifier("keystore-passphrase", true); 4170 trustServerKeystorePassword.addLongIdentifier("keystorePassphrase", true); 4171 trustServerKeystorePassword.addLongIdentifier("keystore-pin", true); 4172 trustServerKeystorePassword.addLongIdentifier("keystorePIN", true); 4173 trustServerKeystorePassword.addLongIdentifier("storepass", true); 4174 trustServerKeystorePassword.setSensitive(true); 4175 trustServerParser.addArgument(trustServerKeystorePassword); 4176 4177 final FileArgument trustServerKeystorePasswordFile = new FileArgument(null, 4178 "keystore-password-file", false, 1, null, 4179 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_PW_FILE_DESC.get(), true, 4180 true, true, false); 4181 trustServerKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 4182 true); 4183 trustServerKeystorePasswordFile.addLongIdentifier( 4184 "keystore-passphrase-file", true); 4185 trustServerKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 4186 true); 4187 trustServerKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 4188 true); 4189 trustServerKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 4190 trustServerParser.addArgument(trustServerKeystorePasswordFile); 4191 4192 final BooleanArgument trustServerPromptForKeystorePassword = 4193 new BooleanArgument(null, "prompt-for-keystore-password", 4194 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_PROMPT_FOR_KS_PW_DESC.get()); 4195 trustServerPromptForKeystorePassword.addLongIdentifier( 4196 "promptForKeystorePassword", true); 4197 trustServerPromptForKeystorePassword.addLongIdentifier( 4198 "prompt-for-keystore-passphrase", true); 4199 trustServerPromptForKeystorePassword.addLongIdentifier( 4200 "promptForKeystorePassphrase", true); 4201 trustServerPromptForKeystorePassword.addLongIdentifier( 4202 "prompt-for-keystore-pin", true); 4203 trustServerPromptForKeystorePassword.addLongIdentifier( 4204 "promptForKeystorePIN", true); 4205 trustServerParser.addArgument(trustServerPromptForKeystorePassword); 4206 4207 final StringArgument trustServerKeystoreType = new StringArgument(null, 4208 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 4209 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_KS_TYPE_DESC.get(), 4210 ALLOWED_KEYSTORE_TYPE_VALUES); 4211 trustServerKeystoreType.addLongIdentifier("key-store-type", true); 4212 trustServerKeystoreType.addLongIdentifier("keystoreType", true); 4213 trustServerKeystoreType.addLongIdentifier("keystore-format", true); 4214 trustServerKeystoreType.addLongIdentifier("key-store-format", true); 4215 trustServerKeystoreType.addLongIdentifier("keystoreFormat", true); 4216 trustServerKeystoreType.addLongIdentifier("storetype", true); 4217 trustServerParser.addArgument(trustServerKeystoreType); 4218 4219 final StringArgument trustServerAlias = new StringArgument(null, 4220 "alias", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 4221 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ALIAS_DESC.get()); 4222 trustServerAlias.addLongIdentifier("nickname", true); 4223 trustServerParser.addArgument(trustServerAlias); 4224 4225 final BooleanArgument trustServerIssuersOnly = new BooleanArgument(null, 4226 "issuers-only", 1, 4227 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ISSUERS_ONLY_DESC.get()); 4228 trustServerIssuersOnly.addLongIdentifier("issuersOnly", true); 4229 trustServerIssuersOnly.addLongIdentifier("issuer-certificates-only", true); 4230 trustServerIssuersOnly.addLongIdentifier("issuerCertificatesOnly", true); 4231 trustServerIssuersOnly.addLongIdentifier("only-issuers", true); 4232 trustServerIssuersOnly.addLongIdentifier("onlyIssuers", true); 4233 trustServerIssuersOnly.addLongIdentifier("only-issuer-certificates", true); 4234 trustServerIssuersOnly.addLongIdentifier("onlyIssuerCertificates", true); 4235 trustServerParser.addArgument(trustServerIssuersOnly); 4236 4237 final BooleanArgument trustServerEnableSSLDebugging = new BooleanArgument( 4238 null, "enableSSLDebugging", 1, 4239 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_ENABLE_SSL_DEBUGGING_DESC.get()); 4240 trustServerEnableSSLDebugging.addLongIdentifier("enableTLSDebugging", true); 4241 trustServerEnableSSLDebugging.addLongIdentifier("enableStartTLSDebugging", 4242 true); 4243 trustServerEnableSSLDebugging.addLongIdentifier("enable-ssl-debugging", 4244 true); 4245 trustServerEnableSSLDebugging.addLongIdentifier("enable-tls-debugging", 4246 true); 4247 trustServerEnableSSLDebugging.addLongIdentifier("enable-starttls-debugging", 4248 true); 4249 trustServerEnableSSLDebugging.addLongIdentifier( 4250 "enable-start-tls-debugging", true); 4251 trustServerParser.addArgument(trustServerEnableSSLDebugging); 4252 addEnableSSLDebuggingArgument(trustServerEnableSSLDebugging); 4253 4254 final BooleanArgument trustServerVerbose = new BooleanArgument(null, 4255 "verbose", 1, 4256 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_VERBOSE_DESC.get()); 4257 trustServerParser.addArgument(trustServerVerbose); 4258 4259 final BooleanArgument trustServerNoPrompt = new BooleanArgument(null, 4260 "no-prompt", 1, 4261 INFO_MANAGE_CERTS_SC_TRUST_SERVER_ARG_NO_PROMPT_DESC.get()); 4262 trustServerNoPrompt.addLongIdentifier("noPrompt", true); 4263 trustServerParser.addArgument(trustServerNoPrompt); 4264 4265 trustServerParser.addRequiredArgumentSet(trustServerKeystorePassword, 4266 trustServerKeystorePasswordFile, trustServerPromptForKeystorePassword); 4267 trustServerParser.addExclusiveArgumentSet(trustServerKeystorePassword, 4268 trustServerKeystorePasswordFile, trustServerPromptForKeystorePassword); 4269 4270 final LinkedHashMap<String[],String> trustServerExamples = 4271 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4272 trustServerExamples.put( 4273 new String[] 4274 { 4275 "trust-server-certificate", 4276 "--hostname", "ds.example.com", 4277 "--port", "636", 4278 "--keystore", getPlatformSpecificPath("config", "truststore"), 4279 "--keystore-password-file", 4280 getPlatformSpecificPath("config", "truststore.pin"), 4281 "--verbose" 4282 }, 4283 INFO_MANAGE_CERTS_SC_TRUST_SERVER_EXAMPLE_1.get( 4284 getPlatformSpecificPath("config", "truststore"))); 4285 trustServerExamples.put( 4286 new String[] 4287 { 4288 "trust-server-certificate", 4289 "--hostname", "ds.example.com", 4290 "--port", "389", 4291 "--use-ldap-start-tls", 4292 "--keystore", getPlatformSpecificPath("config", "truststore"), 4293 "--keystore-password-file", 4294 getPlatformSpecificPath("config", "truststore.pin"), 4295 "--issuers-only", 4296 "--alias", "ds-start-tls-cert", 4297 "--no-prompt" 4298 }, 4299 INFO_MANAGE_CERTS_SC_TRUST_SERVER_EXAMPLE_2.get( 4300 getPlatformSpecificPath("config", "truststore"))); 4301 4302 final SubCommand trustServerSubCommand = new SubCommand( 4303 "trust-server-certificate", 4304 INFO_MANAGE_CERTS_SC_TRUST_SERVER_DESC.get(), trustServerParser, 4305 trustServerExamples); 4306 trustServerSubCommand.addName("trustServerCertificate", true); 4307 trustServerSubCommand.addName("trust-server", true); 4308 trustServerSubCommand.addName("trustServer", true); 4309 4310 parser.addSubCommand(trustServerSubCommand); 4311 4312 4313 // Define the "check-certificate-usability" subcommand and all of its 4314 // arguments. 4315 final ArgumentParser checkUsabilityParser = new ArgumentParser( 4316 "check-certificate-usability", 4317 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_DESC.get()); 4318 4319 final FileArgument checkUsabilityKeystore = new FileArgument(null, 4320 "keystore", true, 1, null, 4321 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_DESC.get(), 4322 true, true, true, false); 4323 checkUsabilityKeystore.addLongIdentifier("keystore-path", true); 4324 checkUsabilityKeystore.addLongIdentifier("keystorePath", true); 4325 checkUsabilityKeystore.addLongIdentifier("keystore-file", true); 4326 checkUsabilityKeystore.addLongIdentifier("keystoreFile", true); 4327 checkUsabilityParser.addArgument(checkUsabilityKeystore); 4328 4329 final StringArgument checkUsabilityKeystorePassword = new StringArgument( 4330 null, "keystore-password", false, 1, 4331 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 4332 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_PW_DESC.get()); 4333 checkUsabilityKeystorePassword.addLongIdentifier("keystorePassword", true); 4334 checkUsabilityKeystorePassword.addLongIdentifier("keystore-passphrase", 4335 true); 4336 checkUsabilityKeystorePassword.addLongIdentifier("keystorePassphrase", 4337 true); 4338 checkUsabilityKeystorePassword.addLongIdentifier("keystore-pin", true); 4339 checkUsabilityKeystorePassword.addLongIdentifier("keystorePIN", true); 4340 checkUsabilityKeystorePassword.addLongIdentifier("storepass", true); 4341 checkUsabilityKeystorePassword.setSensitive(true); 4342 checkUsabilityParser.addArgument(checkUsabilityKeystorePassword); 4343 4344 final FileArgument checkUsabilityKeystorePasswordFile = new FileArgument( 4345 null, "keystore-password-file", false, 1, null, 4346 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_PW_FILE_DESC.get(), true, 4347 true, true, false); 4348 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 4349 true); 4350 checkUsabilityKeystorePasswordFile.addLongIdentifier( 4351 "keystore-passphrase-file", true); 4352 checkUsabilityKeystorePasswordFile.addLongIdentifier( 4353 "keystorePassphraseFile", true); 4354 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 4355 true); 4356 checkUsabilityKeystorePasswordFile.addLongIdentifier("keystorePINFile", 4357 true); 4358 checkUsabilityParser.addArgument(checkUsabilityKeystorePasswordFile); 4359 4360 final BooleanArgument checkUsabilityPromptForKeystorePassword = 4361 new BooleanArgument(null, "prompt-for-keystore-password", 4362 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_PROMPT_FOR_KS_PW_DESC.get()); 4363 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4364 "promptForKeystorePassword", true); 4365 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4366 "prompt-for-keystore-passphrase", true); 4367 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4368 "promptForKeystorePassphrase", true); 4369 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4370 "prompt-for-keystore-pin", true); 4371 checkUsabilityPromptForKeystorePassword.addLongIdentifier( 4372 "promptForKeystorePIN", true); 4373 checkUsabilityParser.addArgument(checkUsabilityPromptForKeystorePassword); 4374 4375 final StringArgument checkUsabilityKeystoreType = new StringArgument(null, 4376 "keystore-type", false, 1, INFO_MANAGE_CERTS_PLACEHOLDER_TYPE.get(), 4377 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_KS_TYPE_DESC.get(), 4378 ALLOWED_KEYSTORE_TYPE_VALUES); 4379 checkUsabilityKeystoreType.addLongIdentifier("key-store-type", true); 4380 checkUsabilityKeystoreType.addLongIdentifier("keystoreType", true); 4381 checkUsabilityKeystoreType.addLongIdentifier("keystore-format", true); 4382 checkUsabilityKeystoreType.addLongIdentifier("key-store-format", true); 4383 checkUsabilityKeystoreType.addLongIdentifier("keystoreFormat", true); 4384 checkUsabilityKeystoreType.addLongIdentifier("storetype", true); 4385 checkUsabilityParser.addArgument(checkUsabilityKeystoreType); 4386 4387 final StringArgument checkUsabilityAlias = new StringArgument(null, "alias", 4388 true, 1, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 4389 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_ARG_ALIAS_DESC.get()); 4390 checkUsabilityAlias.addLongIdentifier("nickname", true); 4391 checkUsabilityParser.addArgument(checkUsabilityAlias); 4392 4393 final BooleanArgument checkUsabilityIgnoreSHA1Signature = 4394 new BooleanArgument(null, 4395 "allow-sha-1-signature-for-issuer-certificates", 1, 4396 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_IGNORE_SHA1_WARNING_DESC. 4397 get()); 4398 checkUsabilityIgnoreSHA1Signature.addLongIdentifier( 4399 "allow-sha1-signature-for-issuer-certificates", true); 4400 checkUsabilityIgnoreSHA1Signature.addLongIdentifier( 4401 "allowSHA1SignatureForIssuerCertificates", true); 4402 checkUsabilityParser.addArgument(checkUsabilityIgnoreSHA1Signature); 4403 4404 checkUsabilityParser.addRequiredArgumentSet(checkUsabilityKeystorePassword, 4405 checkUsabilityKeystorePasswordFile, 4406 checkUsabilityPromptForKeystorePassword); 4407 checkUsabilityParser.addExclusiveArgumentSet(checkUsabilityKeystorePassword, 4408 checkUsabilityKeystorePasswordFile, 4409 checkUsabilityPromptForKeystorePassword); 4410 4411 final LinkedHashMap<String[],String> checkUsabilityExamples = 4412 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4413 checkUsabilityExamples.put( 4414 new String[] 4415 { 4416 "check-certificate-usability", 4417 "--keystore", getPlatformSpecificPath("config", "keystore"), 4418 "--keystore-password-file", 4419 getPlatformSpecificPath("config", "keystore.pin"), 4420 "--alias", "server-cert" 4421 }, 4422 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_EXAMPLE_1.get( 4423 getPlatformSpecificPath("config", "keystore"))); 4424 4425 final SubCommand checkUsabilitySubCommand = new SubCommand( 4426 "check-certificate-usability", 4427 INFO_MANAGE_CERTS_SC_CHECK_USABILITY_DESC.get(), checkUsabilityParser, 4428 checkUsabilityExamples); 4429 checkUsabilitySubCommand.addName("checkCertificateUsability", true); 4430 checkUsabilitySubCommand.addName("check-usability", true); 4431 checkUsabilitySubCommand.addName("checkUsability", true); 4432 4433 parser.addSubCommand(checkUsabilitySubCommand); 4434 4435 4436 // Define the "display-certificate-file" subcommand and all of its 4437 // arguments. 4438 final ArgumentParser displayCertParser = new ArgumentParser( 4439 "display-certificate-file", 4440 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_DESC.get()); 4441 4442 final FileArgument displayCertFile = new FileArgument(null, 4443 "certificate-file", true, 1, null, 4444 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_FILE_DESC.get(), true, true, 4445 true, false); 4446 displayCertFile.addLongIdentifier("certificateFile", true); 4447 displayCertFile.addLongIdentifier("input-file", true); 4448 displayCertFile.addLongIdentifier("inputFile", true); 4449 displayCertFile.addLongIdentifier("file", true); 4450 displayCertFile.addLongIdentifier("filename", true); 4451 displayCertParser.addArgument(displayCertFile); 4452 4453 final BooleanArgument displayCertVerbose = new BooleanArgument(null, 4454 "verbose", 1, 4455 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_VERBOSE_DESC.get()); 4456 displayCertParser.addArgument(displayCertVerbose); 4457 4458 final BooleanArgument displayCertDisplayCommand = new BooleanArgument(null, 4459 "display-keytool-command", 1, 4460 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_ARG_DISPLAY_COMMAND_DESC.get()); 4461 displayCertDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 4462 displayCertDisplayCommand.addLongIdentifier("show-keytool-command", true); 4463 displayCertDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 4464 displayCertParser.addArgument(displayCertDisplayCommand); 4465 4466 final LinkedHashMap<String[],String> displayCertExamples = 4467 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 4468 displayCertExamples.put( 4469 new String[] 4470 { 4471 "display-certificate-file", 4472 "--certificate-file", "certificate.pem", 4473 }, 4474 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_EXAMPLE_1.get("certificate.pem")); 4475 displayCertExamples.put( 4476 new String[] 4477 { 4478 "display-certificate-file", 4479 "--certificate-file", "certificate.pem", 4480 "--verbose", 4481 "--display-keytool-command" 4482 }, 4483 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_EXAMPLE_2.get("certificate.pem")); 4484 4485 final SubCommand displayCertSubCommand = new SubCommand( 4486 "display-certificate-file", 4487 INFO_MANAGE_CERTS_SC_DISPLAY_CERT_DESC.get(), displayCertParser, 4488 displayCertExamples); 4489 displayCertSubCommand.addName("displayCertificateFile", true); 4490 displayCertSubCommand.addName("display-certificate", true); 4491 displayCertSubCommand.addName("displayCertificate", true); 4492 displayCertSubCommand.addName("display-certificates", true); 4493 displayCertSubCommand.addName("displayCertificates", true); 4494 displayCertSubCommand.addName("show-certificate", true); 4495 displayCertSubCommand.addName("showCertificate", true); 4496 displayCertSubCommand.addName("show-certificate-file", true); 4497 displayCertSubCommand.addName("showCertificateFile", true); 4498 displayCertSubCommand.addName("show-certificates", true); 4499 displayCertSubCommand.addName("showCertificates", true); 4500 displayCertSubCommand.addName("print-certificate-file", true); 4501 displayCertSubCommand.addName("printCertificateFile", true); 4502 displayCertSubCommand.addName("print-certificate", true); 4503 displayCertSubCommand.addName("printCertificate", true); 4504 displayCertSubCommand.addName("print-certificates", true); 4505 displayCertSubCommand.addName("printCertificates", true); 4506 displayCertSubCommand.addName("printcert", true); 4507 4508 parser.addSubCommand(displayCertSubCommand); 4509 4510 4511 // Define the "display-certificate-signing-request-file" subcommand and all 4512 // of its arguments. 4513 final ArgumentParser displayCSRParser = new ArgumentParser( 4514 "display-certificate-signing-request-file", 4515 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_DESC.get()); 4516 4517 final FileArgument displayCSRFile = new FileArgument(null, 4518 "certificate-signing-request-file", true, 1, null, 4519 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_FILE_DESC.get(), true, true, 4520 true, false); 4521 displayCSRFile.addLongIdentifier("certificateSigningRequestFile", true); 4522 displayCSRFile.addLongIdentifier("request-file", true); 4523 displayCSRFile.addLongIdentifier("requestFile", true); 4524 displayCSRFile.addLongIdentifier("input-file", true); 4525 displayCSRFile.addLongIdentifier("inputFile", true); 4526 displayCSRFile.addLongIdentifier("file", true); 4527 displayCSRFile.addLongIdentifier("filename", true); 4528 displayCSRParser.addArgument(displayCSRFile); 4529 4530 final BooleanArgument displayCSRVerbose = new BooleanArgument(null, 4531 "verbose", 1, 4532 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_VERBOSE_DESC.get()); 4533 displayCSRParser.addArgument(displayCSRVerbose); 4534 4535 final BooleanArgument displayCSRDisplayCommand = new BooleanArgument(null, 4536 "display-keytool-command", 1, 4537 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_ARG_DISPLAY_COMMAND_DESC.get()); 4538 displayCSRDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 4539 displayCSRDisplayCommand.addLongIdentifier("show-keytool-command", true); 4540 displayCSRDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 4541 displayCSRParser.addArgument(displayCSRDisplayCommand); 4542 4543 final LinkedHashMap<String[],String> displayCSRExamples = 4544 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 4545 displayCSRExamples.put( 4546 new String[] 4547 { 4548 "display-certificate-signing-request-file", 4549 "--certificate-signing-request-file", "server-cert.csr", 4550 "--display-keytool-command" 4551 }, 4552 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_EXAMPLE_1.get("server-cert.csr")); 4553 4554 final SubCommand displayCSRSubCommand = new SubCommand( 4555 "display-certificate-signing-request-file", 4556 INFO_MANAGE_CERTS_SC_DISPLAY_CSR_DESC.get(), displayCSRParser, 4557 displayCSRExamples); 4558 displayCSRSubCommand.addName("displayCertificateSigningRequestFile", true); 4559 displayCSRSubCommand.addName("display-certificate-signing-request", true); 4560 displayCSRSubCommand.addName("displayCertificateSigningRequest", true); 4561 displayCSRSubCommand.addName("display-certificate-request-file", true); 4562 displayCSRSubCommand.addName("displayCertificateRequestFile", true); 4563 displayCSRSubCommand.addName("display-certificate-request", true); 4564 displayCSRSubCommand.addName("displayCertificateRequest", true); 4565 displayCSRSubCommand.addName("display-csr-file", true); 4566 displayCSRSubCommand.addName("displayCSRFile", true); 4567 displayCSRSubCommand.addName("display-csr", true); 4568 displayCSRSubCommand.addName("displayCSR", true); 4569 displayCSRSubCommand.addName("show-certificate-signing-request-file", true); 4570 displayCSRSubCommand.addName("showCertificateSigningRequestFile", true); 4571 displayCSRSubCommand.addName("show-certificate-signing-request", true); 4572 displayCSRSubCommand.addName("showCertificateSigningRequest", true); 4573 displayCSRSubCommand.addName("show-certificate-request-file", true); 4574 displayCSRSubCommand.addName("showCertificateRequestFile", true); 4575 displayCSRSubCommand.addName("show-certificate-request", true); 4576 displayCSRSubCommand.addName("showCertificateRequest", true); 4577 displayCSRSubCommand.addName("show-csr-file", true); 4578 displayCSRSubCommand.addName("showCSRFile", true); 4579 displayCSRSubCommand.addName("show-csr", true); 4580 displayCSRSubCommand.addName("showCSR", true); 4581 displayCSRSubCommand.addName("print-certificate-signing-request-file", 4582 true); 4583 displayCSRSubCommand.addName("printCertificateSigningRequestFile", true); 4584 displayCSRSubCommand.addName("print-certificate-signing-request", true); 4585 displayCSRSubCommand.addName("printCertificateSigningRequest", true); 4586 displayCSRSubCommand.addName("print-certificate-request-file", true); 4587 displayCSRSubCommand.addName("printCertificateRequestFile", true); 4588 displayCSRSubCommand.addName("print-certificate-request", true); 4589 displayCSRSubCommand.addName("printCertificateRequest", true); 4590 displayCSRSubCommand.addName("print-csr-file", true); 4591 displayCSRSubCommand.addName("printCSRFile", true); 4592 displayCSRSubCommand.addName("print-csr", true); 4593 displayCSRSubCommand.addName("printCSR", true); 4594 displayCSRSubCommand.addName("printcertreq", true); 4595 4596 parser.addSubCommand(displayCSRSubCommand); 4597 } 4598 4599 4600 4601 /** 4602 * Constructs a platform-specific relative path from the provided elements. 4603 * 4604 * @param pathElements The elements of the path to construct. It must not 4605 * be {@code null} or empty. 4606 * 4607 * @return The constructed path. 4608 */ 4609 @NotNull() 4610 private static String getPlatformSpecificPath( 4611 @NotNull final String... pathElements) 4612 { 4613 final StringBuilder buffer = new StringBuilder(); 4614 for (int i=0; i < pathElements.length; i++) 4615 { 4616 if (i > 0) 4617 { 4618 buffer.append(File.separatorChar); 4619 } 4620 4621 buffer.append(pathElements[i]); 4622 } 4623 4624 return buffer.toString(); 4625 } 4626 4627 4628 4629 /** 4630 * Performs the core set of processing for this tool. 4631 * 4632 * @return A result code that indicates whether the processing completed 4633 * successfully. 4634 */ 4635 @Override() 4636 @NotNull() 4637 public ResultCode doToolProcessing() 4638 { 4639 final SubCommand selectedSubCommand = globalParser.getSelectedSubCommand(); 4640 if (selectedSubCommand == null) 4641 { 4642 // This should never happen. 4643 wrapErr(0, WRAP_COLUMN, ERR_MANAGE_CERTS_NO_SUBCOMMAND.get()); 4644 return ResultCode.PARAM_ERROR; 4645 } 4646 4647 subCommandParser = selectedSubCommand.getArgumentParser(); 4648 4649 if (selectedSubCommand.hasName("list-certificates")) 4650 { 4651 return doListCertificates(); 4652 } 4653 else if (selectedSubCommand.hasName("export-certificate")) 4654 { 4655 return doExportCertificate(); 4656 } 4657 else if (selectedSubCommand.hasName("export-private-key")) 4658 { 4659 return doExportPrivateKey(); 4660 } 4661 else if (selectedSubCommand.hasName("import-certificate")) 4662 { 4663 return doImportCertificate(); 4664 } 4665 else if (selectedSubCommand.hasName("delete-certificate")) 4666 { 4667 return doDeleteCertificate(); 4668 } 4669 else if (selectedSubCommand.hasName("generate-self-signed-certificate")) 4670 { 4671 return doGenerateOrSignCertificateOrCSR(); 4672 } 4673 else if (selectedSubCommand.hasName("generate-certificate-signing-request")) 4674 { 4675 return doGenerateOrSignCertificateOrCSR(); 4676 } 4677 else if (selectedSubCommand.hasName("sign-certificate-signing-request")) 4678 { 4679 return doGenerateOrSignCertificateOrCSR(); 4680 } 4681 else if (selectedSubCommand.hasName("change-certificate-alias")) 4682 { 4683 return doChangeCertificateAlias(); 4684 } 4685 else if (selectedSubCommand.hasName("change-keystore-password")) 4686 { 4687 return doChangeKeystorePassword(); 4688 } 4689 else if (selectedSubCommand.hasName("change-private-key-password")) 4690 { 4691 return doChangePrivateKeyPassword(); 4692 } 4693 else if (selectedSubCommand.hasName("copy-keystore")) 4694 { 4695 return doCopyKeystore(); 4696 } 4697 else if (selectedSubCommand.hasName("retrieve-server-certificate")) 4698 { 4699 return doRetrieveServerCertificate(); 4700 } 4701 else if (selectedSubCommand.hasName("trust-server-certificate")) 4702 { 4703 return doTrustServerCertificate(); 4704 } 4705 else if (selectedSubCommand.hasName("check-certificate-usability")) 4706 { 4707 return doCheckCertificateUsability(); 4708 } 4709 else if (selectedSubCommand.hasName("display-certificate-file")) 4710 { 4711 return doDisplayCertificateFile(); 4712 } 4713 else if (selectedSubCommand.hasName( 4714 "display-certificate-signing-request-file")) 4715 { 4716 return doDisplayCertificateSigningRequestFile(); 4717 } 4718 else 4719 { 4720 // This should never happen. 4721 wrapErr(0, WRAP_COLUMN, 4722 ERR_MANAGE_CERTS_UNKNOWN_SUBCOMMAND.get( 4723 selectedSubCommand.getPrimaryName())); 4724 return ResultCode.PARAM_ERROR; 4725 } 4726 } 4727 4728 4729 4730 /** 4731 * Performs the necessary processing for the list-certificates subcommand. 4732 * 4733 * @return A result code that indicates whether the processing completed 4734 * successfully. 4735 */ 4736 @NotNull() 4737 private ResultCode doListCertificates() 4738 { 4739 // Get the values of a number of configured arguments. 4740 final BooleanArgument displayPEMArgument = 4741 subCommandParser.getBooleanArgument("display-pem-certificate"); 4742 final boolean displayPEM = 4743 ((displayPEMArgument != null) && displayPEMArgument.isPresent()); 4744 4745 final BooleanArgument verboseArgument = 4746 subCommandParser.getBooleanArgument("verbose"); 4747 final boolean verbose = 4748 ((verboseArgument != null) && verboseArgument.isPresent()); 4749 4750 final Map<String,String> missingAliases; 4751 final Set<String> aliases; 4752 final StringArgument aliasArgument = 4753 subCommandParser.getStringArgument("alias"); 4754 if ((aliasArgument == null) || (! aliasArgument.isPresent())) 4755 { 4756 aliases = Collections.emptySet(); 4757 missingAliases = Collections.emptyMap(); 4758 } 4759 else 4760 { 4761 final List<String> values = aliasArgument.getValues(); 4762 aliases = new LinkedHashSet<>(StaticUtils.computeMapCapacity( 4763 values.size())); 4764 missingAliases = 4765 new LinkedHashMap<>(StaticUtils.computeMapCapacity(values.size())); 4766 for (final String alias : values) 4767 { 4768 final String lowerAlias = StaticUtils.toLowerCase(alias); 4769 aliases.add(StaticUtils.toLowerCase(lowerAlias)); 4770 missingAliases.put(lowerAlias, alias); 4771 } 4772 } 4773 4774 final String keystoreType; 4775 final File keystorePath = getKeystorePath(); 4776 try 4777 { 4778 keystoreType = inferKeystoreType(keystorePath); 4779 } 4780 catch (final LDAPException le) 4781 { 4782 Debug.debugException(le); 4783 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4784 return le.getResultCode(); 4785 } 4786 4787 final char[] keystorePassword; 4788 try 4789 { 4790 keystorePassword = getKeystorePassword(keystorePath); 4791 } 4792 catch (final LDAPException le) 4793 { 4794 Debug.debugException(le); 4795 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4796 return le.getResultCode(); 4797 } 4798 4799 final BooleanArgument displayKeytoolCommandArgument = 4800 subCommandParser.getBooleanArgument("display-keytool-command"); 4801 if ((displayKeytoolCommandArgument != null) && 4802 displayKeytoolCommandArgument.isPresent()) 4803 { 4804 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 4805 keytoolArgs.add("-list"); 4806 4807 keytoolArgs.add("-keystore"); 4808 keytoolArgs.add(keystorePath.getAbsolutePath()); 4809 keytoolArgs.add("-storetype"); 4810 keytoolArgs.add(keystoreType); 4811 4812 if (keystorePassword != null) 4813 { 4814 keytoolArgs.add("-storepass"); 4815 keytoolArgs.add("*****REDACTED*****"); 4816 } 4817 4818 for (final String alias : missingAliases.values()) 4819 { 4820 keytoolArgs.add("-alias"); 4821 keytoolArgs.add(alias); 4822 } 4823 4824 if (displayPEM) 4825 { 4826 keytoolArgs.add("-rfc"); 4827 } 4828 4829 if (verbose) 4830 { 4831 keytoolArgs.add("-v"); 4832 } 4833 4834 displayKeytoolCommand(keytoolArgs); 4835 } 4836 4837 4838 // Get the keystore. 4839 final KeyStore keystore; 4840 try 4841 { 4842 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 4843 } 4844 catch (final LDAPException le) 4845 { 4846 Debug.debugException(le); 4847 wrapErr(0, WRAP_COLUMN, le.getMessage()); 4848 return le.getResultCode(); 4849 } 4850 4851 4852 // Display a message with the keystore type. 4853 wrapOut(0, WRAP_COLUMN, 4854 INFO_MANAGE_CERTS_LIST_KEYSTORE_TYPE.get(keystoreType)); 4855 4856 4857 // Iterate through the keystore and display the appropriate certificates. 4858 final Enumeration<String> aliasEnumeration; 4859 try 4860 { 4861 aliasEnumeration = keystore.aliases(); 4862 } 4863 catch (final Exception e) 4864 { 4865 Debug.debugException(e); 4866 err(); 4867 wrapErr(0, WRAP_COLUMN, 4868 ERR_MANAGE_CERTS_LIST_CERTS_CANNOT_GET_ALIASES.get( 4869 keystorePath.getAbsolutePath())); 4870 e.printStackTrace(getErr()); 4871 return ResultCode.LOCAL_ERROR; 4872 } 4873 4874 int listedCount = 0; 4875 ResultCode resultCode = ResultCode.SUCCESS; 4876 while (aliasEnumeration.hasMoreElements()) 4877 { 4878 final String alias = aliasEnumeration.nextElement(); 4879 final String lowerAlias = StaticUtils.toLowerCase(alias); 4880 if ((!aliases.isEmpty()) && (missingAliases.remove(lowerAlias) == null)) 4881 { 4882 // We don't care about this alias. 4883 continue; 4884 } 4885 4886 final X509Certificate[] certificateChain; 4887 try 4888 { 4889 // NOTE: Keystore entries that have private keys may have a certificate 4890 // chain associated with them (the end certificate plus all of the 4891 // issuer certificates). In that case all of those certificates in the 4892 // chain will be stored under the same alias, and the only way we can 4893 // access them is to call the getCertificateChain method. However, if 4894 // the keystore only has a certificate for the alias but no private key, 4895 // then the entry will not have a chain, and the call to 4896 // getCertificateChain will return null for that alias. We want to be 4897 // able to handle both of these cases, so we will first try 4898 // getCertificateChain to see if we can get a complete chain, but if 4899 // that returns null, then use getCertificate to see if we can get a 4900 // single certificate. That call to getCertificate can also return null 4901 // because the entry with this alias might be some other type of entry, 4902 // like a secret key entry. 4903 Certificate[] chain = keystore.getCertificateChain(alias); 4904 if ((chain == null) || (chain.length == 0)) 4905 { 4906 final Certificate cert = keystore.getCertificate(alias); 4907 if (cert == null) 4908 { 4909 continue; 4910 } 4911 else 4912 { 4913 chain = new Certificate[] { cert }; 4914 } 4915 } 4916 4917 certificateChain = new X509Certificate[chain.length]; 4918 for (int i = 0; i < chain.length; i++) 4919 { 4920 certificateChain[i] = new X509Certificate(chain[i].getEncoded()); 4921 } 4922 } 4923 catch (final Exception e) 4924 { 4925 Debug.debugException(e); 4926 err(); 4927 wrapErr(0, WRAP_COLUMN, 4928 ERR_MANAGE_CERTS_LIST_CERTS_ERROR_GETTING_CERT.get(alias, 4929 StaticUtils.getExceptionMessage(e))); 4930 resultCode = ResultCode.LOCAL_ERROR; 4931 continue; 4932 } 4933 4934 listedCount++; 4935 for (int i = 0; i < certificateChain.length; i++) 4936 { 4937 out(); 4938 if (certificateChain.length == 1) 4939 { 4940 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_ALIAS_WITHOUT_CHAIN.get( 4941 alias)); 4942 } 4943 else 4944 { 4945 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_ALIAS_WITH_CHAIN.get(alias, 4946 (i + 1), certificateChain.length)); 4947 } 4948 4949 printCertificate(certificateChain[i], "", verbose); 4950 4951 if (i == 0) 4952 { 4953 if (hasKeyAlias(keystore, alias)) 4954 { 4955 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_HAS_PK_YES.get()); 4956 } 4957 else 4958 { 4959 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_HAS_PK_NO.get()); 4960 } 4961 } 4962 4963 CertException signatureVerificationException = null; 4964 if (certificateChain[i].isSelfSigned()) 4965 { 4966 try 4967 { 4968 certificateChain[i].verifySignature(null); 4969 } 4970 catch (final CertException ce) 4971 { 4972 Debug.debugException(ce); 4973 signatureVerificationException = ce; 4974 } 4975 } 4976 else 4977 { 4978 X509Certificate issuerCertificate = null; 4979 try 4980 { 4981 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 4982 new AtomicReference<>(); 4983 final AtomicReference<DN> missingIssuerRef = 4984 new AtomicReference<>(); 4985 issuerCertificate = getIssuerCertificate(certificateChain[i], 4986 keystore, jvmDefaultTrustStoreRef, missingIssuerRef); 4987 } 4988 catch (final Exception e) 4989 { 4990 Debug.debugException(e); 4991 } 4992 4993 if (issuerCertificate == null) 4994 { 4995 signatureVerificationException = new CertException( 4996 ERR_MANAGE_CERTS_LIST_CERTS_VERIFY_SIGNATURE_NO_ISSUER.get( 4997 certificateChain[i].getIssuerDN())); 4998 } 4999 else 5000 { 5001 try 5002 { 5003 certificateChain[i].verifySignature(issuerCertificate); 5004 } 5005 catch (final CertException ce) 5006 { 5007 Debug.debugException(ce); 5008 signatureVerificationException = ce; 5009 } 5010 } 5011 } 5012 5013 if (signatureVerificationException == null) 5014 { 5015 wrapOut(0, WRAP_COLUMN, 5016 INFO_MANAGE_CERTS_LIST_CERTS_SIGNATURE_VALID.get()); 5017 } 5018 else 5019 { 5020 wrapErr(0, WRAP_COLUMN, 5021 signatureVerificationException.getMessage()); 5022 } 5023 5024 if (displayPEM) 5025 { 5026 out(INFO_MANAGE_CERTS_LIST_CERTS_LABEL_PEM.get()); 5027 writePEMCertificate(getOut(), 5028 certificateChain[i].getX509CertificateBytes()); 5029 } 5030 } 5031 } 5032 5033 if (! missingAliases.isEmpty()) 5034 { 5035 err(); 5036 for (final String missingAlias : missingAliases.values()) 5037 { 5038 wrapErr(0, WRAP_COLUMN, 5039 WARN_MANAGE_CERTS_LIST_CERTS_ALIAS_NOT_IN_KS.get(missingAlias, 5040 keystorePath.getAbsolutePath())); 5041 resultCode = ResultCode.PARAM_ERROR; 5042 } 5043 } 5044 else if (listedCount == 0) 5045 { 5046 out(); 5047 if (keystorePassword == null) 5048 { 5049 wrapOut(0, WRAP_COLUMN, 5050 INFO_MANAGE_CERTS_LIST_CERTS_NO_CERTS_OR_KEYS_WITHOUT_PW.get()); 5051 } 5052 else 5053 { 5054 wrapOut(0, WRAP_COLUMN, 5055 INFO_MANAGE_CERTS_LIST_CERTS_NO_CERTS_OR_KEYS_WITH_PW.get()); 5056 } 5057 } 5058 5059 return resultCode; 5060 } 5061 5062 5063 5064 /** 5065 * Performs the necessary processing for the export-certificate subcommand. 5066 * 5067 * @return A result code that indicates whether the processing completed 5068 * successfully. 5069 */ 5070 @NotNull() 5071 private ResultCode doExportCertificate() 5072 { 5073 // Get the values of a number of configured arguments. 5074 final StringArgument aliasArgument = 5075 subCommandParser.getStringArgument("alias"); 5076 final String alias = aliasArgument.getValue(); 5077 5078 final BooleanArgument exportChainArgument = 5079 subCommandParser.getBooleanArgument("export-certificate-chain"); 5080 final boolean exportChain = 5081 ((exportChainArgument != null) && exportChainArgument.isPresent()); 5082 5083 final BooleanArgument separateFilePerCertificateArgument = 5084 subCommandParser.getBooleanArgument("separate-file-per-certificate"); 5085 final boolean separateFilePerCertificate = 5086 ((separateFilePerCertificateArgument != null) && 5087 separateFilePerCertificateArgument.isPresent()); 5088 5089 boolean exportPEM = true; 5090 final StringArgument outputFormatArgument = 5091 subCommandParser.getStringArgument("output-format"); 5092 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 5093 { 5094 final String format = outputFormatArgument.getValue().toLowerCase(); 5095 if (format.equals("der") || format.equals("binary") || 5096 format.equals("bin")) 5097 { 5098 exportPEM = false; 5099 } 5100 } 5101 5102 File outputFile = null; 5103 final FileArgument outputFileArgument = 5104 subCommandParser.getFileArgument("output-file"); 5105 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 5106 { 5107 outputFile = outputFileArgument.getValue(); 5108 } 5109 5110 if ((outputFile == null) && (! exportPEM)) 5111 { 5112 wrapErr(0, WRAP_COLUMN, 5113 ERR_MANAGE_CERTS_EXPORT_CERT_NO_FILE_WITH_DER.get()); 5114 return ResultCode.PARAM_ERROR; 5115 } 5116 5117 final String keystoreType; 5118 final File keystorePath = getKeystorePath(); 5119 try 5120 { 5121 keystoreType = inferKeystoreType(keystorePath); 5122 } 5123 catch (final LDAPException le) 5124 { 5125 Debug.debugException(le); 5126 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5127 return le.getResultCode(); 5128 } 5129 5130 final char[] keystorePassword; 5131 try 5132 { 5133 keystorePassword = getKeystorePassword(keystorePath); 5134 } 5135 catch (final LDAPException le) 5136 { 5137 Debug.debugException(le); 5138 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5139 return le.getResultCode(); 5140 } 5141 5142 final BooleanArgument displayKeytoolCommandArgument = 5143 subCommandParser.getBooleanArgument("display-keytool-command"); 5144 if ((displayKeytoolCommandArgument != null) && 5145 displayKeytoolCommandArgument.isPresent()) 5146 { 5147 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 5148 keytoolArgs.add("-list"); 5149 5150 keytoolArgs.add("-keystore"); 5151 keytoolArgs.add(keystorePath.getAbsolutePath()); 5152 keytoolArgs.add("-storetype"); 5153 keytoolArgs.add(keystoreType); 5154 5155 if (keystorePassword != null) 5156 { 5157 keytoolArgs.add("-storepass"); 5158 keytoolArgs.add("*****REDACTED*****"); 5159 } 5160 5161 keytoolArgs.add("-alias"); 5162 keytoolArgs.add(alias); 5163 5164 if (exportPEM) 5165 { 5166 keytoolArgs.add("-rfc"); 5167 } 5168 5169 if (outputFile != null) 5170 { 5171 keytoolArgs.add("-file"); 5172 keytoolArgs.add(outputFile.getAbsolutePath()); 5173 } 5174 5175 displayKeytoolCommand(keytoolArgs); 5176 } 5177 5178 5179 // Get the keystore. 5180 final KeyStore keystore; 5181 try 5182 { 5183 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5184 } 5185 catch (final LDAPException le) 5186 { 5187 Debug.debugException(le); 5188 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5189 return le.getResultCode(); 5190 } 5191 5192 5193 // Get the certificates to export. If the --export-certificate-chain 5194 // argument was provided, this can be multiple certificates. Otherwise, it 5195 // there will only be one. 5196 DN missingIssuerDN = null; 5197 final X509Certificate[] certificatesToExport; 5198 if (exportChain) 5199 { 5200 try 5201 { 5202 final AtomicReference<DN> missingIssuerRef = new AtomicReference<>(); 5203 certificatesToExport = 5204 getCertificateChain(alias, keystore, missingIssuerRef); 5205 missingIssuerDN = missingIssuerRef.get(); 5206 } 5207 catch (final LDAPException le) 5208 { 5209 Debug.debugException(le); 5210 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5211 return le.getResultCode(); 5212 } 5213 } 5214 else 5215 { 5216 try 5217 { 5218 final Certificate cert = keystore.getCertificate(alias); 5219 if (cert == null) 5220 { 5221 certificatesToExport = new X509Certificate[0]; 5222 } 5223 else 5224 { 5225 certificatesToExport = new X509Certificate[] 5226 { 5227 new X509Certificate(cert.getEncoded()) 5228 }; 5229 } 5230 } 5231 catch (final Exception e) 5232 { 5233 Debug.debugException(e); 5234 wrapErr(0, WRAP_COLUMN, 5235 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_GETTING_CERT.get(alias, 5236 keystorePath.getAbsolutePath())); 5237 e.printStackTrace(getErr()); 5238 return ResultCode.LOCAL_ERROR; 5239 } 5240 } 5241 5242 if (certificatesToExport.length == 0) 5243 { 5244 wrapErr(0, WRAP_COLUMN, 5245 ERR_MANAGE_CERTS_EXPORT_CERT_NO_CERT_WITH_ALIAS.get(alias, 5246 keystorePath.getAbsolutePath())); 5247 return ResultCode.PARAM_ERROR; 5248 } 5249 5250 5251 // Get a PrintStream to use for the output. 5252 int fileCounter = 1; 5253 String filename = null; 5254 PrintStream printStream; 5255 if (outputFile == null) 5256 { 5257 printStream = getOut(); 5258 } 5259 else 5260 { 5261 try 5262 { 5263 if ((certificatesToExport.length > 1) && separateFilePerCertificate) 5264 { 5265 filename = outputFile.getAbsolutePath() + '.' + fileCounter; 5266 } 5267 else 5268 { 5269 filename = outputFile.getAbsolutePath(); 5270 } 5271 printStream = new PrintStream(filename); 5272 } 5273 catch (final Exception e) 5274 { 5275 Debug.debugException(e); 5276 wrapErr(0, WRAP_COLUMN, 5277 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_OPENING_OUTPUT.get( 5278 outputFile.getAbsolutePath())); 5279 e.printStackTrace(getErr()); 5280 return ResultCode.LOCAL_ERROR; 5281 } 5282 } 5283 5284 try 5285 { 5286 for (final X509Certificate certificate : certificatesToExport) 5287 { 5288 try 5289 { 5290 if (separateFilePerCertificate && (certificatesToExport.length > 1)) 5291 { 5292 if (fileCounter > 1) 5293 { 5294 printStream.close(); 5295 filename = outputFile.getAbsolutePath() + '.' + fileCounter; 5296 printStream = new PrintStream(filename); 5297 } 5298 5299 fileCounter++; 5300 } 5301 5302 if (exportPEM) 5303 { 5304 writePEMCertificate(printStream, 5305 certificate.getX509CertificateBytes()); 5306 } 5307 else 5308 { 5309 printStream.write(certificate.getX509CertificateBytes()); 5310 } 5311 } 5312 catch (final Exception e) 5313 { 5314 Debug.debugException(e); 5315 wrapErr(0, WRAP_COLUMN, 5316 ERR_MANAGE_CERTS_EXPORT_CERT_ERROR_WRITING_CERT.get(alias, 5317 certificate.getSubjectDN())); 5318 e.printStackTrace(getErr()); 5319 return ResultCode.LOCAL_ERROR; 5320 } 5321 5322 if (outputFile != null) 5323 { 5324 out(); 5325 wrapOut(0, WRAP_COLUMN, 5326 INFO_MANAGE_CERTS_EXPORT_CERT_EXPORT_SUCCESSFUL.get(filename)); 5327 printCertificate(certificate, "", false); 5328 } 5329 } 5330 } 5331 finally 5332 { 5333 printStream.flush(); 5334 if (outputFile != null) 5335 { 5336 printStream.close(); 5337 } 5338 } 5339 5340 if (missingIssuerDN != null) 5341 { 5342 err(); 5343 wrapErr(0, WRAP_COLUMN, 5344 WARN_MANAGE_CERTS_EXPORT_CERT_MISSING_CERT_IN_CHAIN.get( 5345 missingIssuerDN, keystorePath.getAbsolutePath())); 5346 return ResultCode.NO_SUCH_OBJECT; 5347 } 5348 5349 return ResultCode.SUCCESS; 5350 } 5351 5352 5353 5354 /** 5355 * Performs the necessary processing for the export-private-key subcommand. 5356 * 5357 * @return A result code that indicates whether the processing completed 5358 * successfully. 5359 */ 5360 @NotNull() 5361 private ResultCode doExportPrivateKey() 5362 { 5363 // Get the values of a number of configured arguments. 5364 final StringArgument aliasArgument = 5365 subCommandParser.getStringArgument("alias"); 5366 final String alias = aliasArgument.getValue(); 5367 5368 boolean exportPEM = true; 5369 final StringArgument outputFormatArgument = 5370 subCommandParser.getStringArgument("output-format"); 5371 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 5372 { 5373 final String format = outputFormatArgument.getValue().toLowerCase(); 5374 if (format.equals("der") || format.equals("binary") || 5375 format.equals("bin")) 5376 { 5377 exportPEM = false; 5378 } 5379 } 5380 5381 File outputFile = null; 5382 final FileArgument outputFileArgument = 5383 subCommandParser.getFileArgument("output-file"); 5384 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 5385 { 5386 outputFile = outputFileArgument.getValue(); 5387 } 5388 5389 if ((outputFile == null) && (! exportPEM)) 5390 { 5391 wrapErr(0, WRAP_COLUMN, 5392 ERR_MANAGE_CERTS_EXPORT_KEY_NO_FILE_WITH_DER.get()); 5393 return ResultCode.PARAM_ERROR; 5394 } 5395 5396 final String keystoreType; 5397 final File keystorePath = getKeystorePath(); 5398 try 5399 { 5400 keystoreType = inferKeystoreType(keystorePath); 5401 } 5402 catch (final LDAPException le) 5403 { 5404 Debug.debugException(le); 5405 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5406 return le.getResultCode(); 5407 } 5408 5409 final char[] keystorePassword; 5410 try 5411 { 5412 keystorePassword = getKeystorePassword(keystorePath); 5413 } 5414 catch (final LDAPException le) 5415 { 5416 Debug.debugException(le); 5417 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5418 return le.getResultCode(); 5419 } 5420 5421 5422 // Get the keystore. 5423 final KeyStore keystore; 5424 try 5425 { 5426 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5427 } 5428 catch (final LDAPException le) 5429 { 5430 Debug.debugException(le); 5431 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5432 return le.getResultCode(); 5433 } 5434 5435 5436 // See if we need to use a private key password that is different from the 5437 // keystore password. 5438 final char[] privateKeyPassword; 5439 try 5440 { 5441 privateKeyPassword = 5442 getPrivateKeyPassword(keystore, alias, keystorePassword); 5443 } 5444 catch (final LDAPException le) 5445 { 5446 Debug.debugException(le); 5447 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5448 return le.getResultCode(); 5449 } 5450 5451 5452 // Get the password to use to encrypt the private key when it is exported. 5453 final char[] encryptionPassword; 5454 try 5455 { 5456 encryptionPassword = getPrivateKeyEncryptionPassword(false); 5457 } 5458 catch (final LDAPException le) 5459 { 5460 Debug.debugException(le); 5461 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5462 return le.getResultCode(); 5463 } 5464 5465 5466 // Get the private key to export. 5467 final PrivateKey privateKey; 5468 try 5469 { 5470 final Key key = keystore.getKey(alias, privateKeyPassword); 5471 if (key == null) 5472 { 5473 wrapErr(0, WRAP_COLUMN, 5474 ERR_MANAGE_CERTS_EXPORT_KEY_NO_KEY_WITH_ALIAS.get(alias, 5475 keystorePath.getAbsolutePath())); 5476 return ResultCode.PARAM_ERROR; 5477 } 5478 5479 privateKey = (PrivateKey) key; 5480 } 5481 catch (final UnrecoverableKeyException e) 5482 { 5483 Debug.debugException(e); 5484 wrapErr(0, WRAP_COLUMN, 5485 ERR_MANAGE_CERTS_EXPORT_KEY_WRONG_KEY_PW.get(alias, 5486 keystorePath.getAbsolutePath())); 5487 return ResultCode.PARAM_ERROR; 5488 } 5489 catch (final Exception e) 5490 { 5491 Debug.debugException(e); 5492 wrapErr(0, WRAP_COLUMN, 5493 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_GETTING_KEY.get(alias, 5494 keystorePath.getAbsolutePath())); 5495 e.printStackTrace(getErr()); 5496 return ResultCode.LOCAL_ERROR; 5497 } 5498 5499 5500 // Get a PrintStream to use for the output. 5501 final PrintStream printStream; 5502 if (outputFile == null) 5503 { 5504 printStream = getOut(); 5505 } 5506 else 5507 { 5508 try 5509 { 5510 printStream = new PrintStream(outputFile); 5511 } 5512 catch (final Exception e) 5513 { 5514 Debug.debugException(e); 5515 wrapErr(0, WRAP_COLUMN, 5516 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_OPENING_OUTPUT.get( 5517 outputFile.getAbsolutePath())); 5518 e.printStackTrace(getErr()); 5519 return ResultCode.LOCAL_ERROR; 5520 } 5521 } 5522 5523 try 5524 { 5525 try 5526 { 5527 if (exportPEM) 5528 { 5529 writePEMPrivateKey(printStream, privateKey.getEncoded(), 5530 encryptionPassword); 5531 } 5532 else 5533 { 5534 if (encryptionPassword == null) 5535 { 5536 printStream.write(privateKey.getEncoded()); 5537 } 5538 else 5539 { 5540 final byte[] encryptedPrivateKey = 5541 PKCS8EncryptionHandler.encryptPrivateKey( 5542 privateKey.getEncoded(), encryptionPassword, 5543 new PKCS8EncryptionProperties()); 5544 printStream.write(encryptedPrivateKey); 5545 } 5546 } 5547 } 5548 catch (final Exception e) 5549 { 5550 Debug.debugException(e); 5551 wrapErr(0, WRAP_COLUMN, 5552 ERR_MANAGE_CERTS_EXPORT_KEY_ERROR_WRITING_KEY.get(alias)); 5553 e.printStackTrace(getErr()); 5554 return ResultCode.LOCAL_ERROR; 5555 } 5556 5557 if (outputFile != null) 5558 { 5559 out(); 5560 wrapOut(0, WRAP_COLUMN, 5561 INFO_MANAGE_CERTS_EXPORT_KEY_EXPORT_SUCCESSFUL.get()); 5562 } 5563 } 5564 finally 5565 { 5566 printStream.flush(); 5567 if (outputFile != null) 5568 { 5569 printStream.close(); 5570 } 5571 } 5572 5573 return ResultCode.SUCCESS; 5574 } 5575 5576 5577 5578 /** 5579 * Performs the necessary processing for the import-certificate subcommand. 5580 * 5581 * @return A result code that indicates whether the processing completed 5582 * successfully. 5583 */ 5584 @NotNull() 5585 private ResultCode doImportCertificate() 5586 { 5587 // Get the values of a number of configured arguments. 5588 final StringArgument aliasArgument = 5589 subCommandParser.getStringArgument("alias"); 5590 final String alias = aliasArgument.getValue(); 5591 5592 final FileArgument certificateFileArgument = 5593 subCommandParser.getFileArgument("certificate-file"); 5594 final List<File> certFiles = certificateFileArgument.getValues(); 5595 5596 final File privateKeyFile; 5597 final FileArgument privateKeyFileArgument = 5598 subCommandParser.getFileArgument("private-key-file"); 5599 if ((privateKeyFileArgument != null) && privateKeyFileArgument.isPresent()) 5600 { 5601 privateKeyFile = privateKeyFileArgument.getValue(); 5602 } 5603 else 5604 { 5605 privateKeyFile = null; 5606 } 5607 5608 final BooleanArgument noPromptArgument = 5609 subCommandParser.getBooleanArgument("no-prompt"); 5610 final boolean noPrompt = 5611 ((noPromptArgument != null) && noPromptArgument.isPresent()); 5612 5613 final String keystoreType; 5614 final File keystorePath = getKeystorePath(); 5615 final boolean isNewKeystore = (! keystorePath.exists()); 5616 try 5617 { 5618 keystoreType = inferKeystoreType(keystorePath); 5619 } 5620 catch (final LDAPException le) 5621 { 5622 Debug.debugException(le); 5623 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5624 return le.getResultCode(); 5625 } 5626 5627 5628 final char[] keystorePassword; 5629 try 5630 { 5631 keystorePassword = getKeystorePassword(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 // Read the contents of the certificate files. 5642 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 5643 for (final File certFile : certFiles) 5644 { 5645 try 5646 { 5647 final List<X509Certificate> certs = readCertificatesFromFile(certFile); 5648 if (certs.isEmpty()) 5649 { 5650 wrapErr(0, WRAP_COLUMN, 5651 ERR_MANAGE_CERTS_IMPORT_CERT_NO_CERTS_IN_FILE.get( 5652 certFile.getAbsolutePath())); 5653 return ResultCode.PARAM_ERROR; 5654 } 5655 5656 certList.addAll(certs); 5657 } 5658 catch (final LDAPException le) 5659 { 5660 Debug.debugException(le); 5661 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5662 return le.getResultCode(); 5663 } 5664 } 5665 5666 5667 // See if there is a password to use to decrypt the private key that is 5668 // being imported. 5669 final char[] encryptionPassword; 5670 try 5671 { 5672 encryptionPassword = getPrivateKeyEncryptionPassword(true); 5673 } 5674 catch (final LDAPException le) 5675 { 5676 Debug.debugException(le); 5677 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5678 return le.getResultCode(); 5679 } 5680 5681 5682 // If a private key file was specified, then read the private key. 5683 final PKCS8PrivateKey privateKey; 5684 if (privateKeyFile == null) 5685 { 5686 privateKey = null; 5687 } 5688 else 5689 { 5690 try 5691 { 5692 privateKey = readPrivateKeyFromFile(privateKeyFile, encryptionPassword); 5693 } 5694 catch (final LDAPException le) 5695 { 5696 Debug.debugException(le); 5697 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5698 return le.getResultCode(); 5699 } 5700 } 5701 5702 5703 // Get the keystore. 5704 final KeyStore keystore; 5705 try 5706 { 5707 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 5708 } 5709 catch (final LDAPException le) 5710 { 5711 Debug.debugException(le); 5712 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5713 return le.getResultCode(); 5714 } 5715 5716 5717 // If there is a private key, then see if we need to use a private key 5718 // password that is different from the keystore password. 5719 final char[] privateKeyPassword; 5720 try 5721 { 5722 privateKeyPassword = 5723 getPrivateKeyPassword(keystore, alias, keystorePassword); 5724 } 5725 catch (final LDAPException le) 5726 { 5727 Debug.debugException(le); 5728 wrapErr(0, WRAP_COLUMN, le.getMessage()); 5729 return le.getResultCode(); 5730 } 5731 5732 5733 // If we should display an equivalent keytool command, then do that now. 5734 final BooleanArgument displayKeytoolCommandArgument = 5735 subCommandParser.getBooleanArgument("display-keytool-command"); 5736 if ((displayKeytoolCommandArgument != null) && 5737 displayKeytoolCommandArgument.isPresent()) 5738 { 5739 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 5740 keytoolArgs.add("-import"); 5741 5742 keytoolArgs.add("-keystore"); 5743 keytoolArgs.add(keystorePath.getAbsolutePath()); 5744 keytoolArgs.add("-storetype"); 5745 keytoolArgs.add(keystoreType); 5746 keytoolArgs.add("-storepass"); 5747 keytoolArgs.add("*****REDACTED*****"); 5748 keytoolArgs.add("-keypass"); 5749 keytoolArgs.add("*****REDACTED*****"); 5750 keytoolArgs.add("-alias"); 5751 keytoolArgs.add(alias); 5752 keytoolArgs.add("-file"); 5753 keytoolArgs.add(certFiles.get(0).getAbsolutePath()); 5754 keytoolArgs.add("-trustcacerts"); 5755 5756 displayKeytoolCommand(keytoolArgs); 5757 } 5758 5759 5760 // Look at all the certificates to be imported. Make sure that every 5761 // subsequent certificate in the chain is the issuer for the previous. 5762 final Iterator<X509Certificate> certIterator = certList.iterator(); 5763 X509Certificate subjectCert = certIterator.next(); 5764 while (true) 5765 { 5766 if (subjectCert.isSelfSigned()) 5767 { 5768 if (certIterator.hasNext()) 5769 { 5770 wrapErr(0, WRAP_COLUMN, 5771 ERR_MANAGE_CERTS_IMPORT_CERT_SELF_SIGNED_NOT_LAST.get( 5772 subjectCert.getSubjectDN())); 5773 return ResultCode.PARAM_ERROR; 5774 } 5775 } 5776 5777 if (! certIterator.hasNext()) 5778 { 5779 break; 5780 } 5781 5782 final X509Certificate issuerCert = certIterator.next(); 5783 final StringBuilder notIssuerReason = new StringBuilder(); 5784 if (! issuerCert.isIssuerFor(subjectCert, notIssuerReason)) 5785 { 5786 // In some cases, the process of signing a certificate can put two 5787 // certificates in the output file (both the signed certificate and its 5788 // issuer. If the same certificate is in the chain twice, then we'll 5789 // silently ignore it. 5790 if (Arrays.equals(issuerCert.getX509CertificateBytes(), 5791 subjectCert.getX509CertificateBytes())) 5792 { 5793 certIterator.remove(); 5794 } 5795 else 5796 { 5797 wrapErr(0, WRAP_COLUMN, 5798 ERR_MANAGE_CERTS_IMPORT_CERT_NEXT_NOT_ISSUER_OF_PREV.get( 5799 notIssuerReason.toString())); 5800 return ResultCode.PARAM_ERROR; 5801 } 5802 } 5803 5804 subjectCert = issuerCert; 5805 } 5806 5807 5808 // If the last certificate in the chain is not self-signed, then make sure 5809 // that we can complete the chain using other certificates in the keystore 5810 // or in the JVM's set of default trusted issuers. If we can't complete 5811 // the chain, then that's an error, although we'll go ahead and proceed 5812 // anyway with the import if we're not also importing a private key. 5813 final ArrayList<X509Certificate> chain; 5814 if (certList.get(certList.size() - 1).isSelfSigned()) 5815 { 5816 chain = certList; 5817 } 5818 else 5819 { 5820 chain = new ArrayList<>(certList.size() + 5); 5821 chain.addAll(certList); 5822 5823 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 5824 new AtomicReference<>(); 5825 final AtomicReference<DN> missingIssuerRef = new AtomicReference<>(); 5826 5827 X509Certificate c = certList.get(certList.size() - 1); 5828 while (! c.isSelfSigned()) 5829 { 5830 final X509Certificate issuer; 5831 try 5832 { 5833 issuer = getIssuerCertificate(c, keystore, jvmDefaultTrustStoreRef, 5834 missingIssuerRef); 5835 } 5836 catch (final Exception e) 5837 { 5838 Debug.debugException(e); 5839 wrapErr(0, WRAP_COLUMN, 5840 ERR_MANAGE_CERTS_IMPORT_CERT_CANNOT_GET_ISSUER.get( 5841 c.getIssuerDN())); 5842 e.printStackTrace(getErr()); 5843 return ResultCode.LOCAL_ERROR; 5844 } 5845 5846 if (issuer == null) 5847 { 5848 final byte[] authorityKeyIdentifier = getAuthorityKeyIdentifier(c); 5849 5850 // We couldn't find the issuer certificate. If we're importing a 5851 // private key, or if the keystore already has a key entry with the 5852 // same alias that we're going to use, then this is definitely an 5853 // error because we can only write a key entry if we have a complete 5854 // certificate chain. 5855 // 5856 // If we weren't explicitly provided with a private key, then it's 5857 // still an undesirable thing to import a certificate without having 5858 // the complete set of issuers, but we'll go ahead and let it slide 5859 // with just a warning. 5860 if ((privateKey != null) || hasKeyAlias(keystore, alias)) 5861 { 5862 if (authorityKeyIdentifier == null) 5863 { 5864 err(); 5865 wrapErr(0, WRAP_COLUMN, 5866 ERR_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_NO_AKI.get( 5867 c.getIssuerDN())); 5868 } 5869 else 5870 { 5871 err(); 5872 wrapErr(0, WRAP_COLUMN, 5873 ERR_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_WITH_AKI.get( 5874 c.getIssuerDN(), 5875 toColonDelimitedHex(authorityKeyIdentifier))); 5876 } 5877 5878 return ResultCode.PARAM_ERROR; 5879 } 5880 else 5881 { 5882 if (authorityKeyIdentifier == null) 5883 { 5884 err(); 5885 wrapErr(0, WRAP_COLUMN, 5886 WARN_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_NO_AKI.get( 5887 c.getIssuerDN())); 5888 } 5889 else 5890 { 5891 err(); 5892 wrapErr(0, WRAP_COLUMN, 5893 WARN_MANAGE_CERTS_IMPORT_CERT_NO_ISSUER_WITH_AKI.get( 5894 c.getIssuerDN(), 5895 toColonDelimitedHex(authorityKeyIdentifier))); 5896 } 5897 5898 break; 5899 } 5900 } 5901 else 5902 { 5903 chain.add(issuer); 5904 c = issuer; 5905 } 5906 } 5907 } 5908 5909 5910 // If we're going to import a private key with a certificate chain, then 5911 // perform the necessary validation and do the import. 5912 if (privateKey != null) 5913 { 5914 // Make sure that the keystore doesn't already have a key or certificate 5915 // with the specified alias. 5916 if (hasKeyAlias(keystore, alias)) 5917 { 5918 wrapErr(0, WRAP_COLUMN, 5919 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_PK_KEY_ALIAS_CONFLICT.get( 5920 alias)); 5921 return ResultCode.PARAM_ERROR; 5922 } 5923 else if (hasCertificateAlias(keystore, alias)) 5924 { 5925 wrapErr(0, WRAP_COLUMN, 5926 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_PK_CERT_ALIAS_CONFLICT.get( 5927 alias)); 5928 return ResultCode.PARAM_ERROR; 5929 } 5930 5931 5932 // Make sure that the private key has a key algorithm of either RSA or EC, 5933 // and convert it into a Java PrivateKey object. 5934 final PrivateKey javaPrivateKey; 5935 try 5936 { 5937 javaPrivateKey = privateKey.toPrivateKey(); 5938 } 5939 catch (final Exception e) 5940 { 5941 Debug.debugException(e); 5942 wrapErr(0, WRAP_COLUMN, 5943 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_KEY.get( 5944 privateKeyFile.getAbsolutePath())); 5945 e.printStackTrace(getErr()); 5946 return ResultCode.LOCAL_ERROR; 5947 } 5948 5949 5950 // Convert the certificate chain into a Java Certificate[]. 5951 final Certificate[] javaCertificateChain = new Certificate[chain.size()]; 5952 for (int i=0; i < javaCertificateChain.length; i++) 5953 { 5954 final X509Certificate c = chain.get(i); 5955 try 5956 { 5957 javaCertificateChain[i] = c.toCertificate(); 5958 } 5959 catch (final Exception e) 5960 { 5961 Debug.debugException(e); 5962 wrapErr(0, WRAP_COLUMN, 5963 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 5964 c.getSubjectDN())); 5965 e.printStackTrace(getErr()); 5966 return ResultCode.LOCAL_ERROR; 5967 } 5968 } 5969 5970 5971 // Prompt the user to confirm the import, if appropriate. 5972 if (! noPrompt) 5973 { 5974 out(); 5975 wrapOut(0, WRAP_COLUMN, 5976 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_NEW_KEY.get( 5977 alias)); 5978 5979 for (final X509Certificate c : chain) 5980 { 5981 out(); 5982 printCertificate(c, "", false); 5983 } 5984 5985 out(); 5986 5987 try 5988 { 5989 if (! promptForYesNo( 5990 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 5991 { 5992 wrapErr(0, WRAP_COLUMN, 5993 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 5994 return ResultCode.USER_CANCELED; 5995 } 5996 } 5997 catch (final LDAPException le) 5998 { 5999 Debug.debugException(le); 6000 err(); 6001 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6002 return le.getResultCode(); 6003 } 6004 } 6005 6006 6007 // Set the private key entry in the keystore. 6008 try 6009 { 6010 keystore.setKeyEntry(alias, javaPrivateKey, privateKeyPassword, 6011 javaCertificateChain); 6012 } 6013 catch (final Exception e) 6014 { 6015 Debug.debugException(e); 6016 wrapErr(0, WRAP_COLUMN, 6017 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CHAIN.get( 6018 alias)); 6019 e.printStackTrace(getErr()); 6020 return ResultCode.LOCAL_ERROR; 6021 } 6022 6023 6024 // Write the updated keystore to disk. 6025 try 6026 { 6027 writeKeystore(keystore, keystorePath, keystorePassword); 6028 } 6029 catch (final LDAPException le) 6030 { 6031 Debug.debugException(le); 6032 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6033 return le.getResultCode(); 6034 } 6035 6036 if (isNewKeystore) 6037 { 6038 out(); 6039 wrapOut(0, WRAP_COLUMN, 6040 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6041 getUserFriendlyKeystoreType(keystoreType))); 6042 } 6043 6044 out(); 6045 wrapOut(0, WRAP_COLUMN, 6046 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITH_PK.get()); 6047 return ResultCode.SUCCESS; 6048 } 6049 6050 6051 // If we've gotten here, then we were given one or more certificates but no 6052 // private key. See if the keystore already has a certificate entry with 6053 // the specified alias. If so, then that's always an error. 6054 if (hasCertificateAlias(keystore, alias)) 6055 { 6056 wrapErr(0, WRAP_COLUMN, 6057 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_CONFLICTING_CERT_ALIAS.get(alias)); 6058 return ResultCode.PARAM_ERROR; 6059 } 6060 6061 6062 // See if the keystore already has a key entry with the specified alias. 6063 // If so, then it may or may not be an error. This can happen if we 6064 // generated a certificate signing request from an existing key pair, and 6065 // now want to import the signed certificate. If that is the case, then we 6066 // will replace the existing key entry with a new one that contains the full 6067 // new certificate chain and the existing private key, but only if the 6068 // new certificate uses the same public key as the certificate at the head 6069 // of the existing chain in that alias. 6070 if (hasKeyAlias(keystore, alias)) 6071 { 6072 // Make sure that the existing key pair uses the same public key as the 6073 // new certificate we are importing. 6074 final PrivateKey existingPrivateKey; 6075 final Certificate[] existingChain; 6076 final X509Certificate existingEndCertificate; 6077 try 6078 { 6079 existingPrivateKey = 6080 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 6081 existingChain = keystore.getCertificateChain(alias); 6082 existingEndCertificate = 6083 new X509Certificate(existingChain[0].getEncoded()); 6084 } 6085 catch (final Exception e) 6086 { 6087 Debug.debugException(e); 6088 wrapErr(0, WRAP_COLUMN, 6089 ERR_MANAGE_CERTS_IMPORT_CERT_INTO_KEY_ALIAS_CANNOT_GET_KEY.get( 6090 alias)); 6091 e.printStackTrace(getErr()); 6092 return ResultCode.LOCAL_ERROR; 6093 } 6094 6095 final boolean[] existingPublicKeyBits = 6096 existingEndCertificate.getEncodedPublicKey().getBits(); 6097 final boolean[] newPublicKeyBits = 6098 chain.get(0).getEncodedPublicKey().getBits(); 6099 if (! Arrays.equals(existingPublicKeyBits, newPublicKeyBits)) 6100 { 6101 wrapErr(0, WRAP_COLUMN, 6102 ERR_MANAGE_CERTS_IMPORT_CERT_INTO_KEY_ALIAS_KEY_MISMATCH.get( 6103 alias)); 6104 return ResultCode.PARAM_ERROR; 6105 } 6106 6107 6108 // Prepare the new certificate chain to store in the alias. 6109 final Certificate[] newChain = new Certificate[chain.size()]; 6110 for (int i=0; i < chain.size(); i++) 6111 { 6112 final X509Certificate c = chain.get(i); 6113 try 6114 { 6115 newChain[i] = c.toCertificate(); 6116 } 6117 catch (final Exception e) 6118 { 6119 Debug.debugException(e); 6120 wrapErr(0, WRAP_COLUMN, 6121 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 6122 c.getSubjectDN())); 6123 e.printStackTrace(getErr()); 6124 return ResultCode.LOCAL_ERROR; 6125 } 6126 } 6127 6128 6129 // Prompt the user to confirm the import, if appropriate. 6130 if (! noPrompt) 6131 { 6132 out(); 6133 wrapOut(0, WRAP_COLUMN, 6134 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_EXISTING_KEY. 6135 get(alias)); 6136 6137 for (final X509Certificate c : chain) 6138 { 6139 out(); 6140 printCertificate(c, "", false); 6141 } 6142 6143 out(); 6144 6145 try 6146 { 6147 if (! promptForYesNo( 6148 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 6149 { 6150 wrapErr(0, WRAP_COLUMN, 6151 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 6152 return ResultCode.USER_CANCELED; 6153 } 6154 } 6155 catch (final LDAPException le) 6156 { 6157 Debug.debugException(le); 6158 err(); 6159 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6160 return le.getResultCode(); 6161 } 6162 } 6163 6164 6165 // Set the private key entry in the keystore. 6166 try 6167 { 6168 keystore.setKeyEntry(alias, existingPrivateKey, privateKeyPassword, 6169 newChain); 6170 } 6171 catch (final Exception e) 6172 { 6173 Debug.debugException(e); 6174 wrapErr(0, WRAP_COLUMN, 6175 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CHAIN.get( 6176 alias)); 6177 e.printStackTrace(getErr()); 6178 return ResultCode.LOCAL_ERROR; 6179 } 6180 6181 6182 // Write the updated keystore to disk. 6183 try 6184 { 6185 writeKeystore(keystore, keystorePath, keystorePassword); 6186 } 6187 catch (final LDAPException le) 6188 { 6189 Debug.debugException(le); 6190 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6191 return le.getResultCode(); 6192 } 6193 6194 out(); 6195 6196 if (isNewKeystore) 6197 { 6198 wrapOut(0, WRAP_COLUMN, 6199 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6200 getUserFriendlyKeystoreType(keystoreType))); 6201 } 6202 6203 wrapOut(0, WRAP_COLUMN, 6204 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITHOUT_PK.get()); 6205 return ResultCode.SUCCESS; 6206 } 6207 6208 6209 // If we've gotten here, then we know that we're just going to add 6210 // certificate entries to the keystore. Iterate through the certificates 6211 // and add them to the keystore under the appropriate aliases, first making 6212 // sure that the alias isn't already in use. 6213 final LinkedHashMap<String,X509Certificate> certMap = 6214 new LinkedHashMap<>(StaticUtils.computeMapCapacity(certList.size())); 6215 for (int i=0; i < certList.size(); i++) 6216 { 6217 final X509Certificate x509Certificate = certList.get(i); 6218 final Certificate javaCertificate; 6219 try 6220 { 6221 javaCertificate = x509Certificate.toCertificate(); 6222 } 6223 catch (final Exception e) 6224 { 6225 Debug.debugException(e); 6226 wrapErr(0, WRAP_COLUMN, 6227 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_CONVERTING_CERT.get( 6228 x509Certificate.getSubjectDN())); 6229 e.printStackTrace(getErr()); 6230 return ResultCode.LOCAL_ERROR; 6231 } 6232 6233 final String certAlias; 6234 if (i == 0) 6235 { 6236 certAlias = alias; 6237 } 6238 else if (certList.size() > 2) 6239 { 6240 certAlias = alias + "-issuer-" + i; 6241 } 6242 else 6243 { 6244 certAlias = alias + "-issuer"; 6245 } 6246 6247 certMap.put(certAlias, x509Certificate); 6248 6249 if (hasKeyAlias(keystore, certAlias) || 6250 hasCertificateAlias(keystore, certAlias)) 6251 { 6252 wrapErr(0, WRAP_COLUMN, 6253 ERR_MANAGE_CERTS_IMPORT_CERT_WITH_CONFLICTING_ISSUER_ALIAS.get( 6254 x509Certificate.getSubjectDN(), certAlias)); 6255 return ResultCode.PARAM_ERROR; 6256 } 6257 6258 try 6259 { 6260 keystore.setCertificateEntry(certAlias, javaCertificate); 6261 } 6262 catch (final Exception e) 6263 { 6264 Debug.debugException(e); 6265 wrapErr(0, WRAP_COLUMN, 6266 ERR_MANAGE_CERTS_IMPORT_CERT_ERROR_UPDATING_KS_WITH_CERT.get( 6267 x509Certificate.getSubjectDN(), alias)); 6268 e.printStackTrace(getErr()); 6269 return ResultCode.LOCAL_ERROR; 6270 } 6271 } 6272 6273 6274 // Prompt about whether to perform the import, if appropriate. 6275 if (! noPrompt) 6276 { 6277 out(); 6278 wrapOut(0, WRAP_COLUMN, 6279 INFO_MANAGE_CERTS_IMPORT_CERT_CONFIRM_IMPORT_CHAIN_NO_KEY. 6280 get(alias)); 6281 6282 for (final Map.Entry<String,X509Certificate> e : certMap.entrySet()) 6283 { 6284 out(); 6285 wrapOut(0, WRAP_COLUMN, 6286 INFO_MANAGE_CERTS_IMPORT_CERT_LABEL_ALIAS.get(e.getKey())); 6287 printCertificate(e.getValue(), "", false); 6288 } 6289 6290 out(); 6291 6292 try 6293 { 6294 if (! promptForYesNo( 6295 INFO_MANAGE_CERTS_IMPORT_CERT_PROMPT_IMPORT_CHAIN.get())) 6296 { 6297 wrapErr(0, WRAP_COLUMN, 6298 ERR_MANAGE_CERTS_IMPORT_CERT_CANCELED.get()); 6299 return ResultCode.USER_CANCELED; 6300 } 6301 } 6302 catch (final LDAPException le) 6303 { 6304 Debug.debugException(le); 6305 err(); 6306 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6307 return le.getResultCode(); 6308 } 6309 } 6310 6311 6312 // Write the updated keystore to disk. 6313 try 6314 { 6315 writeKeystore(keystore, keystorePath, keystorePassword); 6316 } 6317 catch (final LDAPException le) 6318 { 6319 Debug.debugException(le); 6320 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6321 return le.getResultCode(); 6322 } 6323 6324 out(); 6325 6326 if (isNewKeystore) 6327 { 6328 wrapOut(0, WRAP_COLUMN, 6329 INFO_MANAGE_CERTS_IMPORT_CERT_CREATED_KEYSTORE.get( 6330 getUserFriendlyKeystoreType(keystoreType))); 6331 } 6332 6333 wrapOut(0, WRAP_COLUMN, 6334 INFO_MANAGE_CERTS_IMPORT_CERT_IMPORTED_CHAIN_WITHOUT_PK.get()); 6335 return ResultCode.SUCCESS; 6336 } 6337 6338 6339 6340 /** 6341 * Performs the necessary processing for the delete-certificate subcommand. 6342 * 6343 * @return A result code that indicates whether the processing completed 6344 * successfully. 6345 */ 6346 @NotNull() 6347 private ResultCode doDeleteCertificate() 6348 { 6349 // Get the values of a number of configured arguments. 6350 final StringArgument aliasArgument = 6351 subCommandParser.getStringArgument("alias"); 6352 final String alias = aliasArgument.getValue(); 6353 6354 final BooleanArgument noPromptArgument = 6355 subCommandParser.getBooleanArgument("no-prompt"); 6356 final boolean noPrompt = 6357 ((noPromptArgument != null) && noPromptArgument.isPresent()); 6358 6359 final String keystoreType; 6360 final File keystorePath = getKeystorePath(); 6361 try 6362 { 6363 keystoreType = inferKeystoreType(keystorePath); 6364 } 6365 catch (final LDAPException le) 6366 { 6367 Debug.debugException(le); 6368 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6369 return le.getResultCode(); 6370 } 6371 6372 final char[] keystorePassword; 6373 try 6374 { 6375 keystorePassword = getKeystorePassword(keystorePath); 6376 } 6377 catch (final LDAPException le) 6378 { 6379 Debug.debugException(le); 6380 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6381 return le.getResultCode(); 6382 } 6383 6384 final BooleanArgument displayKeytoolCommandArgument = 6385 subCommandParser.getBooleanArgument("display-keytool-command"); 6386 if ((displayKeytoolCommandArgument != null) && 6387 displayKeytoolCommandArgument.isPresent()) 6388 { 6389 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 6390 keytoolArgs.add("-delete"); 6391 6392 keytoolArgs.add("-keystore"); 6393 keytoolArgs.add(keystorePath.getAbsolutePath()); 6394 keytoolArgs.add("-storetype"); 6395 keytoolArgs.add(keystoreType); 6396 keytoolArgs.add("-storepass"); 6397 keytoolArgs.add("*****REDACTED*****"); 6398 keytoolArgs.add("-alias"); 6399 keytoolArgs.add(alias); 6400 6401 displayKeytoolCommand(keytoolArgs); 6402 } 6403 6404 6405 // Get the keystore. 6406 final KeyStore keystore; 6407 try 6408 { 6409 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 6410 } 6411 catch (final LDAPException le) 6412 { 6413 Debug.debugException(le); 6414 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6415 return le.getResultCode(); 6416 } 6417 6418 6419 // Get the entry for the specified alias. 6420 final boolean hasPrivateKey; 6421 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 6422 if (hasCertificateAlias(keystore, alias)) 6423 { 6424 try 6425 { 6426 hasPrivateKey = false; 6427 certList.add( 6428 new X509Certificate(keystore.getCertificate(alias).getEncoded())); 6429 } 6430 catch (final Exception e) 6431 { 6432 Debug.debugException(e); 6433 wrapErr(0, WRAP_COLUMN, 6434 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_GETTING_CERT.get(alias)); 6435 e.printStackTrace(getErr()); 6436 return ResultCode.LOCAL_ERROR; 6437 } 6438 } 6439 else if (hasKeyAlias(keystore, alias)) 6440 { 6441 try 6442 { 6443 hasPrivateKey = true; 6444 for (final Certificate c : keystore.getCertificateChain(alias)) 6445 { 6446 certList.add(new X509Certificate(c.getEncoded())); 6447 } 6448 } 6449 catch (final Exception e) 6450 { 6451 Debug.debugException(e); 6452 wrapErr(0, WRAP_COLUMN, 6453 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_GETTING_CHAIN.get(alias)); 6454 e.printStackTrace(getErr()); 6455 return ResultCode.LOCAL_ERROR; 6456 } 6457 } 6458 else 6459 { 6460 wrapErr(0, WRAP_COLUMN, 6461 ERR_MANAGE_CERTS_DELETE_CERT_ERROR_ALIAS_NOT_CERT_OR_KEY.get(alias)); 6462 return ResultCode.PARAM_ERROR; 6463 } 6464 6465 6466 // Prompt about whether to perform the delete, if appropriate. 6467 if (! noPrompt) 6468 { 6469 out(); 6470 if (! hasPrivateKey) 6471 { 6472 wrapOut(0, WRAP_COLUMN, 6473 INFO_MANAGE_CERTS_DELETE_CERT_CONFIRM_DELETE_CERT.get()); 6474 } 6475 else 6476 { 6477 wrapOut(0, WRAP_COLUMN, 6478 INFO_MANAGE_CERTS_DELETE_CERT_CONFIRM_DELETE_CHAIN.get()); 6479 } 6480 6481 for (final X509Certificate c : certList) 6482 { 6483 out(); 6484 printCertificate(c, "", false); 6485 } 6486 6487 out(); 6488 6489 try 6490 { 6491 if (! promptForYesNo( 6492 INFO_MANAGE_CERTS_DELETE_CERT_PROMPT_DELETE.get())) 6493 { 6494 wrapErr(0, WRAP_COLUMN, 6495 ERR_MANAGE_CERTS_DELETE_CERT_CANCELED.get()); 6496 return ResultCode.USER_CANCELED; 6497 } 6498 } 6499 catch (final LDAPException le) 6500 { 6501 Debug.debugException(le); 6502 err(); 6503 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6504 return le.getResultCode(); 6505 } 6506 } 6507 6508 6509 // Delete the entry from the keystore. 6510 try 6511 { 6512 keystore.deleteEntry(alias); 6513 } 6514 catch (final Exception e) 6515 { 6516 Debug.debugException(e); 6517 wrapErr(0, WRAP_COLUMN, 6518 ERR_MANAGE_CERTS_DELETE_CERT_DELETE_ERROR.get(alias)); 6519 e.printStackTrace(getErr()); 6520 return ResultCode.LOCAL_ERROR; 6521 } 6522 6523 6524 // Write the updated keystore to disk. 6525 try 6526 { 6527 writeKeystore(keystore, keystorePath, keystorePassword); 6528 } 6529 catch (final LDAPException le) 6530 { 6531 Debug.debugException(le); 6532 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6533 return le.getResultCode(); 6534 } 6535 6536 if (certList.size() == 1) 6537 { 6538 out(); 6539 wrapOut(0, WRAP_COLUMN, 6540 INFO_MANAGE_CERTS_DELETE_CERT_DELETED_CERT.get()); 6541 } 6542 else 6543 { 6544 out(); 6545 wrapOut(0, WRAP_COLUMN, 6546 INFO_MANAGE_CERTS_DELETE_CERT_DELETED_CHAIN.get()); 6547 } 6548 6549 return ResultCode.SUCCESS; 6550 } 6551 6552 6553 6554 /** 6555 * Performs the necessary processing for the generate-self-signed-certificate, 6556 * generate-certificate-signing-request, and sign-certificate-signing-request 6557 * subcommands. 6558 * 6559 * @return A result code that indicates whether the processing completed 6560 * successfully. 6561 */ 6562 @NotNull() 6563 private ResultCode doGenerateOrSignCertificateOrCSR() 6564 { 6565 // Figure out which subcommand we're processing. 6566 final boolean isGenerateCertificate; 6567 final boolean isGenerateCSR; 6568 final boolean isSignCSR; 6569 final SubCommand selectedSubCommand = globalParser.getSelectedSubCommand(); 6570 if (selectedSubCommand.hasName("generate-self-signed-certificate")) 6571 { 6572 isGenerateCertificate = true; 6573 isGenerateCSR = false; 6574 isSignCSR = false; 6575 } 6576 else if (selectedSubCommand.hasName("generate-certificate-signing-request")) 6577 { 6578 isGenerateCertificate = false; 6579 isGenerateCSR = true; 6580 isSignCSR = false; 6581 } 6582 else 6583 { 6584 Validator.ensureTrue( 6585 selectedSubCommand.hasName("sign-certificate-signing-request")); 6586 isGenerateCertificate = false; 6587 isGenerateCSR = false; 6588 isSignCSR = true; 6589 } 6590 6591 6592 // Get the values of a number of configured arguments. 6593 final StringArgument aliasArgument = 6594 subCommandParser.getStringArgument("alias"); 6595 final String alias = aliasArgument.getValue(); 6596 6597 final File keystorePath = getKeystorePath(); 6598 final boolean isNewKeystore = (! keystorePath.exists()); 6599 6600 DN subjectDN = null; 6601 final DNArgument subjectDNArgument = 6602 subCommandParser.getDNArgument("subject-dn"); 6603 if ((subjectDNArgument != null) && subjectDNArgument.isPresent()) 6604 { 6605 subjectDN = subjectDNArgument.getValue(); 6606 } 6607 6608 File inputFile = null; 6609 final FileArgument inputFileArgument = 6610 subCommandParser.getFileArgument("input-file"); 6611 if ((inputFileArgument != null) && inputFileArgument.isPresent()) 6612 { 6613 inputFile = inputFileArgument.getValue(); 6614 } 6615 6616 File outputFile = null; 6617 final FileArgument outputFileArgument = 6618 subCommandParser.getFileArgument("output-file"); 6619 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 6620 { 6621 outputFile = outputFileArgument.getValue(); 6622 } 6623 6624 boolean outputPEM = true; 6625 final StringArgument outputFormatArgument = 6626 subCommandParser.getStringArgument("output-format"); 6627 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 6628 { 6629 final String format = outputFormatArgument.getValue().toLowerCase(); 6630 if (format.equals("der") || format.equals("binary") || 6631 format.equals("bin")) 6632 { 6633 outputPEM = false; 6634 } 6635 } 6636 6637 if ((! outputPEM) && (outputFile == null)) 6638 { 6639 wrapErr(0, WRAP_COLUMN, 6640 ERR_MANAGE_CERTS_GEN_CERT_NO_FILE_WITH_DER.get()); 6641 return ResultCode.PARAM_ERROR; 6642 } 6643 6644 final BooleanArgument useExistingKeyPairArgument = 6645 subCommandParser.getBooleanArgument("use-existing-key-pair"); 6646 final boolean useExistingKeyPair = 6647 ((useExistingKeyPairArgument != null) && 6648 useExistingKeyPairArgument.isPresent()); 6649 if (useExistingKeyPair && (! keystorePath.exists())) 6650 { 6651 wrapErr(0, WRAP_COLUMN, 6652 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_WITHOUT_KS.get()); 6653 return ResultCode.PARAM_ERROR; 6654 } 6655 6656 final BooleanArgument inheritExtensionsArgument = 6657 subCommandParser.getBooleanArgument("inherit-extensions"); 6658 final boolean inheritExtensions = 6659 ((inheritExtensionsArgument != null) && 6660 inheritExtensionsArgument.isPresent()); 6661 6662 final BooleanArgument includeRequestedExtensionsArgument = 6663 subCommandParser.getBooleanArgument("include-requested-extensions"); 6664 final boolean includeRequestedExtensions = 6665 ((includeRequestedExtensionsArgument != null) && 6666 includeRequestedExtensionsArgument.isPresent()); 6667 6668 final BooleanArgument noPromptArgument = 6669 subCommandParser.getBooleanArgument("no-prompt"); 6670 final boolean noPrompt = 6671 ((noPromptArgument != null) && noPromptArgument.isPresent()); 6672 6673 final BooleanArgument displayKeytoolCommandArgument = 6674 subCommandParser.getBooleanArgument("display-keytool-command"); 6675 final boolean displayKeytoolCommand = 6676 ((displayKeytoolCommandArgument != null) && 6677 displayKeytoolCommandArgument.isPresent()); 6678 6679 int daysValid = 365; 6680 final IntegerArgument daysValidArgument = 6681 subCommandParser.getIntegerArgument("days-valid"); 6682 if ((daysValidArgument != null) && daysValidArgument.isPresent()) 6683 { 6684 daysValid = daysValidArgument.getValue(); 6685 } 6686 6687 Date validityStartTime = null; 6688 final TimestampArgument validityStartTimeArgument = 6689 subCommandParser.getTimestampArgument("validity-start-time"); 6690 if ((validityStartTimeArgument != null) && 6691 validityStartTimeArgument.isPresent()) 6692 { 6693 validityStartTime = validityStartTimeArgument.getValue(); 6694 } 6695 6696 PublicKeyAlgorithmIdentifier keyAlgorithmIdentifier = null; 6697 String keyAlgorithmName = null; 6698 final StringArgument keyAlgorithmArgument = 6699 subCommandParser.getStringArgument("key-algorithm"); 6700 if ((keyAlgorithmArgument != null) && keyAlgorithmArgument.isPresent()) 6701 { 6702 final String name = keyAlgorithmArgument.getValue(); 6703 keyAlgorithmIdentifier = PublicKeyAlgorithmIdentifier.forName(name); 6704 if (keyAlgorithmIdentifier == null) 6705 { 6706 wrapErr(0, WRAP_COLUMN, 6707 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_KEY_ALG.get(name)); 6708 return ResultCode.PARAM_ERROR; 6709 } 6710 else 6711 { 6712 keyAlgorithmName = keyAlgorithmIdentifier.getName(); 6713 } 6714 } 6715 6716 Integer keySizeBits = null; 6717 final IntegerArgument keySizeBitsArgument = 6718 subCommandParser.getIntegerArgument("key-size-bits"); 6719 if ((keySizeBitsArgument != null) && keySizeBitsArgument.isPresent()) 6720 { 6721 keySizeBits = keySizeBitsArgument.getValue(); 6722 } 6723 6724 if ((keyAlgorithmIdentifier != null) && 6725 (keyAlgorithmIdentifier != PublicKeyAlgorithmIdentifier.RSA) && 6726 (keySizeBits == null)) 6727 { 6728 wrapErr(0, WRAP_COLUMN, 6729 ERR_MANAGE_CERTS_GEN_CERT_NO_KEY_SIZE_FOR_NON_RSA_KEY.get()); 6730 return ResultCode.PARAM_ERROR; 6731 } 6732 6733 String signatureAlgorithmName = null; 6734 SignatureAlgorithmIdentifier signatureAlgorithmIdentifier = null; 6735 final StringArgument signatureAlgorithmArgument = 6736 subCommandParser.getStringArgument("signature-algorithm"); 6737 if ((signatureAlgorithmArgument != null) && 6738 signatureAlgorithmArgument.isPresent()) 6739 { 6740 final String name = signatureAlgorithmArgument.getValue(); 6741 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forName(name); 6742 if (signatureAlgorithmIdentifier == null) 6743 { 6744 wrapErr(0, WRAP_COLUMN, 6745 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG.get(name)); 6746 return ResultCode.PARAM_ERROR; 6747 } 6748 else 6749 { 6750 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 6751 } 6752 } 6753 6754 if ((keyAlgorithmIdentifier != null) && 6755 (keyAlgorithmIdentifier != PublicKeyAlgorithmIdentifier.RSA) && 6756 (signatureAlgorithmIdentifier == null)) 6757 { 6758 wrapErr(0, WRAP_COLUMN, 6759 ERR_MANAGE_CERTS_GEN_CERT_NO_SIG_ALG_FOR_NON_RSA_KEY.get()); 6760 return ResultCode.PARAM_ERROR; 6761 } 6762 6763 6764 // Build a subject alternative name extension, if appropriate. 6765 final ArrayList<X509CertificateExtension> extensionList = 6766 new ArrayList<>(10); 6767 final GeneralNamesBuilder sanBuilder = new GeneralNamesBuilder(); 6768 final LinkedHashSet<String> sanValues = 6769 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 6770 final StringArgument sanDNSArgument = 6771 subCommandParser.getStringArgument("subject-alternative-name-dns"); 6772 if ((sanDNSArgument != null) && sanDNSArgument.isPresent()) 6773 { 6774 for (final String value : sanDNSArgument.getValues()) 6775 { 6776 sanBuilder.addDNSName(value); 6777 sanValues.add("DNS:" + value); 6778 } 6779 } 6780 6781 final StringArgument sanIPArgument = subCommandParser.getStringArgument( 6782 "subject-alternative-name-ip-address"); 6783 if ((sanIPArgument != null) && sanIPArgument.isPresent()) 6784 { 6785 for (final String value : sanIPArgument.getValues()) 6786 { 6787 try 6788 { 6789 sanBuilder.addIPAddress(LDAPConnectionOptions.DEFAULT_NAME_RESOLVER. 6790 getByName(value)); 6791 sanValues.add("IP:" + value); 6792 } 6793 catch (final Exception e) 6794 { 6795 // This should never happen. 6796 Debug.debugException(e); 6797 throw new RuntimeException(e); 6798 } 6799 } 6800 } 6801 6802 final StringArgument sanEmailArgument = subCommandParser.getStringArgument( 6803 "subject-alternative-name-email-address"); 6804 if ((sanEmailArgument != null) && sanEmailArgument.isPresent()) 6805 { 6806 for (final String value : sanEmailArgument.getValues()) 6807 { 6808 sanBuilder.addRFC822Name(value); 6809 sanValues.add("EMAIL:" + value); 6810 } 6811 } 6812 6813 final StringArgument sanURIArgument = 6814 subCommandParser.getStringArgument("subject-alternative-name-uri"); 6815 if ((sanURIArgument != null) && sanURIArgument.isPresent()) 6816 { 6817 for (final String value : sanURIArgument.getValues()) 6818 { 6819 sanBuilder.addUniformResourceIdentifier(value); 6820 sanValues.add("URI:" + value); 6821 } 6822 } 6823 6824 final StringArgument sanOIDArgument = 6825 subCommandParser.getStringArgument("subject-alternative-name-oid"); 6826 if ((sanOIDArgument != null) && sanOIDArgument.isPresent()) 6827 { 6828 for (final String value : sanOIDArgument.getValues()) 6829 { 6830 sanBuilder.addRegisteredID(new OID(value)); 6831 sanValues.add("OID:" + value); 6832 } 6833 } 6834 6835 if (! sanValues.isEmpty()) 6836 { 6837 try 6838 { 6839 extensionList.add( 6840 new SubjectAlternativeNameExtension(false, sanBuilder.build())); 6841 } 6842 catch (final Exception e) 6843 { 6844 // This should never happen. 6845 Debug.debugException(e); 6846 throw new RuntimeException(e); 6847 } 6848 } 6849 6850 // Build a set of issuer alternative name extension values. 6851 final GeneralNamesBuilder ianBuilder = new GeneralNamesBuilder(); 6852 final LinkedHashSet<String> ianValues = 6853 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 6854 final StringArgument ianDNSArgument = 6855 subCommandParser.getStringArgument("issuer-alternative-name-dns"); 6856 if ((ianDNSArgument != null) && ianDNSArgument.isPresent()) 6857 { 6858 for (final String value : ianDNSArgument.getValues()) 6859 { 6860 ianBuilder.addDNSName(value); 6861 ianValues.add("DNS:" + value); 6862 } 6863 } 6864 6865 final StringArgument ianIPArgument = subCommandParser.getStringArgument( 6866 "issuer-alternative-name-ip-address"); 6867 if ((ianIPArgument != null) && ianIPArgument.isPresent()) 6868 { 6869 for (final String value : ianIPArgument.getValues()) 6870 { 6871 try 6872 { 6873 ianBuilder.addIPAddress(LDAPConnectionOptions.DEFAULT_NAME_RESOLVER. 6874 getByName(value)); 6875 ianValues.add("IP:" + value); 6876 } 6877 catch (final Exception e) 6878 { 6879 // This should never happen. 6880 Debug.debugException(e); 6881 throw new RuntimeException(e); 6882 } 6883 } 6884 } 6885 6886 final StringArgument ianEmailArgument = subCommandParser.getStringArgument( 6887 "issuer-alternative-name-email-address"); 6888 if ((ianEmailArgument != null) && ianEmailArgument.isPresent()) 6889 { 6890 for (final String value : ianEmailArgument.getValues()) 6891 { 6892 ianBuilder.addRFC822Name(value); 6893 ianValues.add("EMAIL:" + value); 6894 } 6895 } 6896 6897 final StringArgument ianURIArgument = 6898 subCommandParser.getStringArgument("issuer-alternative-name-uri"); 6899 if ((ianURIArgument != null) && ianURIArgument.isPresent()) 6900 { 6901 for (final String value : ianURIArgument.getValues()) 6902 { 6903 ianBuilder.addUniformResourceIdentifier(value); 6904 ianValues.add("URI:" + value); 6905 } 6906 } 6907 6908 final StringArgument ianOIDArgument = 6909 subCommandParser.getStringArgument("issuer-alternative-name-oid"); 6910 if ((ianOIDArgument != null) && ianOIDArgument.isPresent()) 6911 { 6912 for (final String value : ianOIDArgument.getValues()) 6913 { 6914 ianBuilder.addRegisteredID(new OID(value)); 6915 ianValues.add("OID:" + value); 6916 } 6917 } 6918 6919 if (! ianValues.isEmpty()) 6920 { 6921 try 6922 { 6923 extensionList.add( 6924 new IssuerAlternativeNameExtension(false, ianBuilder.build())); 6925 } 6926 catch (final Exception e) 6927 { 6928 // This should never happen. 6929 Debug.debugException(e); 6930 throw new RuntimeException(e); 6931 } 6932 } 6933 6934 6935 // Build a basic constraints extension, if appropriate. 6936 BasicConstraintsExtension basicConstraints = null; 6937 final BooleanValueArgument basicConstraintsIsCAArgument = 6938 subCommandParser.getBooleanValueArgument("basic-constraints-is-ca"); 6939 if ((basicConstraintsIsCAArgument != null) && 6940 basicConstraintsIsCAArgument.isPresent()) 6941 { 6942 final boolean isCA = basicConstraintsIsCAArgument.getValue(); 6943 6944 Integer pathLength = null; 6945 final IntegerArgument pathLengthArgument = 6946 subCommandParser.getIntegerArgument( 6947 "basic-constraints-maximum-path-length"); 6948 if ((pathLengthArgument != null) && pathLengthArgument.isPresent()) 6949 { 6950 if (isCA) 6951 { 6952 pathLength = pathLengthArgument.getValue(); 6953 } 6954 else 6955 { 6956 wrapErr(0, WRAP_COLUMN, 6957 ERR_MANAGE_CERTS_GEN_CERT_BC_PATH_LENGTH_WITHOUT_CA.get()); 6958 return ResultCode.PARAM_ERROR; 6959 } 6960 } 6961 6962 basicConstraints = new BasicConstraintsExtension(false, isCA, pathLength); 6963 extensionList.add(basicConstraints); 6964 } 6965 6966 6967 // Build a key usage extension, if appropriate. 6968 KeyUsageExtension keyUsage = null; 6969 final StringArgument keyUsageArgument = 6970 subCommandParser.getStringArgument("key-usage"); 6971 if ((keyUsageArgument != null) && keyUsageArgument.isPresent()) 6972 { 6973 boolean digitalSignature = false; 6974 boolean nonRepudiation = false; 6975 boolean keyEncipherment = false; 6976 boolean dataEncipherment = false; 6977 boolean keyAgreement = false; 6978 boolean keyCertSign = false; 6979 boolean crlSign = false; 6980 boolean encipherOnly = false; 6981 boolean decipherOnly = false; 6982 6983 for (final String value : keyUsageArgument.getValues()) 6984 { 6985 if (value.equalsIgnoreCase("digital-signature") || 6986 value.equalsIgnoreCase("digitalSignature")) 6987 { 6988 digitalSignature = true; 6989 } 6990 else if (value.equalsIgnoreCase("non-repudiation") || 6991 value.equalsIgnoreCase("nonRepudiation") || 6992 value.equalsIgnoreCase("content-commitment") || 6993 value.equalsIgnoreCase("contentCommitment")) 6994 { 6995 nonRepudiation = true; 6996 } 6997 else if (value.equalsIgnoreCase("key-encipherment") || 6998 value.equalsIgnoreCase("keyEncipherment")) 6999 { 7000 keyEncipherment = true; 7001 } 7002 else if (value.equalsIgnoreCase("data-encipherment") || 7003 value.equalsIgnoreCase("dataEncipherment")) 7004 { 7005 dataEncipherment = true; 7006 } 7007 else if (value.equalsIgnoreCase("key-agreement") || 7008 value.equalsIgnoreCase("keyAgreement")) 7009 { 7010 keyAgreement = true; 7011 } 7012 else if (value.equalsIgnoreCase("key-cert-sign") || 7013 value.equalsIgnoreCase("keyCertSign")) 7014 { 7015 keyCertSign = true; 7016 } 7017 else if (value.equalsIgnoreCase("crl-sign") || 7018 value.equalsIgnoreCase("crlSign")) 7019 { 7020 crlSign = true; 7021 } 7022 else if (value.equalsIgnoreCase("encipher-only") || 7023 value.equalsIgnoreCase("encipherOnly")) 7024 { 7025 encipherOnly = true; 7026 } 7027 else if (value.equalsIgnoreCase("decipher-only") || 7028 value.equalsIgnoreCase("decipherOnly")) 7029 { 7030 decipherOnly = true; 7031 } 7032 else 7033 { 7034 wrapErr(0, WRAP_COLUMN, 7035 ERR_MANAGE_CERTS_GEN_CERT_INVALID_KEY_USAGE.get(value)); 7036 return ResultCode.PARAM_ERROR; 7037 } 7038 } 7039 7040 keyUsage = new KeyUsageExtension(false, digitalSignature, nonRepudiation, 7041 keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, 7042 crlSign, encipherOnly, decipherOnly); 7043 extensionList.add(keyUsage); 7044 } 7045 7046 7047 // Build an extended key usage extension, if appropriate. 7048 ExtendedKeyUsageExtension extendedKeyUsage = null; 7049 final StringArgument extendedKeyUsageArgument = 7050 subCommandParser.getStringArgument("extended-key-usage"); 7051 if ((extendedKeyUsageArgument != null) && 7052 extendedKeyUsageArgument.isPresent()) 7053 { 7054 final List<String> values = extendedKeyUsageArgument.getValues(); 7055 final ArrayList<OID> keyPurposeIDs = new ArrayList<>(values.size()); 7056 for (final String value : values) 7057 { 7058 if (value.equalsIgnoreCase("server-auth") || 7059 value.equalsIgnoreCase("serverAuth") || 7060 value.equalsIgnoreCase("server-authentication") || 7061 value.equalsIgnoreCase("serverAuthentication") || 7062 value.equalsIgnoreCase("tls-server-authentication") || 7063 value.equalsIgnoreCase("tlsServerAuthentication")) 7064 { 7065 keyPurposeIDs.add( 7066 ExtendedKeyUsageID.TLS_SERVER_AUTHENTICATION.getOID()); 7067 } 7068 else if (value.equalsIgnoreCase("client-auth") || 7069 value.equalsIgnoreCase("clientAuth") || 7070 value.equalsIgnoreCase("client-authentication") || 7071 value.equalsIgnoreCase("clientAuthentication") || 7072 value.equalsIgnoreCase("tls-client-authentication") || 7073 value.equalsIgnoreCase("tlsClientAuthentication")) 7074 { 7075 keyPurposeIDs.add( 7076 ExtendedKeyUsageID.TLS_CLIENT_AUTHENTICATION.getOID()); 7077 } 7078 else if (value.equalsIgnoreCase("code-signing") || 7079 value.equalsIgnoreCase("codeSigning")) 7080 { 7081 keyPurposeIDs.add(ExtendedKeyUsageID.CODE_SIGNING.getOID()); 7082 } 7083 else if (value.equalsIgnoreCase("email-protection") || 7084 value.equalsIgnoreCase("emailProtection")) 7085 { 7086 keyPurposeIDs.add(ExtendedKeyUsageID.EMAIL_PROTECTION.getOID()); 7087 } 7088 else if (value.equalsIgnoreCase("time-stamping") || 7089 value.equalsIgnoreCase("timeStamping")) 7090 { 7091 keyPurposeIDs.add(ExtendedKeyUsageID.TIME_STAMPING.getOID()); 7092 } 7093 else if (value.equalsIgnoreCase("ocsp-signing") || 7094 value.equalsIgnoreCase("ocspSigning")) 7095 { 7096 keyPurposeIDs.add(ExtendedKeyUsageID.OCSP_SIGNING.getOID()); 7097 } 7098 else if (OID.isStrictlyValidNumericOID(value)) 7099 { 7100 keyPurposeIDs.add(new OID(value)); 7101 } 7102 else 7103 { 7104 wrapErr(0, WRAP_COLUMN, 7105 ERR_MANAGE_CERTS_GEN_CERT_INVALID_EXTENDED_KEY_USAGE.get(value)); 7106 return ResultCode.PARAM_ERROR; 7107 } 7108 } 7109 7110 try 7111 { 7112 extendedKeyUsage = new ExtendedKeyUsageExtension(false, keyPurposeIDs); 7113 } 7114 catch (final Exception e) 7115 { 7116 // This should never happen. 7117 Debug.debugException(e); 7118 wrapErr(0, WRAP_COLUMN, 7119 ERR_MANAGE_CERTS_GEN_CERT_EXTENDED_KEY_USAGE_ERROR.get()); 7120 e.printStackTrace(getErr()); 7121 return ResultCode.PARAM_ERROR; 7122 } 7123 7124 extensionList.add(extendedKeyUsage); 7125 } 7126 7127 7128 // Build a list of generic extensions. 7129 final ArrayList<X509CertificateExtension> genericExtensions = 7130 new ArrayList<>(5); 7131 final StringArgument extensionArgument = 7132 subCommandParser.getStringArgument("extension"); 7133 if ((extensionArgument != null) && extensionArgument.isPresent()) 7134 { 7135 for (final String value : extensionArgument.getValues()) 7136 { 7137 try 7138 { 7139 final int firstColonPos = value.indexOf(':'); 7140 final int secondColonPos = value.indexOf(':', firstColonPos + 1); 7141 final OID oid = new OID(value.substring(0, firstColonPos)); 7142 if (! oid.isStrictlyValidNumericOID()) 7143 { 7144 wrapErr(0, WRAP_COLUMN, 7145 ERR_MANAGE_CERTS_GEN_CERT_EXT_MALFORMED_OID.get(value, 7146 oid.toString())); 7147 return ResultCode.PARAM_ERROR; 7148 } 7149 7150 final boolean criticality; 7151 final String criticalityString = 7152 value.substring(firstColonPos + 1, secondColonPos); 7153 if (criticalityString.equalsIgnoreCase("true") || 7154 criticalityString.equalsIgnoreCase("t") || 7155 criticalityString.equalsIgnoreCase("yes") || 7156 criticalityString.equalsIgnoreCase("y") || 7157 criticalityString.equalsIgnoreCase("on") || 7158 criticalityString.equalsIgnoreCase("1")) 7159 { 7160 criticality = true; 7161 } 7162 else if (criticalityString.equalsIgnoreCase("false") || 7163 criticalityString.equalsIgnoreCase("f") || 7164 criticalityString.equalsIgnoreCase("no") || 7165 criticalityString.equalsIgnoreCase("n") || 7166 criticalityString.equalsIgnoreCase("off") || 7167 criticalityString.equalsIgnoreCase("0")) 7168 { 7169 criticality = false; 7170 } 7171 else 7172 { 7173 wrapErr(0, WRAP_COLUMN, 7174 ERR_MANAGE_CERTS_GEN_CERT_EXT_INVALID_CRITICALITY.get( 7175 value, criticalityString)); 7176 return ResultCode.PARAM_ERROR; 7177 } 7178 7179 final byte[] valueBytes; 7180 try 7181 { 7182 valueBytes = StaticUtils.fromHex(value.substring(secondColonPos+1)); 7183 } 7184 catch (final Exception e) 7185 { 7186 Debug.debugException(e); 7187 wrapErr(0, WRAP_COLUMN, 7188 ERR_MANAGE_CERTS_GEN_CERT_EXT_INVALID_VALUE.get(value)); 7189 return ResultCode.PARAM_ERROR; 7190 } 7191 7192 final X509CertificateExtension extension = 7193 new X509CertificateExtension(oid, criticality, valueBytes); 7194 genericExtensions.add(extension); 7195 extensionList.add(extension); 7196 } 7197 catch (final Exception e) 7198 { 7199 Debug.debugException(e); 7200 wrapErr(0, WRAP_COLUMN, 7201 ERR_MANAGE_CERTS_GEN_CERT_EXT_MALFORMED.get(value)); 7202 return ResultCode.PARAM_ERROR; 7203 } 7204 } 7205 } 7206 7207 7208 final String keystoreType; 7209 try 7210 { 7211 keystoreType = inferKeystoreType(keystorePath); 7212 } 7213 catch (final LDAPException le) 7214 { 7215 Debug.debugException(le); 7216 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7217 return le.getResultCode(); 7218 } 7219 7220 final char[] keystorePassword; 7221 try 7222 { 7223 keystorePassword = getKeystorePassword(keystorePath); 7224 } 7225 catch (final LDAPException le) 7226 { 7227 Debug.debugException(le); 7228 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7229 return le.getResultCode(); 7230 } 7231 7232 7233 // Get the keystore. 7234 final KeyStore keystore; 7235 try 7236 { 7237 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 7238 } 7239 catch (final LDAPException le) 7240 { 7241 Debug.debugException(le); 7242 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7243 return le.getResultCode(); 7244 } 7245 7246 7247 // If there is a private key, then see if we need to use a private key 7248 // password that is different from the keystore password. 7249 final char[] privateKeyPassword; 7250 try 7251 { 7252 privateKeyPassword = 7253 getPrivateKeyPassword(keystore, alias, keystorePassword); 7254 } 7255 catch (final LDAPException le) 7256 { 7257 Debug.debugException(le); 7258 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7259 return le.getResultCode(); 7260 } 7261 7262 7263 // If we're going to replace an existing certificate in the keystore, then 7264 // perform the appropriate processing for that. 7265 if (useExistingKeyPair) 7266 { 7267 // Make sure that the keystore already has a private key entry with the 7268 // specified alias. 7269 if (! hasKeyAlias(keystore, alias)) 7270 { 7271 if (hasCertificateAlias(keystore, alias)) 7272 { 7273 wrapErr(0, WRAP_COLUMN, 7274 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_ALIAS_IS_CERT.get( 7275 alias, keystorePath.getAbsolutePath())); 7276 return ResultCode.PARAM_ERROR; 7277 } 7278 else 7279 { 7280 wrapErr(0, WRAP_COLUMN, 7281 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_NO_SUCH_ALIAS.get( 7282 alias, keystorePath.getAbsolutePath())); 7283 return ResultCode.PARAM_ERROR; 7284 } 7285 } 7286 7287 7288 // Get the certificate to replace, along with its key pair. 7289 final X509Certificate certToReplace; 7290 final KeyPair keyPair; 7291 try 7292 { 7293 final Certificate[] chain = keystore.getCertificateChain(alias); 7294 certToReplace = new X509Certificate(chain[0].getEncoded()); 7295 7296 final PublicKey publicKey = chain[0].getPublicKey(); 7297 final PrivateKey privateKey = 7298 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 7299 keyPair = new KeyPair(publicKey, privateKey); 7300 } 7301 catch (final Exception e) 7302 { 7303 Debug.debugException(e); 7304 wrapErr(0, WRAP_COLUMN, 7305 ERR_MANAGE_CERTS_GEN_CERT_USE_EXISTING_KP_COULD_NOT_GET_CERT.get( 7306 alias)); 7307 e.printStackTrace(getErr()); 7308 return ResultCode.LOCAL_ERROR; 7309 } 7310 7311 7312 // Assign the remaining values using information in the existing 7313 // certificate. 7314 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forOID( 7315 certToReplace.getSignatureAlgorithmOID()); 7316 if (signatureAlgorithmIdentifier == null) 7317 { 7318 wrapErr(0, WRAP_COLUMN, 7319 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG_IN_CERT.get( 7320 certToReplace.getSignatureAlgorithmOID())); 7321 return ResultCode.PARAM_ERROR; 7322 } 7323 else 7324 { 7325 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 7326 } 7327 7328 if (subjectDN == null) 7329 { 7330 subjectDN = certToReplace.getSubjectDN(); 7331 } 7332 7333 if (inheritExtensions) 7334 { 7335 for (final X509CertificateExtension extension : 7336 certToReplace.getExtensions()) 7337 { 7338 if ((extension instanceof AuthorityKeyIdentifierExtension) || 7339 (extension instanceof IssuerAlternativeNameExtension)) 7340 { 7341 // This extension applies to the issuer. We won't include this in 7342 // the set of inherited extensions. 7343 } 7344 else if (extension instanceof SubjectKeyIdentifierExtension) 7345 { 7346 // The generated certificate will automatically include a subject 7347 // key identifier extension, so we don't need to include it. 7348 } 7349 else if (extension instanceof BasicConstraintsExtension) 7350 { 7351 // Don't override a value already provided on the command line. 7352 if (basicConstraints == null) 7353 { 7354 basicConstraints = (BasicConstraintsExtension) extension; 7355 extensionList.add(basicConstraints); 7356 } 7357 } 7358 else if (extension instanceof ExtendedKeyUsageExtension) 7359 { 7360 // Don't override a value already provided on the command line. 7361 if (extendedKeyUsage == null) 7362 { 7363 extendedKeyUsage = (ExtendedKeyUsageExtension) extension; 7364 extensionList.add(extendedKeyUsage); 7365 } 7366 } 7367 else if (extension instanceof KeyUsageExtension) 7368 { 7369 // Don't override a value already provided on the command line. 7370 if (keyUsage == null) 7371 { 7372 keyUsage = (KeyUsageExtension) extension; 7373 extensionList.add(keyUsage); 7374 } 7375 } 7376 else if (extension instanceof SubjectAlternativeNameExtension) 7377 { 7378 // Although we could merge values, it's safer to not do that if any 7379 // subject alternative name values were provided on the command 7380 // line. 7381 if (sanValues.isEmpty()) 7382 { 7383 final SubjectAlternativeNameExtension e = 7384 (SubjectAlternativeNameExtension) extension; 7385 for (final String dnsName : e.getDNSNames()) 7386 { 7387 sanValues.add("DNS:" + dnsName); 7388 } 7389 7390 for (final InetAddress ipAddress : e.getIPAddresses()) 7391 { 7392 sanValues.add("IP:" + ipAddress.getHostAddress()); 7393 } 7394 7395 for (final String emailAddress : e.getRFC822Names()) 7396 { 7397 sanValues.add("EMAIL:" + emailAddress); 7398 } 7399 7400 for (final String uri : e.getUniformResourceIdentifiers()) 7401 { 7402 sanValues.add("URI:" + uri); 7403 } 7404 7405 for (final OID oid : e.getRegisteredIDs()) 7406 { 7407 sanValues.add("OID:" + oid.toString()); 7408 } 7409 7410 extensionList.add(extension); 7411 } 7412 } 7413 else 7414 { 7415 genericExtensions.add(extension); 7416 extensionList.add(extension); 7417 } 7418 } 7419 } 7420 7421 7422 // Create an array with the final set of extensions to include in the 7423 // certificate or certificate signing request. 7424 final X509CertificateExtension[] extensions = 7425 new X509CertificateExtension[extensionList.size()]; 7426 extensionList.toArray(extensions); 7427 7428 7429 // If we're generating a self-signed certificate or a certificate signing 7430 // request, then we should now have everything we need to do that. Build 7431 // a keytool command that we could use to accomplish it. 7432 if (isGenerateCertificate) 7433 { 7434 if (displayKeytoolCommand) 7435 { 7436 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7437 keytoolArguments.add("-selfcert"); 7438 keytoolArguments.add("-keystore"); 7439 keytoolArguments.add(keystorePath.getAbsolutePath()); 7440 keytoolArguments.add("-storetype"); 7441 keytoolArguments.add(keystoreType); 7442 keytoolArguments.add("-storepass"); 7443 keytoolArguments.add("*****REDACTED*****"); 7444 keytoolArguments.add("-keypass"); 7445 keytoolArguments.add("*****REDACTED*****"); 7446 keytoolArguments.add("-alias"); 7447 keytoolArguments.add(alias); 7448 keytoolArguments.add("-dname"); 7449 keytoolArguments.add(subjectDN.toString()); 7450 keytoolArguments.add("-sigalg"); 7451 keytoolArguments.add(signatureAlgorithmName); 7452 keytoolArguments.add("-validity"); 7453 keytoolArguments.add(String.valueOf(daysValid)); 7454 7455 if (validityStartTime != null) 7456 { 7457 keytoolArguments.add("-startdate"); 7458 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 7459 } 7460 7461 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7462 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7463 7464 displayKeytoolCommand(keytoolArguments); 7465 } 7466 7467 7468 // Generate the self-signed certificate. 7469 final long notBefore; 7470 if (validityStartTime == null) 7471 { 7472 notBefore = System.currentTimeMillis(); 7473 } 7474 else 7475 { 7476 notBefore = validityStartTime.getTime(); 7477 } 7478 7479 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 7480 7481 final X509Certificate certificate; 7482 final Certificate[] chain; 7483 try 7484 { 7485 certificate = X509Certificate.generateSelfSignedCertificate( 7486 signatureAlgorithmIdentifier, keyPair, subjectDN, notBefore, 7487 notAfter, extensions); 7488 chain = new Certificate[] { certificate.toCertificate() }; 7489 } 7490 catch (final Exception e) 7491 { 7492 Debug.debugException(e); 7493 wrapErr(0, WRAP_COLUMN, 7494 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CERT.get()); 7495 e.printStackTrace(getErr()); 7496 return ResultCode.LOCAL_ERROR; 7497 } 7498 7499 7500 // Update the keystore with the new certificate. 7501 try 7502 { 7503 keystore.setKeyEntry(alias, keyPair.getPrivate(), privateKeyPassword, 7504 chain); 7505 writeKeystore(keystore, keystorePath, keystorePassword); 7506 } 7507 catch (final Exception e) 7508 { 7509 Debug.debugException(e); 7510 wrapErr(0, WRAP_COLUMN, 7511 ERR_MANAGE_CERTS_GEN_CERT_ERROR_UPDATING_KEYSTORE.get()); 7512 e.printStackTrace(getErr()); 7513 return ResultCode.LOCAL_ERROR; 7514 } 7515 7516 7517 // Display the certificate we just generated to the end user. 7518 out(); 7519 wrapOut(0, WRAP_COLUMN, 7520 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_SELF_CERT. 7521 get()); 7522 printCertificate(certificate, "", false); 7523 7524 7525 // If we should write an output file, then do that now. 7526 if (outputFile != null) 7527 { 7528 try (PrintStream ps = new PrintStream(outputFile)) 7529 { 7530 final byte[] certBytes = certificate.getX509CertificateBytes(); 7531 if (outputPEM) 7532 { 7533 writePEMCertificate(ps, certBytes); 7534 } 7535 else 7536 { 7537 ps.write(certBytes); 7538 } 7539 7540 out(); 7541 wrapOut(0, WRAP_COLUMN, 7542 INFO_MANAGE_CERTS_GEN_CERT_WROTE_OUTPUT_FILE.get( 7543 outputFile.getAbsolutePath())); 7544 } 7545 catch (final Exception e) 7546 { 7547 Debug.debugException(e); 7548 err(); 7549 wrapErr(0, WRAP_COLUMN, 7550 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CERT.get( 7551 outputFile.getAbsolutePath())); 7552 e.printStackTrace(getErr()); 7553 return ResultCode.LOCAL_ERROR; 7554 } 7555 } 7556 7557 return ResultCode.SUCCESS; 7558 } 7559 else 7560 { 7561 // Build the keytool command used to generate the certificate signing 7562 // request. 7563 Validator.ensureTrue(isGenerateCSR); 7564 if (displayKeytoolCommand) 7565 { 7566 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7567 keytoolArguments.add("-certreq"); 7568 keytoolArguments.add("-keystore"); 7569 keytoolArguments.add(keystorePath.getAbsolutePath()); 7570 keytoolArguments.add("-storetype"); 7571 keytoolArguments.add(keystoreType); 7572 keytoolArguments.add("-storepass"); 7573 keytoolArguments.add("*****REDACTED*****"); 7574 keytoolArguments.add("-keypass"); 7575 keytoolArguments.add("*****REDACTED*****"); 7576 keytoolArguments.add("-alias"); 7577 keytoolArguments.add(alias); 7578 keytoolArguments.add("-dname"); 7579 keytoolArguments.add(subjectDN.toString()); 7580 keytoolArguments.add("-sigalg"); 7581 keytoolArguments.add(signatureAlgorithmName); 7582 7583 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7584 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7585 7586 if (outputFile != null) 7587 { 7588 keytoolArguments.add("-file"); 7589 keytoolArguments.add(outputFile.getAbsolutePath()); 7590 } 7591 7592 displayKeytoolCommand(keytoolArguments); 7593 } 7594 7595 7596 // Generate the certificate signing request. 7597 final PKCS10CertificateSigningRequest certificateSigningRequest; 7598 try 7599 { 7600 certificateSigningRequest = PKCS10CertificateSigningRequest. 7601 generateCertificateSigningRequest(signatureAlgorithmIdentifier, 7602 keyPair, subjectDN, extensions); 7603 } 7604 catch (final Exception e) 7605 { 7606 Debug.debugException(e); 7607 wrapErr(0, WRAP_COLUMN, 7608 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CSR.get()); 7609 e.printStackTrace(getErr()); 7610 return ResultCode.LOCAL_ERROR; 7611 } 7612 7613 7614 // Write the generated certificate signing request to the appropriate 7615 // location. 7616 try 7617 { 7618 final PrintStream ps; 7619 if (outputFile == null) 7620 { 7621 ps = getOut(); 7622 } 7623 else 7624 { 7625 ps = new PrintStream(outputFile); 7626 } 7627 7628 if (outputPEM) 7629 { 7630 writePEMCertificateSigningRequest(ps, 7631 certificateSigningRequest. 7632 getPKCS10CertificateSigningRequestBytes()); 7633 } 7634 else 7635 { 7636 ps.write(certificateSigningRequest. 7637 getPKCS10CertificateSigningRequestBytes()); 7638 } 7639 7640 if (outputFile != null) 7641 { 7642 ps.close(); 7643 } 7644 } 7645 catch (final Exception e) 7646 { 7647 Debug.debugException(e); 7648 wrapErr(0, WRAP_COLUMN, 7649 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CSR.get()); 7650 e.printStackTrace(getErr()); 7651 return ResultCode.LOCAL_ERROR; 7652 } 7653 7654 7655 // If the certificate signing request was written to an output file, 7656 // then let the user know that it was successful. If it was written to 7657 // standard output, then we don't need to tell them because they'll be 7658 // able to see it. 7659 if (outputFile != null) 7660 { 7661 out(); 7662 wrapOut(0, WRAP_COLUMN, 7663 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_CSR.get( 7664 outputFile.getAbsolutePath())); 7665 } 7666 7667 return ResultCode.SUCCESS; 7668 } 7669 } 7670 7671 7672 // If we've gotten here, then we know we're not replacing an existing 7673 // certificate. Perform any remaining argument assignment and validation. 7674 if ((subjectDN == null) && (! isSignCSR)) 7675 { 7676 wrapErr(0, WRAP_COLUMN, 7677 ERR_MANAGE_CERTS_GEN_CERT_NO_SUBJECT_DN_WITHOUT_USE_EXISTING_KP. 7678 get()); 7679 return ResultCode.PARAM_ERROR; 7680 } 7681 7682 if (keyAlgorithmIdentifier == null) 7683 { 7684 keyAlgorithmIdentifier = PublicKeyAlgorithmIdentifier.RSA; 7685 keyAlgorithmName = keyAlgorithmIdentifier.getName(); 7686 } 7687 7688 if (keySizeBits == null) 7689 { 7690 keySizeBits = 2048; 7691 } 7692 7693 if ((signatureAlgorithmIdentifier == null) && (! isSignCSR)) 7694 { 7695 signatureAlgorithmIdentifier = 7696 SignatureAlgorithmIdentifier.SHA_256_WITH_RSA; 7697 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 7698 } 7699 7700 7701 // If we're going to generate a self-signed certificate or a certificate 7702 // signing request, then we first need to generate a key pair. Put together 7703 // the appropriate set of keytool arguments and then generate a self-signed 7704 // certificate. 7705 if (isGenerateCertificate || isGenerateCSR) 7706 { 7707 // Make sure that the specified alias is not already in use in the 7708 // keystore. 7709 if (hasKeyAlias(keystore, alias) || hasCertificateAlias(keystore, alias)) 7710 { 7711 wrapErr(0, WRAP_COLUMN, 7712 ERR_MANAGE_CERTS_GEN_CERT_ALIAS_EXISTS_WITHOUT_USE_EXISTING_KP.get( 7713 alias)); 7714 return ResultCode.PARAM_ERROR; 7715 } 7716 7717 7718 if (displayKeytoolCommand) 7719 { 7720 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7721 keytoolArguments.add("-genkeypair"); 7722 keytoolArguments.add("-keystore"); 7723 keytoolArguments.add(keystorePath.getAbsolutePath()); 7724 keytoolArguments.add("-storetype"); 7725 keytoolArguments.add(keystoreType); 7726 keytoolArguments.add("-storepass"); 7727 keytoolArguments.add("*****REDACTED*****"); 7728 keytoolArguments.add("-keypass"); 7729 keytoolArguments.add("*****REDACTED*****"); 7730 keytoolArguments.add("-alias"); 7731 keytoolArguments.add(alias); 7732 keytoolArguments.add("-dname"); 7733 keytoolArguments.add(subjectDN.toString()); 7734 keytoolArguments.add("-keyalg"); 7735 keytoolArguments.add(keyAlgorithmName); 7736 keytoolArguments.add("-keysize"); 7737 keytoolArguments.add(String.valueOf(keySizeBits)); 7738 keytoolArguments.add("-sigalg"); 7739 keytoolArguments.add(signatureAlgorithmName); 7740 keytoolArguments.add("-validity"); 7741 keytoolArguments.add(String.valueOf(daysValid)); 7742 7743 if (validityStartTime != null) 7744 { 7745 keytoolArguments.add("-startdate"); 7746 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 7747 } 7748 7749 addExtensionArguments(keytoolArguments, basicConstraints, 7750 keyUsage, extendedKeyUsage, sanValues, ianValues, 7751 genericExtensions); 7752 7753 displayKeytoolCommand(keytoolArguments); 7754 } 7755 7756 7757 // Generate the self-signed certificate. 7758 final long notBefore; 7759 if (validityStartTime == null) 7760 { 7761 notBefore = System.currentTimeMillis(); 7762 } 7763 else 7764 { 7765 notBefore = validityStartTime.getTime(); 7766 } 7767 7768 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 7769 7770 final X509CertificateExtension[] extensions = 7771 new X509CertificateExtension[extensionList.size()]; 7772 extensionList.toArray(extensions); 7773 7774 final Certificate[] chain; 7775 final KeyPair keyPair; 7776 final X509Certificate certificate; 7777 try 7778 { 7779 final ObjectPair<X509Certificate,KeyPair> p = 7780 X509Certificate.generateSelfSignedCertificate( 7781 signatureAlgorithmIdentifier, keyAlgorithmIdentifier, 7782 keySizeBits, subjectDN, notBefore, notAfter, extensions); 7783 certificate = p.getFirst(); 7784 chain = new Certificate[] { certificate.toCertificate() }; 7785 keyPair = p.getSecond(); 7786 } 7787 catch (final Exception e) 7788 { 7789 Debug.debugException(e); 7790 wrapErr(0, WRAP_COLUMN, 7791 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CERT.get()); 7792 e.printStackTrace(getErr()); 7793 return ResultCode.LOCAL_ERROR; 7794 } 7795 7796 7797 // Update the keystore with the new certificate. 7798 try 7799 { 7800 keystore.setKeyEntry(alias, keyPair.getPrivate(), privateKeyPassword, 7801 chain); 7802 writeKeystore(keystore, keystorePath, keystorePassword); 7803 } 7804 catch (final Exception e) 7805 { 7806 Debug.debugException(e); 7807 wrapErr(0, WRAP_COLUMN, 7808 ERR_MANAGE_CERTS_GEN_CERT_ERROR_UPDATING_KEYSTORE.get()); 7809 e.printStackTrace(getErr()); 7810 return ResultCode.LOCAL_ERROR; 7811 } 7812 7813 if (isNewKeystore) 7814 { 7815 out(); 7816 wrapOut(0, WRAP_COLUMN, 7817 INFO_MANAGE_CERTS_GEN_CERT_CERT_CREATED_KEYSTORE.get( 7818 getUserFriendlyKeystoreType(keystoreType))); 7819 } 7820 7821 7822 // If we're just generating a self-signed certificate, then display the 7823 // certificate that we generated and potentially write it to an output 7824 // file. 7825 if (isGenerateCertificate) 7826 { 7827 out(); 7828 wrapOut(0, WRAP_COLUMN, 7829 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_SELF_CERT.get()); 7830 printCertificate(certificate, "", false); 7831 7832 7833 // If we should write an output file, then do that now. 7834 if (outputFile != null) 7835 { 7836 try (PrintStream ps = new PrintStream(outputFile)) 7837 { 7838 final byte[] certBytes = certificate.getX509CertificateBytes(); 7839 if (outputPEM) 7840 { 7841 writePEMCertificate(ps, certBytes); 7842 } 7843 else 7844 { 7845 ps.write(certBytes); 7846 } 7847 7848 out(); 7849 wrapOut(0, WRAP_COLUMN, 7850 INFO_MANAGE_CERTS_GEN_CERT_WROTE_OUTPUT_FILE.get( 7851 outputFile.getAbsolutePath())); 7852 } 7853 catch (final Exception e) 7854 { 7855 Debug.debugException(e); 7856 err(); 7857 wrapErr(0, WRAP_COLUMN, 7858 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CERT.get( 7859 outputFile.getAbsolutePath())); 7860 e.printStackTrace(getErr()); 7861 return ResultCode.LOCAL_ERROR; 7862 } 7863 } 7864 7865 return ResultCode.SUCCESS; 7866 } 7867 7868 7869 // If we're generating a certificate signing request, then put together 7870 // the appropriate set of arguments for that. 7871 Validator.ensureTrue(isGenerateCSR); 7872 out(); 7873 wrapOut(0, WRAP_COLUMN, 7874 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_KEYPAIR.get()); 7875 7876 if (displayKeytoolCommand) 7877 { 7878 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7879 keytoolArguments.add("-certreq"); 7880 keytoolArguments.add("-keystore"); 7881 keytoolArguments.add(keystorePath.getAbsolutePath()); 7882 keytoolArguments.add("-storetype"); 7883 keytoolArguments.add(keystoreType); 7884 keytoolArguments.add("-storepass"); 7885 keytoolArguments.add("*****REDACTED*****"); 7886 keytoolArguments.add("-keypass"); 7887 keytoolArguments.add("*****REDACTED*****"); 7888 keytoolArguments.add("-alias"); 7889 keytoolArguments.add(alias); 7890 keytoolArguments.add("-dname"); 7891 keytoolArguments.add(subjectDN.toString()); 7892 keytoolArguments.add("-sigalg"); 7893 keytoolArguments.add(signatureAlgorithmName); 7894 7895 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7896 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7897 7898 if (outputFile != null) 7899 { 7900 keytoolArguments.add("-file"); 7901 keytoolArguments.add(outputFile.getAbsolutePath()); 7902 } 7903 7904 displayKeytoolCommand(keytoolArguments); 7905 } 7906 7907 7908 // Generate the certificate signing request. 7909 final PKCS10CertificateSigningRequest certificateSigningRequest; 7910 try 7911 { 7912 certificateSigningRequest = PKCS10CertificateSigningRequest. 7913 generateCertificateSigningRequest(signatureAlgorithmIdentifier, 7914 keyPair, subjectDN, extensions); 7915 } 7916 catch (final Exception e) 7917 { 7918 Debug.debugException(e); 7919 wrapErr(0, WRAP_COLUMN, 7920 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CSR.get()); 7921 e.printStackTrace(getErr()); 7922 return ResultCode.LOCAL_ERROR; 7923 } 7924 7925 7926 // Write the generated certificate signing request to the appropriate 7927 // location. 7928 try 7929 { 7930 final PrintStream ps; 7931 if (outputFile == null) 7932 { 7933 ps = getOut(); 7934 } 7935 else 7936 { 7937 ps = new PrintStream(outputFile); 7938 } 7939 7940 if (outputPEM) 7941 { 7942 writePEMCertificateSigningRequest(ps, 7943 certificateSigningRequest. 7944 getPKCS10CertificateSigningRequestBytes()); 7945 } 7946 else 7947 { 7948 ps.write(certificateSigningRequest. 7949 getPKCS10CertificateSigningRequestBytes()); 7950 } 7951 7952 if (outputFile != null) 7953 { 7954 ps.close(); 7955 } 7956 } 7957 catch (final Exception e) 7958 { 7959 Debug.debugException(e); 7960 wrapErr(0, WRAP_COLUMN, 7961 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CSR.get()); 7962 e.printStackTrace(getErr()); 7963 return ResultCode.LOCAL_ERROR; 7964 } 7965 7966 7967 // If the certificate signing request was written to an output file, 7968 // then let the user know that it was successful. If it was written to 7969 // standard output, then we don't need to tell them because they'll be 7970 // able to see it. 7971 if (outputFile != null) 7972 { 7973 out(); 7974 wrapOut(0, WRAP_COLUMN, 7975 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_CSR.get( 7976 outputFile.getAbsolutePath())); 7977 } 7978 7979 return ResultCode.SUCCESS; 7980 } 7981 7982 7983 // If we've gotten here, then we should be signing a certificate signing 7984 // request. Make sure that the keystore already has a private key entry 7985 // with the specified alias. 7986 Validator.ensureTrue(isSignCSR); 7987 if (! hasKeyAlias(keystore, alias)) 7988 { 7989 if (hasCertificateAlias(keystore, alias)) 7990 { 7991 wrapErr(0, WRAP_COLUMN, 7992 ERR_MANAGE_CERTS_GEN_CERT_SIGN_ALIAS_IS_CERT.get(alias, 7993 keystorePath.getAbsolutePath())); 7994 return ResultCode.PARAM_ERROR; 7995 } 7996 else 7997 { 7998 wrapErr(0, WRAP_COLUMN, 7999 ERR_MANAGE_CERTS_GEN_CERT_SIGN_NO_SUCH_ALIAS.get(alias, 8000 keystorePath.getAbsolutePath())); 8001 return ResultCode.PARAM_ERROR; 8002 } 8003 } 8004 8005 8006 // Get the signing certificate and its key pair. 8007 final PrivateKey issuerPrivateKey; 8008 final X509Certificate issuerCertificate; 8009 try 8010 { 8011 final Certificate[] chain = keystore.getCertificateChain(alias); 8012 issuerCertificate = new X509Certificate(chain[0].getEncoded()); 8013 8014 issuerPrivateKey = 8015 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 8016 } 8017 catch (final Exception e) 8018 { 8019 Debug.debugException(e); 8020 wrapErr(0, WRAP_COLUMN, 8021 ERR_MANAGE_CERTS_GEN_CERT_SIGN_CANNOT_GET_SIGNING_CERT.get(alias)); 8022 e.printStackTrace(getErr()); 8023 return ResultCode.LOCAL_ERROR; 8024 } 8025 8026 8027 // Make sure that we can decode the certificate signing request. 8028 final PKCS10CertificateSigningRequest csr; 8029 try 8030 { 8031 csr = readCertificateSigningRequestFromFile(inputFile); 8032 } 8033 catch (final LDAPException le) 8034 { 8035 Debug.debugException(le); 8036 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8037 return le.getResultCode(); 8038 } 8039 8040 8041 // Make sure that we can verify the certificate signing request's signature. 8042 try 8043 { 8044 csr.verifySignature(); 8045 } 8046 catch (final CertException ce) 8047 { 8048 Debug.debugException(ce); 8049 wrapErr(0, WRAP_COLUMN, ce.getMessage()); 8050 return ResultCode.PARAM_ERROR; 8051 } 8052 8053 8054 // Prompt about whether to sign the request, if appropriate. 8055 if (! noPrompt) 8056 { 8057 out(); 8058 wrapOut(0, WRAP_COLUMN, 8059 INFO_MANAGE_CERTS_GEN_CERT_SIGN_CONFIRM.get()); 8060 out(); 8061 printCertificateSigningRequest(csr, false, ""); 8062 out(); 8063 8064 try 8065 { 8066 if (! promptForYesNo( 8067 INFO_MANAGE_CERTS_GEN_CERT_PROMPT_SIGN.get())) 8068 { 8069 wrapErr(0, WRAP_COLUMN, 8070 ERR_MANAGE_CERTS_GEN_CERT_SIGN_CANCELED.get()); 8071 return ResultCode.USER_CANCELED; 8072 } 8073 } 8074 catch (final LDAPException le) 8075 { 8076 Debug.debugException(le); 8077 err(); 8078 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8079 return le.getResultCode(); 8080 } 8081 } 8082 8083 8084 // Read the certificate signing request and see if we need to take values 8085 // from it. 8086 if ((subjectDN == null) || (signatureAlgorithmIdentifier == null) || 8087 includeRequestedExtensions) 8088 { 8089 if (subjectDN == null) 8090 { 8091 subjectDN = csr.getSubjectDN(); 8092 } 8093 8094 if (signatureAlgorithmIdentifier == null) 8095 { 8096 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forOID( 8097 csr.getSignatureAlgorithmOID()); 8098 if (signatureAlgorithmIdentifier == null) 8099 { 8100 wrapErr(0, WRAP_COLUMN, 8101 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG_IN_CSR.get( 8102 csr.getSignatureAlgorithmOID())); 8103 return ResultCode.PARAM_ERROR; 8104 } 8105 else 8106 { 8107 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 8108 } 8109 } 8110 8111 if (includeRequestedExtensions) 8112 { 8113 for (final X509CertificateExtension extension : csr.getExtensions()) 8114 { 8115 if ((extension instanceof AuthorityKeyIdentifierExtension) || 8116 (extension instanceof IssuerAlternativeNameExtension)) 8117 { 8118 // This extension applies to the issuer. We won't include this in 8119 // the set of inherited extensions. 8120 } 8121 else if (extension instanceof SubjectKeyIdentifierExtension) 8122 { 8123 // The generated certificate will automatically include a subject 8124 // key identifier extension, so we don't need to include it. 8125 } 8126 else if (extension instanceof BasicConstraintsExtension) 8127 { 8128 // Don't override a value already provided on the command line. 8129 if (basicConstraints == null) 8130 { 8131 basicConstraints = (BasicConstraintsExtension) extension; 8132 extensionList.add(basicConstraints); 8133 } 8134 } 8135 else if (extension instanceof ExtendedKeyUsageExtension) 8136 { 8137 // Don't override a value already provided on the command line. 8138 if (extendedKeyUsage == null) 8139 { 8140 extendedKeyUsage = (ExtendedKeyUsageExtension) extension; 8141 extensionList.add(extendedKeyUsage); 8142 } 8143 } 8144 else if (extension instanceof KeyUsageExtension) 8145 { 8146 // Don't override a value already provided on the command line. 8147 if (keyUsage == null) 8148 { 8149 keyUsage = (KeyUsageExtension) extension; 8150 extensionList.add(keyUsage); 8151 } 8152 } 8153 else if (extension instanceof SubjectAlternativeNameExtension) 8154 { 8155 // Although we could merge values, it's safer to not do that if any 8156 // subject alternative name values were provided on the command 8157 // line. 8158 if (sanValues.isEmpty()) 8159 { 8160 final SubjectAlternativeNameExtension e = 8161 (SubjectAlternativeNameExtension) extension; 8162 for (final String dnsName : e.getDNSNames()) 8163 { 8164 sanBuilder.addDNSName(dnsName); 8165 sanValues.add("DNS:" + dnsName); 8166 } 8167 8168 for (final InetAddress ipAddress : e.getIPAddresses()) 8169 { 8170 sanBuilder.addIPAddress(ipAddress); 8171 sanValues.add("IP:" + ipAddress.getHostAddress()); 8172 } 8173 8174 for (final String emailAddress : e.getRFC822Names()) 8175 { 8176 sanBuilder.addRFC822Name(emailAddress); 8177 sanValues.add("EMAIL:" + emailAddress); 8178 } 8179 8180 for (final String uri : e.getUniformResourceIdentifiers()) 8181 { 8182 sanBuilder.addUniformResourceIdentifier(uri); 8183 sanValues.add("URI:" + uri); 8184 } 8185 8186 for (final OID oid : e.getRegisteredIDs()) 8187 { 8188 sanBuilder.addRegisteredID(oid); 8189 sanValues.add("OID:" + oid.toString()); 8190 } 8191 8192 try 8193 { 8194 extensionList.add( 8195 new SubjectAlternativeNameExtension(false, 8196 sanBuilder.build())); 8197 } 8198 catch (final Exception ex) 8199 { 8200 // This should never happen. 8201 Debug.debugException(ex); 8202 throw new RuntimeException(ex); 8203 } 8204 } 8205 } 8206 else 8207 { 8208 genericExtensions.add(extension); 8209 extensionList.add(extension); 8210 } 8211 } 8212 } 8213 } 8214 8215 8216 // Generate the keytool arguments to use to sign the requested certificate. 8217 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8218 keytoolArguments.add("-gencert"); 8219 keytoolArguments.add("-keystore"); 8220 keytoolArguments.add(keystorePath.getAbsolutePath()); 8221 keytoolArguments.add("-storetype"); 8222 keytoolArguments.add(keystoreType); 8223 keytoolArguments.add("-storepass"); 8224 keytoolArguments.add("*****REDACTED*****"); 8225 keytoolArguments.add("-keypass"); 8226 keytoolArguments.add("*****REDACTED*****"); 8227 keytoolArguments.add("-alias"); 8228 keytoolArguments.add(alias); 8229 keytoolArguments.add("-dname"); 8230 keytoolArguments.add(subjectDN.toString()); 8231 keytoolArguments.add("-sigalg"); 8232 keytoolArguments.add(signatureAlgorithmName); 8233 keytoolArguments.add("-validity"); 8234 keytoolArguments.add(String.valueOf(daysValid)); 8235 8236 if (validityStartTime != null) 8237 { 8238 keytoolArguments.add("-startdate"); 8239 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 8240 } 8241 8242 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 8243 extendedKeyUsage, sanValues, ianValues, genericExtensions); 8244 8245 keytoolArguments.add("-infile"); 8246 keytoolArguments.add(inputFile.getAbsolutePath()); 8247 8248 if (outputFile != null) 8249 { 8250 keytoolArguments.add("-outfile"); 8251 keytoolArguments.add(outputFile.getAbsolutePath()); 8252 } 8253 8254 if (outputPEM) 8255 { 8256 keytoolArguments.add("-rfc"); 8257 } 8258 8259 if (displayKeytoolCommand) 8260 { 8261 displayKeytoolCommand(keytoolArguments); 8262 } 8263 8264 8265 // Generate the signed certificate. 8266 final long notBefore; 8267 if (validityStartTime == null) 8268 { 8269 notBefore = System.currentTimeMillis(); 8270 } 8271 else 8272 { 8273 notBefore = validityStartTime.getTime(); 8274 } 8275 8276 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 8277 8278 final X509CertificateExtension[] extensions = 8279 new X509CertificateExtension[extensionList.size()]; 8280 extensionList.toArray(extensions); 8281 8282 final X509Certificate signedCertificate; 8283 try 8284 { 8285 signedCertificate = X509Certificate.generateIssuerSignedCertificate( 8286 signatureAlgorithmIdentifier, issuerCertificate, issuerPrivateKey, 8287 csr.getPublicKeyAlgorithmOID(), 8288 csr.getPublicKeyAlgorithmParameters(), csr.getEncodedPublicKey(), 8289 csr.getDecodedPublicKey(), subjectDN, notBefore, notAfter, 8290 extensions); 8291 } 8292 catch (final Exception e) 8293 { 8294 Debug.debugException(e); 8295 wrapErr(0, WRAP_COLUMN, 8296 ERR_MANAGE_CERTS_GEN_CERT_ERROR_SIGNING_CERT.get()); 8297 e.printStackTrace(getErr()); 8298 return ResultCode.LOCAL_ERROR; 8299 } 8300 8301 8302 // Write the signed certificate signing request to the appropriate location. 8303 try 8304 { 8305 final PrintStream ps; 8306 if (outputFile == null) 8307 { 8308 ps = getOut(); 8309 } 8310 else 8311 { 8312 ps = new PrintStream(outputFile); 8313 } 8314 8315 if (outputPEM) 8316 { 8317 writePEMCertificate(ps, signedCertificate.getX509CertificateBytes()); 8318 } 8319 else 8320 { 8321 ps.write(signedCertificate.getX509CertificateBytes()); 8322 } 8323 8324 if (outputFile != null) 8325 { 8326 ps.close(); 8327 } 8328 } 8329 catch (final Exception e) 8330 { 8331 Debug.debugException(e); 8332 wrapErr(0, WRAP_COLUMN, 8333 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_SIGNED_CERT.get()); 8334 e.printStackTrace(getErr()); 8335 return ResultCode.LOCAL_ERROR; 8336 } 8337 8338 8339 // If the certificate signing request was written to an output file, 8340 // then let the user know that it was successful. If it was written to 8341 // standard output, then we don't need to tell them because they'll be 8342 // able to see it. 8343 if (outputFile != null) 8344 { 8345 out(); 8346 wrapOut(0, WRAP_COLUMN, 8347 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_SIGNED_CERT.get( 8348 outputFile.getAbsolutePath())); 8349 } 8350 8351 return ResultCode.SUCCESS; 8352 } 8353 8354 8355 8356 /** 8357 * Performs the necessary processing for the change-certificate-alias 8358 * subcommand. 8359 * 8360 * @return A result code that indicates whether the processing completed 8361 * successfully. 8362 */ 8363 @NotNull() 8364 private ResultCode doChangeCertificateAlias() 8365 { 8366 // Get the values of a number of configured arguments. 8367 final StringArgument currentAliasArgument = 8368 subCommandParser.getStringArgument("current-alias"); 8369 final String currentAlias = currentAliasArgument.getValue(); 8370 8371 final StringArgument newAliasArgument = 8372 subCommandParser.getStringArgument("new-alias"); 8373 final String newAlias = newAliasArgument.getValue(); 8374 8375 final String keystoreType; 8376 final File keystorePath = getKeystorePath(); 8377 try 8378 { 8379 keystoreType = inferKeystoreType(keystorePath); 8380 } 8381 catch (final LDAPException le) 8382 { 8383 Debug.debugException(le); 8384 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8385 return le.getResultCode(); 8386 } 8387 8388 final char[] keystorePassword; 8389 try 8390 { 8391 keystorePassword = getKeystorePassword(keystorePath); 8392 } 8393 catch (final LDAPException le) 8394 { 8395 Debug.debugException(le); 8396 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8397 return le.getResultCode(); 8398 } 8399 8400 8401 // Get the keystore. 8402 final KeyStore keystore; 8403 try 8404 { 8405 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 8406 } 8407 catch (final LDAPException le) 8408 { 8409 Debug.debugException(le); 8410 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8411 return le.getResultCode(); 8412 } 8413 8414 8415 // See if we need to use a private key password that is different from the 8416 // keystore password. 8417 final char[] privateKeyPassword; 8418 try 8419 { 8420 privateKeyPassword = 8421 getPrivateKeyPassword(keystore, currentAlias, keystorePassword); 8422 } 8423 catch (final LDAPException le) 8424 { 8425 Debug.debugException(le); 8426 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8427 return le.getResultCode(); 8428 } 8429 8430 8431 // Make sure that the keystore has an existing entry with the current alias. 8432 // It must be either a certificate entry or a private key entry. 8433 final Certificate existingCertificate; 8434 final Certificate[] existingCertificateChain; 8435 final PrivateKey existingPrivateKey; 8436 try 8437 { 8438 if (hasCertificateAlias(keystore, currentAlias)) 8439 { 8440 existingCertificate = keystore.getCertificate(currentAlias); 8441 existingCertificateChain = null; 8442 existingPrivateKey = null; 8443 } 8444 else if (hasKeyAlias(keystore, currentAlias)) 8445 { 8446 existingCertificateChain = keystore.getCertificateChain(currentAlias); 8447 existingPrivateKey = 8448 (PrivateKey) keystore.getKey(currentAlias, privateKeyPassword); 8449 existingCertificate = null; 8450 } 8451 else 8452 { 8453 wrapErr(0, WRAP_COLUMN, 8454 ERR_MANAGE_CERTS_CHANGE_ALIAS_NO_SUCH_ALIAS.get(currentAlias)); 8455 return ResultCode.PARAM_ERROR; 8456 } 8457 } 8458 catch (final Exception e) 8459 { 8460 Debug.debugException(e); 8461 wrapErr(0, WRAP_COLUMN, 8462 ERR_MANAGE_CERTS_CHANGE_ALIAS_CANNOT_GET_EXISTING_ENTRY.get( 8463 currentAlias)); 8464 e.printStackTrace(getErr()); 8465 return ResultCode.LOCAL_ERROR; 8466 } 8467 8468 8469 // Make sure that the keystore does not have an entry with the new alias. 8470 if (hasCertificateAlias(keystore, newAlias) || 8471 hasKeyAlias(keystore, newAlias)) 8472 { 8473 wrapErr(0, WRAP_COLUMN, 8474 ERR_MANAGE_CERTS_CHANGE_ALIAS_NEW_ALIAS_IN_USE.get(newAlias)); 8475 return ResultCode.PARAM_ERROR; 8476 } 8477 8478 8479 // Generate the keytool arguments to use to change the certificate alias. 8480 final BooleanArgument displayKeytoolCommandArgument = 8481 subCommandParser.getBooleanArgument("display-keytool-command"); 8482 if ((displayKeytoolCommandArgument != null) && 8483 displayKeytoolCommandArgument.isPresent()) 8484 { 8485 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8486 keytoolArguments.add("-changealias"); 8487 keytoolArguments.add("-keystore"); 8488 keytoolArguments.add(keystorePath.getAbsolutePath()); 8489 keytoolArguments.add("-storetype"); 8490 keytoolArguments.add(keystoreType); 8491 keytoolArguments.add("-storepass"); 8492 keytoolArguments.add("*****REDACTED*****"); 8493 keytoolArguments.add("-keypass"); 8494 keytoolArguments.add("*****REDACTED*****"); 8495 keytoolArguments.add("-alias"); 8496 keytoolArguments.add(currentAlias); 8497 keytoolArguments.add("-destalias"); 8498 keytoolArguments.add(newAlias); 8499 8500 displayKeytoolCommand(keytoolArguments); 8501 } 8502 8503 8504 // Update the keystore to remove the entry with the current alias and 8505 // re-write it with the new alias. 8506 try 8507 { 8508 keystore.deleteEntry(currentAlias); 8509 if (existingCertificate != null) 8510 { 8511 keystore.setCertificateEntry(newAlias, existingCertificate); 8512 } 8513 else 8514 { 8515 keystore.setKeyEntry(newAlias, existingPrivateKey, 8516 privateKeyPassword, existingCertificateChain); 8517 } 8518 8519 writeKeystore(keystore, keystorePath, keystorePassword); 8520 } 8521 catch (final Exception e) 8522 { 8523 Debug.debugException(e); 8524 wrapErr(0, WRAP_COLUMN, 8525 ERR_MANAGE_CERTS_CHANGE_ALIAS_CANNOT_UPDATE_KEYSTORE.get()); 8526 e.printStackTrace(getErr()); 8527 return ResultCode.LOCAL_ERROR; 8528 } 8529 8530 wrapOut(0, WRAP_COLUMN, 8531 INFO_MANAGE_CERTS_CHANGE_ALIAS_SUCCESSFUL.get(currentAlias, 8532 newAlias)); 8533 return ResultCode.SUCCESS; 8534 } 8535 8536 8537 8538 /** 8539 * Performs the necessary processing for the change-keystore-password 8540 * subcommand. 8541 * 8542 * @return A result code that indicates whether the processing completed 8543 * successfully. 8544 */ 8545 @NotNull() 8546 private ResultCode doChangeKeystorePassword() 8547 { 8548 // Get the values of a number of configured arguments. 8549 final String keystoreType; 8550 final File keystorePath = getKeystorePath(); 8551 try 8552 { 8553 keystoreType = inferKeystoreType(keystorePath); 8554 } 8555 catch (final LDAPException le) 8556 { 8557 Debug.debugException(le); 8558 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8559 return le.getResultCode(); 8560 } 8561 8562 final char[] currentKeystorePassword; 8563 try 8564 { 8565 currentKeystorePassword = getKeystorePassword(keystorePath, "current"); 8566 } 8567 catch (final LDAPException le) 8568 { 8569 Debug.debugException(le); 8570 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8571 return le.getResultCode(); 8572 } 8573 8574 final char[] newKeystorePassword; 8575 try 8576 { 8577 newKeystorePassword = getKeystorePassword(keystorePath, "new"); 8578 } 8579 catch (final LDAPException le) 8580 { 8581 Debug.debugException(le); 8582 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8583 return le.getResultCode(); 8584 } 8585 8586 8587 // Get the keystore. 8588 final KeyStore keystore; 8589 try 8590 { 8591 keystore = getKeystore(keystoreType, keystorePath, 8592 currentKeystorePassword); 8593 } 8594 catch (final LDAPException le) 8595 { 8596 Debug.debugException(le); 8597 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8598 return le.getResultCode(); 8599 } 8600 8601 8602 // Generate the keytool arguments to use to change the keystore password. 8603 final BooleanArgument displayKeytoolCommandArgument = 8604 subCommandParser.getBooleanArgument("display-keytool-command"); 8605 if ((displayKeytoolCommandArgument != null) && 8606 displayKeytoolCommandArgument.isPresent()) 8607 { 8608 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8609 keytoolArguments.add("-storepasswd"); 8610 keytoolArguments.add("-keystore"); 8611 keytoolArguments.add(keystorePath.getAbsolutePath()); 8612 keytoolArguments.add("-storetype"); 8613 keytoolArguments.add(keystoreType); 8614 keytoolArguments.add("-storepass"); 8615 keytoolArguments.add("*****REDACTED*****"); 8616 keytoolArguments.add("-new"); 8617 keytoolArguments.add("*****REDACTED*****"); 8618 8619 displayKeytoolCommand(keytoolArguments); 8620 } 8621 8622 8623 // Rewrite the keystore with the new password. 8624 try 8625 { 8626 writeKeystore(keystore, keystorePath, newKeystorePassword); 8627 } 8628 catch (final LDAPException le) 8629 { 8630 Debug.debugException(le); 8631 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8632 return le.getResultCode(); 8633 } 8634 8635 wrapOut(0, WRAP_COLUMN, 8636 INFO_MANAGE_CERTS_CHANGE_KS_PW_SUCCESSFUL.get( 8637 keystorePath.getAbsolutePath())); 8638 return ResultCode.SUCCESS; 8639 } 8640 8641 8642 8643 /** 8644 * Performs the necessary processing for the change-private-key-password 8645 * subcommand. 8646 * 8647 * @return A result code that indicates whether the processing completed 8648 * successfully. 8649 */ 8650 @NotNull() 8651 private ResultCode doChangePrivateKeyPassword() 8652 { 8653 // Get the values of a number of configured arguments. 8654 final StringArgument aliasArgument = 8655 subCommandParser.getStringArgument("alias"); 8656 final String alias = aliasArgument.getValue(); 8657 8658 final String keystoreType; 8659 final File keystorePath = getKeystorePath(); 8660 try 8661 { 8662 keystoreType = inferKeystoreType(keystorePath); 8663 } 8664 catch (final LDAPException le) 8665 { 8666 Debug.debugException(le); 8667 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8668 return le.getResultCode(); 8669 } 8670 8671 final char[] keystorePassword; 8672 try 8673 { 8674 keystorePassword = getKeystorePassword(keystorePath); 8675 } 8676 catch (final LDAPException le) 8677 { 8678 Debug.debugException(le); 8679 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8680 return le.getResultCode(); 8681 } 8682 8683 8684 // Get the keystore. 8685 final KeyStore keystore; 8686 try 8687 { 8688 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 8689 } 8690 catch (final LDAPException le) 8691 { 8692 Debug.debugException(le); 8693 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8694 return le.getResultCode(); 8695 } 8696 8697 8698 // Make sure that the keystore has a key entry with the specified alias. 8699 if (hasCertificateAlias(keystore, alias)) 8700 { 8701 wrapErr(0, WRAP_COLUMN, 8702 ERR_MANAGE_CERTS_CHANGE_PK_PW_ALIAS_IS_CERT.get(alias)); 8703 return ResultCode.PARAM_ERROR; 8704 } 8705 else if (! hasKeyAlias(keystore, alias)) 8706 { 8707 wrapErr(0, WRAP_COLUMN, 8708 ERR_MANAGE_CERTS_CHANGE_PK_PW_NO_SUCH_ALIAS.get(alias)); 8709 return ResultCode.PARAM_ERROR; 8710 } 8711 8712 8713 // Get the current and new private key passwords. 8714 final char[] currentPrivateKeyPassword; 8715 try 8716 { 8717 currentPrivateKeyPassword = 8718 getPrivateKeyPassword(keystore, alias, "current", keystorePassword); 8719 } 8720 catch (final LDAPException le) 8721 { 8722 Debug.debugException(le); 8723 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8724 return le.getResultCode(); 8725 } 8726 8727 final char[] newPrivateKeyPassword; 8728 try 8729 { 8730 newPrivateKeyPassword = 8731 getPrivateKeyPassword(keystore, alias, "new", keystorePassword); 8732 } 8733 catch (final LDAPException le) 8734 { 8735 Debug.debugException(le); 8736 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8737 return le.getResultCode(); 8738 } 8739 8740 8741 // Generate the keytool arguments to use to change the private key. 8742 final BooleanArgument displayKeytoolCommandArgument = 8743 subCommandParser.getBooleanArgument("display-keytool-command"); 8744 if ((displayKeytoolCommandArgument != null) && 8745 displayKeytoolCommandArgument.isPresent()) 8746 { 8747 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 8748 keytoolArguments.add("-keypasswd"); 8749 keytoolArguments.add("-keystore"); 8750 keytoolArguments.add(keystorePath.getAbsolutePath()); 8751 keytoolArguments.add("-storetype"); 8752 keytoolArguments.add(keystoreType); 8753 keytoolArguments.add("-storepass"); 8754 keytoolArguments.add("*****REDACTED*****"); 8755 keytoolArguments.add("-alias"); 8756 keytoolArguments.add(alias); 8757 keytoolArguments.add("-keypass"); 8758 keytoolArguments.add("*****REDACTED*****"); 8759 keytoolArguments.add("-new"); 8760 keytoolArguments.add("*****REDACTED*****"); 8761 8762 displayKeytoolCommand(keytoolArguments); 8763 } 8764 8765 8766 // Get the contents of the private key entry. 8767 final Certificate[] chain; 8768 final PrivateKey privateKey; 8769 try 8770 { 8771 chain = keystore.getCertificateChain(alias); 8772 privateKey = 8773 (PrivateKey) keystore.getKey(alias, currentPrivateKeyPassword); 8774 } 8775 catch (final UnrecoverableKeyException e) 8776 { 8777 Debug.debugException(e); 8778 wrapErr(0, WRAP_COLUMN, 8779 ERR_MANAGE_CERTS_CHANGE_PK_PW_WRONG_PK_PW.get(alias)); 8780 return ResultCode.PARAM_ERROR; 8781 } 8782 catch (final Exception e) 8783 { 8784 Debug.debugException(e); 8785 wrapErr(0, WRAP_COLUMN, 8786 ERR_MANAGE_CERTS_CHANGE_PK_PW_CANNOT_GET_PK.get(alias)); 8787 e.printStackTrace(getErr()); 8788 return ResultCode.LOCAL_ERROR; 8789 } 8790 8791 8792 // Remove the existing key entry and re-add it with the new password. 8793 try 8794 { 8795 keystore.deleteEntry(alias); 8796 keystore.setKeyEntry(alias, privateKey, newPrivateKeyPassword, chain); 8797 writeKeystore(keystore, keystorePath, keystorePassword); 8798 } 8799 catch (final Exception e) 8800 { 8801 Debug.debugException(e); 8802 wrapErr(0, WRAP_COLUMN, 8803 ERR_MANAGE_CERTS_CHANGE_PK_PW_CANNOT_UPDATE_KS.get()); 8804 e.printStackTrace(getErr()); 8805 return ResultCode.LOCAL_ERROR; 8806 } 8807 8808 wrapOut(0, WRAP_COLUMN, 8809 INFO_MANAGE_CERTS_CHANGE_PK_PW_SUCCESSFUL.get(alias)); 8810 return ResultCode.SUCCESS; 8811 } 8812 8813 8814 8815 /** 8816 * Performs the necessary processing for the copy-keystore subcommand. 8817 * 8818 * @return A result code that indicates whether the processing completed 8819 * successfully. 8820 */ 8821 @NotNull() 8822 private ResultCode doCopyKeystore() 8823 { 8824 // Get the source key store. 8825 final String sourceKeyStoreType; 8826 final File sourceKeyStorePath = getKeystorePath("source-keystore"); 8827 try 8828 { 8829 sourceKeyStoreType = inferKeystoreType(sourceKeyStorePath, "source"); 8830 } 8831 catch (final LDAPException le) 8832 { 8833 Debug.debugException(le); 8834 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8835 return le.getResultCode(); 8836 } 8837 8838 final char[] sourceKeyStorePassword; 8839 try 8840 { 8841 sourceKeyStorePassword = 8842 getKeystorePassword(sourceKeyStorePath, "source"); 8843 } 8844 catch (final LDAPException le) 8845 { 8846 Debug.debugException(le); 8847 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8848 return le.getResultCode(); 8849 } 8850 8851 final KeyStore sourceKeyStore; 8852 try 8853 { 8854 sourceKeyStore = getKeystore(sourceKeyStoreType, sourceKeyStorePath, 8855 sourceKeyStorePassword); 8856 } 8857 catch (final LDAPException le) 8858 { 8859 Debug.debugException(le); 8860 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8861 return le.getResultCode(); 8862 } 8863 8864 8865 // Get the destination key store. 8866 final String destinationKeyStoreType; 8867 final File destinationKeyStorePath = 8868 getKeystorePath("destination-keystore"); 8869 try 8870 { 8871 destinationKeyStoreType = inferKeystoreType(destinationKeyStorePath, 8872 "destination"); 8873 } 8874 catch (final LDAPException le) 8875 { 8876 Debug.debugException(le); 8877 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8878 return le.getResultCode(); 8879 } 8880 8881 final boolean destinationExists = destinationKeyStorePath.exists(); 8882 8883 char[] destinationKeyStorePassword; 8884 try 8885 { 8886 destinationKeyStorePassword = 8887 getKeystorePassword(destinationKeyStorePath, "destination"); 8888 if (destinationKeyStorePassword == null) 8889 { 8890 destinationKeyStorePassword = sourceKeyStorePassword; 8891 } 8892 } 8893 catch (final LDAPException le) 8894 { 8895 Debug.debugException(le); 8896 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8897 return le.getResultCode(); 8898 } 8899 8900 final KeyStore destinationKeyStore; 8901 try 8902 { 8903 destinationKeyStore = getKeystore(destinationKeyStoreType, 8904 destinationKeyStorePath, destinationKeyStorePassword); 8905 } 8906 catch (final LDAPException le) 8907 { 8908 Debug.debugException(le); 8909 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8910 return le.getResultCode(); 8911 } 8912 8913 8914 // Get the value of the aliases argument, if it was provided. 8915 final Set<String> aliases = new LinkedHashSet<>(); 8916 try 8917 { 8918 final StringArgument aliasArg = 8919 subCommandParser.getStringArgument("alias"); 8920 if ((aliasArg != null) && aliasArg.isPresent()) 8921 { 8922 for (final String alias : aliasArg.getValues()) 8923 { 8924 aliases.add(alias); 8925 if (! sourceKeyStore.containsAlias(alias)) 8926 { 8927 wrapErr(0, WRAP_COLUMN, 8928 ERR_MANAGE_CERTS_COPY_KS_NO_SUCH_SOURCE_ALIAS.get( 8929 sourceKeyStorePath.getAbsolutePath(), alias)); 8930 return ResultCode.PARAM_ERROR; 8931 } 8932 } 8933 } 8934 else 8935 { 8936 final Enumeration<String> sourceAliases = sourceKeyStore.aliases(); 8937 while (sourceAliases.hasMoreElements()) 8938 { 8939 aliases.add(sourceAliases.nextElement()); 8940 } 8941 } 8942 } 8943 catch (final Exception e) 8944 { 8945 Debug.debugException(e); 8946 wrapErr(0, WRAP_COLUMN, 8947 ERR_MANAGE_CERTS_COPY_KS_CANNOT_GET_SOURCE_ALIASES.get( 8948 sourceKeyStorePath.getAbsolutePath(), 8949 StaticUtils.getExceptionMessage(e))); 8950 return ResultCode.LOCAL_ERROR; 8951 } 8952 8953 8954 // If the set of aliases is empty and the destination key store already 8955 // exists, then exit without doing anything. 8956 if (aliases.isEmpty() && destinationExists) 8957 { 8958 wrapOut(0, WRAP_COLUMN, 8959 INFO_MANAGE_CERTS_COPY_KS_NO_CERTS_COPIED_EXISTING_KS.get( 8960 sourceKeyStorePath.getAbsolutePath(), 8961 destinationKeyStorePath.getAbsolutePath())); 8962 return ResultCode.SUCCESS; 8963 } 8964 8965 8966 // Make sure that none of the target aliases exist in the destination key 8967 // store. 8968 for (final String alias : aliases) 8969 { 8970 try 8971 { 8972 if (destinationKeyStore.containsAlias(alias)) 8973 { 8974 wrapErr(0, WRAP_COLUMN, 8975 ERR_MANAGE_CERTS_COPY_KS_CONFLICTING_ALIAS.get(alias, 8976 destinationKeyStorePath.getAbsolutePath(), 8977 subCommandParser.getCommandName())); 8978 return ResultCode.CONSTRAINT_VIOLATION; 8979 } 8980 } 8981 catch (final Exception e) 8982 { 8983 Debug.debugException(e); 8984 wrapErr(0, WRAP_COLUMN, 8985 ERR_MANAGE_CERTS_COPY_KS_CANNOT_CHECK_DEST_ALIAS.get(alias, 8986 destinationKeyStorePath.getAbsolutePath(), 8987 StaticUtils.getExceptionMessage(e))); 8988 return ResultCode.LOCAL_ERROR; 8989 } 8990 } 8991 8992 8993 // Copy each of the targeted entries from the source key store into the 8994 // destination key store. 8995 char[] sourcePrivateKeyPassword = null; 8996 char[] destinationPrivateKeyPassword = null; 8997 for (final String alias : aliases) 8998 { 8999 try 9000 { 9001 if (sourceKeyStore.isCertificateEntry(alias)) 9002 { 9003 final Certificate certificate = sourceKeyStore.getCertificate(alias); 9004 destinationKeyStore.setCertificateEntry(alias, certificate); 9005 } 9006 else 9007 { 9008 if (sourcePrivateKeyPassword == null) 9009 { 9010 sourcePrivateKeyPassword = getPrivateKeyPassword(sourceKeyStore, 9011 alias, "source", sourceKeyStorePassword); 9012 } 9013 9014 if (destinationPrivateKeyPassword == null) 9015 { 9016 destinationPrivateKeyPassword = getPrivateKeyPassword( 9017 destinationKeyStore, alias, "destination", 9018 destinationKeyStorePassword); 9019 } 9020 9021 final Certificate[] chain = sourceKeyStore.getCertificateChain(alias); 9022 final Key key = 9023 sourceKeyStore.getKey(alias, sourcePrivateKeyPassword); 9024 destinationKeyStore.setKeyEntry(alias, key, 9025 destinationPrivateKeyPassword, chain); 9026 } 9027 } 9028 catch (final Exception e) 9029 { 9030 Debug.debugException(e); 9031 wrapErr(0, WRAP_COLUMN, 9032 ERR_MANAGE_CERTS_COPY_KS_ERROR_COPYING_ENTRY.get(alias, 9033 sourceKeyStorePath.getAbsolutePath(), 9034 destinationKeyStorePath.getAbsolutePath(), 9035 StaticUtils.getExceptionMessage(e))); 9036 return ResultCode.LOCAL_ERROR; 9037 } 9038 } 9039 9040 9041 // Rewrite the destination keystore. 9042 try 9043 { 9044 writeKeystore(destinationKeyStore, destinationKeyStorePath, 9045 destinationKeyStorePassword); 9046 } 9047 catch (final LDAPException le) 9048 { 9049 Debug.debugException(le); 9050 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9051 return le.getResultCode(); 9052 } 9053 9054 if (aliases.isEmpty()) 9055 { 9056 // This should only happen if the alias argument was not provided, the 9057 // source key store is empty, and the destination key store doesn't exist. 9058 // In that case, the destination key store will have been created. 9059 wrapOut(0, WRAP_COLUMN, 9060 INFO_MANAGE_CERTS_COPY_KS_NO_CERTS_COPIED_KS_CREATED.get( 9061 sourceKeyStorePath.getAbsolutePath(), 9062 destinationKeyStoreType, 9063 destinationKeyStorePath.getAbsolutePath())); 9064 } 9065 else 9066 { 9067 // Write a message about the entries that were successfully copied. 9068 wrapOut(0, WRAP_COLUMN, 9069 INFO_MANAGE_CERTS_COPY_KS_CERTS_COPIED_HEADER.get( 9070 sourceKeyStorePath.getAbsolutePath(), 9071 destinationKeyStoreType, 9072 destinationKeyStorePath.getAbsolutePath())); 9073 for (final String alias : aliases) 9074 { 9075 out("* ", alias); 9076 } 9077 } 9078 9079 return ResultCode.SUCCESS; 9080 } 9081 9082 9083 9084 /** 9085 * Performs the necessary processing for the retrieve-server-certificate 9086 * subcommand. 9087 * 9088 * @return A result code that indicates whether the processing completed 9089 * successfully. 9090 */ 9091 @NotNull() 9092 private ResultCode doRetrieveServerCertificate() 9093 { 9094 // Get the values of a number of configured arguments. 9095 final StringArgument hostnameArgument = 9096 subCommandParser.getStringArgument("hostname"); 9097 final String hostname = hostnameArgument.getValue(); 9098 9099 final IntegerArgument portArgument = 9100 subCommandParser.getIntegerArgument("port"); 9101 final int port = portArgument.getValue(); 9102 9103 final BooleanArgument useLDAPStartTLSArgument = 9104 subCommandParser.getBooleanArgument("use-ldap-start-tls"); 9105 final boolean useLDAPStartTLS = 9106 ((useLDAPStartTLSArgument != null) && 9107 useLDAPStartTLSArgument.isPresent()); 9108 9109 final BooleanArgument onlyPeerArgument = 9110 subCommandParser.getBooleanArgument("only-peer-certificate"); 9111 final boolean onlyPeer = 9112 ((onlyPeerArgument != null) && onlyPeerArgument.isPresent()); 9113 9114 final BooleanArgument verboseArgument = 9115 subCommandParser.getBooleanArgument("verbose"); 9116 final boolean verbose = 9117 ((verboseArgument != null) && verboseArgument.isPresent()); 9118 9119 boolean outputPEM = true; 9120 final StringArgument outputFormatArgument = 9121 subCommandParser.getStringArgument("output-format"); 9122 if ((outputFormatArgument != null) && outputFormatArgument.isPresent()) 9123 { 9124 final String format = outputFormatArgument.getValue().toLowerCase(); 9125 if (format.equals("der") || format.equals("binary") || 9126 format.equals("bin")) 9127 { 9128 outputPEM = false; 9129 } 9130 } 9131 9132 File outputFile = null; 9133 final FileArgument outputFileArgument = 9134 subCommandParser.getFileArgument("output-file"); 9135 if ((outputFileArgument != null) && outputFileArgument.isPresent()) 9136 { 9137 outputFile = outputFileArgument.getValue(); 9138 } 9139 9140 9141 // Spawn a background thread to establish a connection and get the 9142 // certificate chain from the target server. 9143 final LinkedBlockingQueue<Object> responseQueue = 9144 new LinkedBlockingQueue<>(10); 9145 final ManageCertificatesServerCertificateCollector certificateCollector = 9146 new ManageCertificatesServerCertificateCollector(this, hostname, port, 9147 useLDAPStartTLS, verbose, responseQueue); 9148 certificateCollector.start(); 9149 9150 Object responseObject = 9151 ERR_MANAGE_CERTS_RETRIEVE_CERT_NO_CERT_CHAIN_RECEIVED.get( 9152 hostname + ':' + port); 9153 try 9154 { 9155 responseObject = responseQueue.poll(90L, TimeUnit.SECONDS); 9156 } 9157 catch (final Exception e) 9158 { 9159 Debug.debugException(e); 9160 } 9161 9162 final X509Certificate[] chain; 9163 if (responseObject instanceof X509Certificate[]) 9164 { 9165 chain = (X509Certificate[]) responseObject; 9166 if (chain.length == 0) 9167 { 9168 wrapErr(0, WRAP_COLUMN, 9169 ERR_MANAGE_CERTS_RETRIEVE_CERT_EMPTY_CHAIN.get()); 9170 return ResultCode.NO_RESULTS_RETURNED; 9171 } 9172 } 9173 else if (responseObject instanceof CertException) 9174 { 9175 // The error message will have already been recorded by the collector 9176 // thread, so we can just return a non-success result. 9177 return ResultCode.LOCAL_ERROR; 9178 } 9179 else 9180 { 9181 wrapErr(0, WRAP_COLUMN, String.valueOf(responseObject)); 9182 return ResultCode.LOCAL_ERROR; 9183 } 9184 9185 try 9186 { 9187 certificateCollector.join(10_000L); 9188 } 9189 catch (final Exception e) 9190 { 9191 Debug.debugException(e); 9192 } 9193 9194 9195 // If the certificates should be written to a file, then do that now. 9196 if (outputFile != null) 9197 { 9198 try (PrintStream s = new PrintStream(outputFile)) 9199 { 9200 for (final X509Certificate c : chain) 9201 { 9202 if (outputPEM) 9203 { 9204 writePEMCertificate(s, c.getX509CertificateBytes()); 9205 } 9206 else 9207 { 9208 s.write(c.getX509CertificateBytes()); 9209 } 9210 9211 if (onlyPeer) 9212 { 9213 break; 9214 } 9215 } 9216 } 9217 catch (final Exception e) 9218 { 9219 Debug.debugException(e); 9220 wrapErr(0, WRAP_COLUMN, 9221 ERR_MANAGE_CERTS_RETRIEVE_CERT_CANNOT_WRITE_TO_FILE.get( 9222 outputFile.getAbsolutePath(), 9223 StaticUtils.getExceptionMessage(e))); 9224 return ResultCode.LOCAL_ERROR; 9225 } 9226 } 9227 9228 9229 // Display information about the certificates. 9230 for (int i=0; i < chain.length; i++) 9231 { 9232 if (verbose || (i > 0)) 9233 { 9234 out(); 9235 out(); 9236 } 9237 9238 if ((! onlyPeer) && (chain.length > 1)) 9239 { 9240 wrapOut(0, WRAP_COLUMN, 9241 INFO_MANAGE_CERTS_RETRIEVE_CERT_DISPLAY_HEADER.get((i+1), 9242 chain.length)); 9243 out(); 9244 } 9245 9246 final X509Certificate c = chain[i]; 9247 writePEMCertificate(getOut(), c.getX509CertificateBytes()); 9248 out(); 9249 printCertificate(c, "", verbose); 9250 9251 if (onlyPeer) 9252 { 9253 break; 9254 } 9255 } 9256 9257 return ResultCode.SUCCESS; 9258 } 9259 9260 9261 9262 /** 9263 * Performs the necessary processing for the trust-server-certificate 9264 * subcommand. 9265 * 9266 * @return A result code that indicates whether the processing completed 9267 * successfully. 9268 */ 9269 @NotNull() 9270 private ResultCode doTrustServerCertificate() 9271 { 9272 // Get the values of a number of configured arguments. 9273 final StringArgument hostnameArgument = 9274 subCommandParser.getStringArgument("hostname"); 9275 final String hostname = hostnameArgument.getValue(); 9276 9277 final IntegerArgument portArgument = 9278 subCommandParser.getIntegerArgument("port"); 9279 final int port = portArgument.getValue(); 9280 9281 final String alias; 9282 final StringArgument aliasArgument = 9283 subCommandParser.getStringArgument("alias"); 9284 if ((aliasArgument != null) && aliasArgument.isPresent()) 9285 { 9286 alias = aliasArgument.getValue(); 9287 } 9288 else 9289 { 9290 alias = hostname + ':' + port; 9291 } 9292 9293 final BooleanArgument useLDAPStartTLSArgument = 9294 subCommandParser.getBooleanArgument("use-ldap-start-tls"); 9295 final boolean useLDAPStartTLS = 9296 ((useLDAPStartTLSArgument != null) && 9297 useLDAPStartTLSArgument.isPresent()); 9298 9299 final BooleanArgument issuersOnlyArgument = 9300 subCommandParser.getBooleanArgument("issuers-only"); 9301 final boolean issuersOnly = 9302 ((issuersOnlyArgument != null) && issuersOnlyArgument.isPresent()); 9303 9304 final BooleanArgument noPromptArgument = 9305 subCommandParser.getBooleanArgument("no-prompt"); 9306 final boolean noPrompt = 9307 ((noPromptArgument != null) && noPromptArgument.isPresent()); 9308 9309 final BooleanArgument verboseArgument = 9310 subCommandParser.getBooleanArgument("verbose"); 9311 final boolean verbose = 9312 ((verboseArgument != null) && verboseArgument.isPresent()); 9313 9314 final String keystoreType; 9315 final File keystorePath = getKeystorePath(); 9316 final boolean isNewKeystore = (! keystorePath.exists()); 9317 try 9318 { 9319 keystoreType = inferKeystoreType(keystorePath); 9320 } 9321 catch (final LDAPException le) 9322 { 9323 Debug.debugException(le); 9324 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9325 return le.getResultCode(); 9326 } 9327 9328 final char[] keystorePassword; 9329 try 9330 { 9331 keystorePassword = getKeystorePassword(keystorePath); 9332 } 9333 catch (final LDAPException le) 9334 { 9335 Debug.debugException(le); 9336 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9337 return le.getResultCode(); 9338 } 9339 9340 9341 // Get the keystore. 9342 final KeyStore keystore; 9343 try 9344 { 9345 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 9346 } 9347 catch (final LDAPException le) 9348 { 9349 Debug.debugException(le); 9350 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9351 return le.getResultCode(); 9352 } 9353 9354 9355 // Make sure that the specified alias is not already in use. 9356 if (hasCertificateAlias(keystore, alias) || 9357 hasKeyAlias(keystore, alias)) 9358 { 9359 wrapErr(0, WRAP_COLUMN, 9360 ERR_MANAGE_CERTS_TRUST_SERVER_ALIAS_IN_USE.get(alias)); 9361 return ResultCode.PARAM_ERROR; 9362 } 9363 9364 9365 // Spawn a background thread to establish a connection and get the 9366 // certificate chain from the target server. 9367 final LinkedBlockingQueue<Object> responseQueue = 9368 new LinkedBlockingQueue<>(10); 9369 final ManageCertificatesServerCertificateCollector certificateCollector = 9370 new ManageCertificatesServerCertificateCollector(this, hostname, port, 9371 useLDAPStartTLS, verbose, responseQueue); 9372 certificateCollector.start(); 9373 9374 Object responseObject = 9375 ERR_MANAGE_CERTS_TRUST_SERVER_NO_CERT_CHAIN_RECEIVED.get( 9376 hostname + ':' + port); 9377 try 9378 { 9379 responseObject = responseQueue.poll(90L, TimeUnit.SECONDS); 9380 } 9381 catch (final Exception e) 9382 { 9383 Debug.debugException(e); 9384 } 9385 9386 final X509Certificate[] chain; 9387 if (responseObject instanceof X509Certificate[]) 9388 { 9389 chain = (X509Certificate[]) responseObject; 9390 } 9391 else if (responseObject instanceof CertException) 9392 { 9393 // The error message will have already been recorded by the collector 9394 // thread, so we can just return a non-success result. 9395 return ResultCode.LOCAL_ERROR; 9396 } 9397 else 9398 { 9399 wrapErr(0, WRAP_COLUMN, String.valueOf(responseObject)); 9400 return ResultCode.LOCAL_ERROR; 9401 } 9402 9403 try 9404 { 9405 certificateCollector.join(10_000L); 9406 } 9407 catch (final Exception e) 9408 { 9409 Debug.debugException(e); 9410 } 9411 9412 9413 // If we should prompt the user about whether to trust the certificates, 9414 // then do so now. 9415 if (! noPrompt) 9416 { 9417 out(); 9418 wrapOut(0, WRAP_COLUMN, 9419 INFO_MANAGE_CERTS_TRUST_SERVER_RETRIEVED_CHAIN.get( 9420 hostname + ':' + port)); 9421 9422 boolean isFirst = true; 9423 for (final X509Certificate c : chain) 9424 { 9425 out(); 9426 9427 if (isFirst) 9428 { 9429 isFirst = false; 9430 if (issuersOnly && (chain.length > 1)) 9431 { 9432 wrapOut(0, WRAP_COLUMN, 9433 INFO_MANAGE_CERTS_TRUST_SERVER_NOTE_OMITTED.get()); 9434 out(); 9435 } 9436 } 9437 9438 printCertificate(c, "", verbose); 9439 } 9440 9441 out(); 9442 9443 try 9444 { 9445 if (! promptForYesNo(INFO_MANAGE_CERTS_TRUST_SERVER_PROMPT_TRUST.get())) 9446 { 9447 wrapErr(0, WRAP_COLUMN, 9448 ERR_MANAGE_CERTS_TRUST_SERVER_CHAIN_REJECTED.get()); 9449 return ResultCode.USER_CANCELED; 9450 } 9451 } 9452 catch (final LDAPException le) 9453 { 9454 Debug.debugException(le); 9455 err(); 9456 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9457 return le.getResultCode(); 9458 } 9459 } 9460 9461 9462 // Add the certificates to the keystore. 9463 final LinkedHashMap<String,X509Certificate> certsByAlias = 9464 new LinkedHashMap<>(StaticUtils.computeMapCapacity(chain.length)); 9465 for (int i=0; i < chain.length; i++) 9466 { 9467 if (i == 0) 9468 { 9469 if (issuersOnly && (chain.length > 1)) 9470 { 9471 continue; 9472 } 9473 9474 certsByAlias.put(alias, chain[i]); 9475 } 9476 else if ((i == 1) && (chain.length == 2)) 9477 { 9478 certsByAlias.put(alias + "-issuer", chain[i]); 9479 } 9480 else 9481 { 9482 certsByAlias.put(alias + "-issuer-" + i, chain[i]); 9483 } 9484 } 9485 9486 for (final Map.Entry<String,X509Certificate> e : certsByAlias.entrySet()) 9487 { 9488 final String certAlias = e.getKey(); 9489 final X509Certificate cert = e.getValue(); 9490 9491 try 9492 { 9493 Validator.ensureFalse( 9494 (hasCertificateAlias(keystore, certAlias) || 9495 hasKeyAlias(keystore, certAlias)), 9496 "ERROR: Alias '" + certAlias + "' is already in use in the " + 9497 "keystore."); 9498 keystore.setCertificateEntry(certAlias, cert.toCertificate()); 9499 } 9500 catch (final Exception ex) 9501 { 9502 Debug.debugException(ex); 9503 wrapErr(0, WRAP_COLUMN, 9504 ERR_MANAGE_CERTS_TRUST_SERVER_ERROR_ADDING_CERT_TO_KS.get( 9505 cert.getSubjectDN())); 9506 ex.printStackTrace(getErr()); 9507 return ResultCode.LOCAL_ERROR; 9508 } 9509 } 9510 9511 9512 // Save the updated keystore. 9513 try 9514 { 9515 writeKeystore(keystore, keystorePath, keystorePassword); 9516 } 9517 catch (final LDAPException le) 9518 { 9519 Debug.debugException(le); 9520 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9521 return le.getResultCode(); 9522 } 9523 9524 if (isNewKeystore) 9525 { 9526 out(); 9527 wrapOut(0, WRAP_COLUMN, 9528 INFO_MANAGE_CERTS_TRUST_SERVER_CERT_CREATED_KEYSTORE.get( 9529 getUserFriendlyKeystoreType(keystoreType))); 9530 } 9531 9532 out(); 9533 if (certsByAlias.size() == 1) 9534 { 9535 wrapOut(0, WRAP_COLUMN, 9536 INFO_MANAGE_CERTS_TRUST_SERVER_ADDED_CERT_TO_KS.get()); 9537 } 9538 else 9539 { 9540 wrapOut(0, WRAP_COLUMN, 9541 INFO_MANAGE_CERTS_TRUST_SERVER_ADDED_CERTS_TO_KS.get( 9542 certsByAlias.size())); 9543 } 9544 9545 return ResultCode.SUCCESS; 9546 } 9547 9548 9549 9550 /** 9551 * Performs the necessary processing for the check-certificate-usability 9552 * subcommand. 9553 * 9554 * @return A result code that indicates whether the processing completed 9555 * successfully. 9556 */ 9557 @NotNull() 9558 private ResultCode doCheckCertificateUsability() 9559 { 9560 // Get the values of a number of configured arguments. 9561 final StringArgument aliasArgument = 9562 subCommandParser.getStringArgument("alias"); 9563 final String alias = aliasArgument.getValue(); 9564 9565 final String keystoreType; 9566 final File keystorePath = getKeystorePath(); 9567 try 9568 { 9569 keystoreType = inferKeystoreType(keystorePath); 9570 } 9571 catch (final LDAPException le) 9572 { 9573 Debug.debugException(le); 9574 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9575 return le.getResultCode(); 9576 } 9577 9578 final char[] keystorePassword; 9579 try 9580 { 9581 keystorePassword = getKeystorePassword(keystorePath); 9582 } 9583 catch (final LDAPException le) 9584 { 9585 Debug.debugException(le); 9586 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9587 return le.getResultCode(); 9588 } 9589 9590 9591 // Get the keystore. 9592 final KeyStore keystore; 9593 try 9594 { 9595 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 9596 } 9597 catch (final LDAPException le) 9598 { 9599 Debug.debugException(le); 9600 wrapErr(0, WRAP_COLUMN, le.getMessage()); 9601 return le.getResultCode(); 9602 } 9603 9604 9605 // Make sure that the specified entry exists in the keystore and is 9606 // associated with a certificate chain and a private key. 9607 final X509Certificate[] chain; 9608 if (hasKeyAlias(keystore, alias)) 9609 { 9610 try 9611 { 9612 final Certificate[] genericChain = keystore.getCertificateChain(alias); 9613 Validator.ensureTrue((genericChain.length > 0), 9614 "ERROR: The keystore has a private key entry for alias '" + 9615 alias + "', but the associated certificate chain is empty."); 9616 9617 chain = new X509Certificate[genericChain.length]; 9618 for (int i=0; i < genericChain.length; i++) 9619 { 9620 chain[i] = new X509Certificate(genericChain[i].getEncoded()); 9621 } 9622 9623 out(); 9624 wrapOut(0, WRAP_COLUMN, 9625 INFO_MANAGE_CERTS_CHECK_USABILITY_GOT_CHAIN.get(alias)); 9626 9627 for (final X509Certificate c : chain) 9628 { 9629 out(); 9630 printCertificate(c, "", false); 9631 } 9632 } 9633 catch (final Exception e) 9634 { 9635 Debug.debugException(e); 9636 wrapErr(0, WRAP_COLUMN, 9637 ERR_MANAGE_CERTS_CHECK_USABILITY_CANNOT_GET_CHAIN.get(alias)); 9638 e.printStackTrace(getErr()); 9639 return ResultCode.LOCAL_ERROR; 9640 } 9641 } 9642 else if (hasCertificateAlias(keystore, alias)) 9643 { 9644 wrapErr(0, WRAP_COLUMN, 9645 ERR_MANAGE_CERTS_CHECK_USABILITY_NO_PRIVATE_KEY.get(alias)); 9646 return ResultCode.PARAM_ERROR; 9647 } 9648 else 9649 { 9650 wrapErr(0, WRAP_COLUMN, 9651 ERR_MANAGE_CERTS_CHECK_USABILITY_NO_SUCH_ALIAS.get(alias)); 9652 return ResultCode.PARAM_ERROR; 9653 } 9654 9655 9656 // Check to see if the certificate is self-signed. If so, then that's a 9657 // warning. If not, then make sure that the chain is complete and that each 9658 // subsequent certificate is the issuer of the previous. 9659 int numWarnings = 0; 9660 int numErrors = 0; 9661 if (chain[0].isSelfSigned()) 9662 { 9663 err(); 9664 wrapErr(0, WRAP_COLUMN, 9665 WARN_MANAGE_CERTS_CHECK_USABILITY_CERT_IS_SELF_SIGNED.get( 9666 chain[0].getSubjectDN())); 9667 numWarnings++; 9668 } 9669 else if ((chain.length == 1) || (! chain[chain.length - 1].isSelfSigned())) 9670 { 9671 err(); 9672 wrapErr(0, WRAP_COLUMN, 9673 ERR_MANAGE_CERTS_CHECK_USABILITY_END_OF_CHAIN_NOT_SELF_SIGNED.get( 9674 alias)); 9675 numErrors++; 9676 } 9677 else 9678 { 9679 boolean chainError = false; 9680 final StringBuilder nonMatchReason = new StringBuilder(); 9681 for (int i=1; i < chain.length; i++) 9682 { 9683 if (! chain[i].isIssuerFor(chain[i-1], nonMatchReason)) 9684 { 9685 err(); 9686 wrapErr(0, WRAP_COLUMN, 9687 ERR_MANAGE_CERTS_CHECK_USABILITY_CHAIN_ISSUER_MISMATCH.get( 9688 alias, chain[i].getSubjectDN(), chain[i-1].getSubjectDN(), 9689 nonMatchReason)); 9690 numErrors++; 9691 chainError = true; 9692 } 9693 } 9694 9695 if (! chainError) 9696 { 9697 out(); 9698 wrapOut(0, WRAP_COLUMN, 9699 INFO_MANAGE_CERTS_CHECK_USABILITY_CHAIN_COMPLETE.get()); 9700 } 9701 } 9702 9703 9704 // If there are multiple certificates in the chain, and if the last 9705 // certificate in the chain is self-signed, then check to see if it is 9706 // contained in the JVM-default trust manager. If it isn't, then we'll 9707 // display a notice, but we won't consider it a warning in and of itself. 9708 if ((chain.length > 1) && chain[chain.length-1].isSelfSigned()) 9709 { 9710 final X509Certificate caCert = chain[chain.length-1]; 9711 9712 try 9713 { 9714 final String jvmDefaultTrustStoreType = 9715 inferKeystoreType(JVM_DEFAULT_CACERTS_FILE); 9716 final KeyStore jvmDefaultTrustStore = 9717 CryptoHelper.getKeyStore(jvmDefaultTrustStoreType); 9718 try (FileInputStream inputStream = 9719 new FileInputStream(JVM_DEFAULT_CACERTS_FILE)) 9720 { 9721 jvmDefaultTrustStore.load(inputStream, null); 9722 } 9723 9724 boolean found = false; 9725 final Enumeration<String> aliases = jvmDefaultTrustStore.aliases(); 9726 while (aliases.hasMoreElements()) 9727 { 9728 final String jvmDefaultCertAlias = aliases.nextElement(); 9729 if (jvmDefaultTrustStore.isCertificateEntry(jvmDefaultCertAlias)) 9730 { 9731 final Certificate c = 9732 jvmDefaultTrustStore.getCertificate(jvmDefaultCertAlias); 9733 final X509Certificate xc = new X509Certificate(c.getEncoded()); 9734 if ((caCert.getSubjectDN().equals(xc.getSubjectDN())) && 9735 Arrays.equals(caCert.getSignatureValue().getBits(), 9736 xc.getSignatureValue().getBits())) 9737 { 9738 found = true; 9739 break; 9740 } 9741 } 9742 } 9743 9744 if (found) 9745 { 9746 out(); 9747 wrapOut(0, WRAP_COLUMN, 9748 INFO_MANAGE_CERTS_CHECK_USABILITY_CA_TRUSTED_OK.get( 9749 caCert.getSubjectDN())); 9750 } 9751 else 9752 { 9753 out(); 9754 wrapOut(0, WRAP_COLUMN, 9755 INFO_MANAGE_CERTS_CHECK_USABILITY_CA_NOT_IN_JVM_DEFAULT_TS.get( 9756 caCert.getSubjectDN())); 9757 } 9758 } 9759 catch (final Exception e) 9760 { 9761 Debug.debugException(e); 9762 err(); 9763 wrapErr(0, WRAP_COLUMN, 9764 WARN_MANAGE_CERTS_CHECK_USABILITY_CHECK_CA_IN_TS_ERROR.get( 9765 caCert.getSubjectDN(), StaticUtils.getExceptionMessage(e))); 9766 numWarnings++; 9767 } 9768 } 9769 9770 9771 // Make sure that the signature is valid for each certificate in the 9772 // chain. If any certificate has an invalid signature, then that's an 9773 // error. 9774 for (int i=0; i < chain.length; i++) 9775 { 9776 final X509Certificate c = chain[i]; 9777 9778 try 9779 { 9780 if (c.isSelfSigned()) 9781 { 9782 c.verifySignature(null); 9783 } 9784 else if ((i + 1) < chain.length) 9785 { 9786 c.verifySignature(chain[i+1]); 9787 } 9788 9789 out(); 9790 wrapOut(0, WRAP_COLUMN, 9791 INFO_MANAGE_CERTS_CHECK_USABILITY_CERT_SIGNATURE_VALID.get( 9792 c.getSubjectDN())); 9793 } 9794 catch (final CertException ce) 9795 { 9796 err(); 9797 wrapErr(0, WRAP_COLUMN, ce.getMessage()); 9798 numErrors++; 9799 } 9800 } 9801 9802 9803 // Check the validity window for each certificate in the chain. If any of 9804 // them is expired or not yet valid, then that's an error. If any of them 9805 // will expire in the near future, then that's a warning. 9806 final long currentTime = System.currentTimeMillis(); 9807 final long thirtyDaysFromNow = 9808 currentTime + (30L * 24L * 60L * 60L * 1000L); 9809 for (int i=0; i < chain.length; i++) 9810 { 9811 final X509Certificate c = chain[i]; 9812 if (c.getNotBeforeTime() > currentTime) 9813 { 9814 err(); 9815 if (i == 0) 9816 { 9817 wrapErr(0, WRAP_COLUMN, 9818 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_NOT_YET_VALID.get( 9819 c.getSubjectDN(), formatDateAndTime(c.getNotBeforeDate()))); 9820 } 9821 else 9822 { 9823 wrapErr(0, WRAP_COLUMN, 9824 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_NOT_YET_VALID.get( 9825 c.getSubjectDN(), formatDateAndTime(c.getNotBeforeDate()))); 9826 } 9827 9828 numErrors++; 9829 } 9830 else if (c.getNotAfterTime() < currentTime) 9831 { 9832 err(); 9833 if (i == 0) 9834 { 9835 wrapErr(0, WRAP_COLUMN, 9836 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_EXPIRED.get( 9837 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9838 } 9839 else 9840 { 9841 wrapErr(0, WRAP_COLUMN, 9842 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_EXPIRED.get( 9843 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9844 } 9845 9846 numErrors++; 9847 } 9848 else if (c.getNotAfterTime() < thirtyDaysFromNow) 9849 { 9850 err(); 9851 if (i == 0) 9852 { 9853 wrapErr(0, WRAP_COLUMN, 9854 WARN_MANAGE_CERTS_CHECK_USABILITY_END_CERT_NEAR_EXPIRATION.get( 9855 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9856 } 9857 else 9858 { 9859 wrapErr(0, WRAP_COLUMN, 9860 WARN_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_NEAR_EXPIRATION. 9861 get(c.getSubjectDN(), 9862 formatDateAndTime(c.getNotAfterDate()))); 9863 } 9864 9865 numWarnings++; 9866 } 9867 else 9868 { 9869 if (i == 0) 9870 { 9871 out(); 9872 wrapOut(0, WRAP_COLUMN, 9873 INFO_MANAGE_CERTS_CHECK_USABILITY_END_CERT_VALIDITY_OK.get( 9874 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9875 } 9876 else 9877 { 9878 out(); 9879 wrapOut(0, WRAP_COLUMN, 9880 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_VALIDITY_OK.get( 9881 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 9882 } 9883 } 9884 } 9885 9886 9887 // Look at all of the extensions for all of the certificates and perform the 9888 // following validation: 9889 // - If the certificate at the head of the chain has an extended key usage 9890 // extension, then make sure it includes the serverAuth usage. If it 9891 // does not include an extended key usage extension, then warn that it 9892 // should. 9893 // - If any of the issuer certificates has a basic constraints extension, 9894 // then make sure it indicates that the associated certificate is a 9895 // certification authority. Further, if it has a path length constraint, 9896 // then make sure the chain does not exceed that length. If any issuer 9897 // certificate does not have a basic constraints extension, then warn that 9898 // it should. 9899 // - If any of the issuer certificates has a key usage extension, then 9900 // make sure it has the certSign usage. If any issuer certificate does 9901 // not have a key usage extension, then warn that it should. 9902 // - TODO: If any certificate has a CRL distribution points extension, then 9903 // retrieve the CRL and make sure the certificate hasn't been revoked. 9904 // - TODO: If any certificate has an authority information access 9905 // extension that points to an OCSP service, then consult that service to 9906 // determine whether the certificate has been revoked. 9907 for (int i=0; i < chain.length; i++) 9908 { 9909 boolean basicConstraintsFound = false; 9910 boolean extendedKeyUsageFound = false; 9911 boolean keyUsageFound = false; 9912 final X509Certificate c = chain[i]; 9913 for (final X509CertificateExtension extension : c.getExtensions()) 9914 { 9915 if (extension instanceof ExtendedKeyUsageExtension) 9916 { 9917 extendedKeyUsageFound = true; 9918 if (i == 0) 9919 { 9920 final ExtendedKeyUsageExtension e = 9921 (ExtendedKeyUsageExtension) extension; 9922 if (!e.getKeyPurposeIDs().contains( 9923 ExtendedKeyUsageID.TLS_SERVER_AUTHENTICATION.getOID())) 9924 { 9925 err(); 9926 wrapErr(0, WRAP_COLUMN, 9927 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_BAD_EKU.get( 9928 c.getSubjectDN())); 9929 numErrors++; 9930 } 9931 else 9932 { 9933 out(); 9934 wrapOut(0, WRAP_COLUMN, 9935 INFO_MANAGE_CERTS_CHECK_USABILITY_END_CERT_GOOD_EKU.get( 9936 c.getSubjectDN())); 9937 } 9938 } 9939 } 9940 else if (extension instanceof BasicConstraintsExtension) 9941 { 9942 basicConstraintsFound = true; 9943 if (i > 0) 9944 { 9945 final BasicConstraintsExtension e = 9946 (BasicConstraintsExtension) extension; 9947 if (!e.isCA()) 9948 { 9949 err(); 9950 wrapErr(0, WRAP_COLUMN, 9951 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_BAD_BC_CA.get( 9952 c.getSubjectDN())); 9953 numErrors++; 9954 } 9955 else if ((e.getPathLengthConstraint() != null) && 9956 ((i - 1) > e.getPathLengthConstraint())) 9957 { 9958 err(); 9959 wrapErr(0, WRAP_COLUMN, 9960 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_BAD_BC_LENGTH. 9961 get(c.getSubjectDN(), e.getPathLengthConstraint(), 9962 chain[0].getSubjectDN(), (i-1))); 9963 numErrors++; 9964 } 9965 else 9966 { 9967 out(); 9968 wrapOut(0, WRAP_COLUMN, 9969 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_GOOD_BC.get( 9970 c.getSubjectDN())); 9971 } 9972 } 9973 } 9974 else if (extension instanceof KeyUsageExtension) 9975 { 9976 keyUsageFound = true; 9977 if (i > 0) 9978 { 9979 final KeyUsageExtension e = (KeyUsageExtension) extension; 9980 if (! e.isKeyCertSignBitSet()) 9981 { 9982 err(); 9983 wrapErr(0, WRAP_COLUMN, 9984 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_NO_CERT_SIGN_KU.get( 9985 c.getSubjectDN())); 9986 numErrors++; 9987 } 9988 else 9989 { 9990 out(); 9991 wrapOut(0, WRAP_COLUMN, 9992 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_GOOD_KU.get( 9993 c.getSubjectDN())); 9994 } 9995 } 9996 } 9997 } 9998 9999 if (i == 0) 10000 { 10001 if (! extendedKeyUsageFound) 10002 { 10003 err(); 10004 wrapErr(0, WRAP_COLUMN, 10005 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_EKU.get( 10006 c.getSubjectDN())); 10007 numWarnings++; 10008 } 10009 } 10010 else 10011 { 10012 if (! basicConstraintsFound) 10013 { 10014 err(); 10015 wrapErr(0, WRAP_COLUMN, 10016 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_BC.get( 10017 c.getSubjectDN())); 10018 numWarnings++; 10019 } 10020 10021 if (! keyUsageFound) 10022 { 10023 err(); 10024 wrapErr(0, WRAP_COLUMN, 10025 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_KU.get( 10026 c.getSubjectDN())); 10027 numWarnings++; 10028 } 10029 } 10030 } 10031 10032 10033 // Make sure that none of the certificates has a signature algorithm that 10034 // uses MD5 or SHA-1. If it uses an unrecognized signature algorithm, then 10035 // that's a warning. 10036 boolean isIssuer = false; 10037 final BooleanArgument ignoreSHA1WarningArg = 10038 subCommandParser.getBooleanArgument( 10039 "allow-sha-1-signature-for-issuer-certificates"); 10040 final boolean ignoreSHA1SignatureWarningForIssuerCertificates = 10041 ((ignoreSHA1WarningArg != null) && ignoreSHA1WarningArg.isPresent()); 10042 for (final X509Certificate c : chain) 10043 { 10044 final OID signatureAlgorithmOID = c.getSignatureAlgorithmOID(); 10045 final SignatureAlgorithmIdentifier id = 10046 SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID); 10047 if (id == null) 10048 { 10049 err(); 10050 wrapErr(0, WRAP_COLUMN, 10051 WARN_MANAGE_CERTS_CHECK_USABILITY_UNKNOWN_SIG_ALG.get( 10052 c.getSubjectDN(), signatureAlgorithmOID)); 10053 numWarnings++; 10054 } 10055 else 10056 { 10057 switch (id) 10058 { 10059 case MD2_WITH_RSA: 10060 case MD5_WITH_RSA: 10061 err(); 10062 wrapErr(0, WRAP_COLUMN, 10063 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_SIG_ALG.get( 10064 c.getSubjectDN(), id.getUserFriendlyName())); 10065 numErrors++; 10066 break; 10067 10068 case SHA_1_WITH_RSA: 10069 case SHA_1_WITH_DSA: 10070 case SHA_1_WITH_ECDSA: 10071 if (isIssuer && ignoreSHA1SignatureWarningForIssuerCertificates) 10072 { 10073 err(); 10074 wrapErr(0, WRAP_COLUMN, 10075 WARN_MANAGE_CERTS_CHECK_USABILITY_ISSUER_WITH_SHA1_SIG.get( 10076 c.getSubjectDN(), id.getUserFriendlyName(), 10077 ignoreSHA1WarningArg.getIdentifierString())); 10078 } 10079 else 10080 { 10081 err(); 10082 wrapErr(0, WRAP_COLUMN, 10083 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_SIG_ALG.get( 10084 c.getSubjectDN(), id.getUserFriendlyName())); 10085 numErrors++; 10086 } 10087 break; 10088 10089 case SHA_224_WITH_RSA: 10090 case SHA_224_WITH_DSA: 10091 case SHA_224_WITH_ECDSA: 10092 case SHA_256_WITH_RSA: 10093 case SHA_256_WITH_DSA: 10094 case SHA_256_WITH_ECDSA: 10095 case SHA_384_WITH_RSA: 10096 case SHA_384_WITH_ECDSA: 10097 case SHA_512_WITH_RSA: 10098 case SHA_512_WITH_ECDSA: 10099 out(); 10100 wrapOut(0, WRAP_COLUMN, 10101 INFO_MANAGE_CERTS_CHECK_USABILITY_SIG_ALG_OK.get( 10102 c.getSubjectDN(), id.getUserFriendlyName())); 10103 break; 10104 } 10105 } 10106 10107 isIssuer = true; 10108 } 10109 10110 10111 // Make sure that none of the certificates that uses the RSA key algorithm 10112 // has a public modulus size smaller than 2048 bits. 10113 for (final X509Certificate c : chain) 10114 { 10115 if ((c.getDecodedPublicKey() != null) && 10116 (c.getDecodedPublicKey() instanceof RSAPublicKey)) 10117 { 10118 final RSAPublicKey rsaPublicKey = 10119 (RSAPublicKey) c.getDecodedPublicKey(); 10120 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10121 int modulusSizeBits = modulusBytes.length * 8; 10122 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10123 { 10124 modulusSizeBits -= 8; 10125 } 10126 10127 if (modulusSizeBits < 2048) 10128 { 10129 err(); 10130 wrapErr(0, WRAP_COLUMN, 10131 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_RSA_MODULUS.get( 10132 c.getSubjectDN(), modulusSizeBits)); 10133 numErrors++; 10134 } 10135 else 10136 { 10137 out(); 10138 wrapOut(0, WRAP_COLUMN, 10139 INFO_MANAGE_CERTS_CHECK_USABILITY_RSA_MODULUS_OK.get( 10140 c.getSubjectDN(), modulusSizeBits)); 10141 } 10142 } 10143 } 10144 10145 10146 switch (numErrors) 10147 { 10148 case 0: 10149 break; 10150 case 1: 10151 err(); 10152 wrapErr(0, WRAP_COLUMN, 10153 ERR_MANAGE_CERTS_CHECK_USABILITY_ONE_ERROR.get()); 10154 return ResultCode.PARAM_ERROR; 10155 default: 10156 err(); 10157 wrapErr(0, WRAP_COLUMN, 10158 ERR_MANAGE_CERTS_CHECK_USABILITY_MULTIPLE_ERRORS.get(numErrors)); 10159 return ResultCode.PARAM_ERROR; 10160 } 10161 10162 switch (numWarnings) 10163 { 10164 case 0: 10165 out(); 10166 wrapOut(0, WRAP_COLUMN, 10167 INFO_MANAGE_CERTS_CHECK_USABILITY_NO_ERRORS_OR_WARNINGS.get()); 10168 return ResultCode.SUCCESS; 10169 case 1: 10170 err(); 10171 wrapErr(0, WRAP_COLUMN, 10172 ERR_MANAGE_CERTS_CHECK_USABILITY_ONE_WARNING.get()); 10173 return ResultCode.PARAM_ERROR; 10174 default: 10175 err(); 10176 wrapErr(0, WRAP_COLUMN, 10177 ERR_MANAGE_CERTS_CHECK_USABILITY_MULTIPLE_WARNINGS.get( 10178 numWarnings)); 10179 return ResultCode.PARAM_ERROR; 10180 } 10181 } 10182 10183 10184 10185 /** 10186 * Performs the necessary processing for the display-certificate-file 10187 * subcommand. 10188 * 10189 * @return A result code that indicates whether the processing completed 10190 * successfully. 10191 */ 10192 @NotNull() 10193 private ResultCode doDisplayCertificateFile() 10194 { 10195 // Get the values of a number of configured arguments. 10196 final FileArgument certificateFileArgument = 10197 subCommandParser.getFileArgument("certificate-file"); 10198 final File certificateFile = certificateFileArgument.getValue(); 10199 10200 final BooleanArgument verboseArgument = 10201 subCommandParser.getBooleanArgument("verbose"); 10202 final boolean verbose = 10203 ((verboseArgument != null) && verboseArgument.isPresent()); 10204 10205 final BooleanArgument displayKeytoolCommandArgument = 10206 subCommandParser.getBooleanArgument("display-keytool-command"); 10207 if ((displayKeytoolCommandArgument != null) && 10208 displayKeytoolCommandArgument.isPresent()) 10209 { 10210 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 10211 keytoolArgs.add("-printcert"); 10212 keytoolArgs.add("-file"); 10213 keytoolArgs.add(certificateFile.getAbsolutePath()); 10214 10215 if (verbose) 10216 { 10217 keytoolArgs.add("-v"); 10218 } 10219 10220 displayKeytoolCommand(keytoolArgs); 10221 } 10222 10223 10224 // Read the certificates from the specified file. 10225 final List<X509Certificate> certificates; 10226 try 10227 { 10228 certificates = readCertificatesFromFile(certificateFile); 10229 } 10230 catch (final LDAPException le) 10231 { 10232 Debug.debugException(le); 10233 wrapErr(0, WRAP_COLUMN, le.getMessage()); 10234 return le.getResultCode(); 10235 } 10236 10237 10238 // If there aren't any certificates in the file, print that. 10239 if (certificates.isEmpty()) 10240 { 10241 wrapOut(0, WRAP_COLUMN, INFO_MANAGE_CERTS_DISPLAY_CERT_NO_CERTS.get( 10242 certificateFile.getAbsolutePath())); 10243 } 10244 else 10245 { 10246 for (final X509Certificate c : certificates) 10247 { 10248 out(); 10249 printCertificate(c, "", verbose); 10250 } 10251 } 10252 10253 return ResultCode.SUCCESS; 10254 } 10255 10256 10257 10258 /** 10259 * Performs the necessary processing for the 10260 * display-certificate-signing-request-file subcommand. 10261 * 10262 * @return A result code that indicates whether the processing completed 10263 * successfully. 10264 */ 10265 @NotNull() 10266 private ResultCode doDisplayCertificateSigningRequestFile() 10267 { 10268 // Get the values of a number of configured arguments. 10269 final FileArgument csrFileArgument = 10270 subCommandParser.getFileArgument("certificate-signing-request-file"); 10271 final File csrFile = csrFileArgument.getValue(); 10272 10273 final BooleanArgument verboseArgument = 10274 subCommandParser.getBooleanArgument("verbose"); 10275 final boolean verbose = 10276 ((verboseArgument != null) && verboseArgument.isPresent()); 10277 10278 final BooleanArgument displayKeytoolCommandArgument = 10279 subCommandParser.getBooleanArgument("display-keytool-command"); 10280 if ((displayKeytoolCommandArgument != null) && 10281 displayKeytoolCommandArgument.isPresent()) 10282 { 10283 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 10284 keytoolArgs.add("-printcertreq"); 10285 keytoolArgs.add("-file"); 10286 keytoolArgs.add(csrFile.getAbsolutePath()); 10287 keytoolArgs.add("-v"); 10288 10289 displayKeytoolCommand(keytoolArgs); 10290 } 10291 10292 10293 // Read the certificate signing request from the specified file. 10294 final PKCS10CertificateSigningRequest csr; 10295 try 10296 { 10297 csr = readCertificateSigningRequestFromFile(csrFile); 10298 } 10299 catch (final LDAPException le) 10300 { 10301 Debug.debugException(le); 10302 wrapErr(0, WRAP_COLUMN, le.getMessage()); 10303 return le.getResultCode(); 10304 } 10305 10306 out(); 10307 printCertificateSigningRequest(csr, verbose, ""); 10308 10309 return ResultCode.SUCCESS; 10310 } 10311 10312 10313 10314 /** 10315 * Prints a string representation of the provided certificate to standard 10316 * output. 10317 * 10318 * @param certificate The certificate to be printed. 10319 * @param indent The string to place at the beginning of each line to 10320 * indent that line. 10321 * @param verbose Indicates whether to display verbose information about 10322 * the certificate. 10323 */ 10324 private void printCertificate(@NotNull final X509Certificate certificate, 10325 @NotNull final String indent, 10326 final boolean verbose) 10327 { 10328 if (verbose) 10329 { 10330 out(indent + 10331 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VERSION.get( 10332 certificate.getVersion().getName())); 10333 } 10334 10335 out(indent + 10336 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_DN.get( 10337 certificate.getSubjectDN())); 10338 out(indent + 10339 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ISSUER_DN.get( 10340 certificate.getIssuerDN())); 10341 10342 if (verbose) 10343 { 10344 out(indent + 10345 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SERIAL_NUMBER.get( 10346 toColonDelimitedHex( 10347 certificate.getSerialNumber().toByteArray()))); 10348 } 10349 10350 out(indent + 10351 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_START.get( 10352 formatDateAndTime(certificate.getNotBeforeDate()))); 10353 out(indent + 10354 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_END.get( 10355 formatDateAndTime(certificate.getNotAfterDate()))); 10356 10357 final long currentTime = System.currentTimeMillis(); 10358 if (currentTime < certificate.getNotBeforeTime()) 10359 { 10360 out(indent + 10361 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_NOT_YET_VALID. 10362 get()); 10363 } 10364 else if (currentTime > certificate.getNotAfterTime()) 10365 { 10366 out(indent + 10367 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_EXPIRED.get()); 10368 } 10369 else 10370 { 10371 out(indent + 10372 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_VALID.get()); 10373 } 10374 10375 out(indent + 10376 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_ALG.get( 10377 certificate.getSignatureAlgorithmNameOrOID())); 10378 if (verbose) 10379 { 10380 String signatureString; 10381 try 10382 { 10383 signatureString = 10384 toColonDelimitedHex(certificate.getSignatureValue().getBytes()); 10385 } 10386 catch (final Exception e) 10387 { 10388 Debug.debugException(e); 10389 signatureString = certificate.getSignatureValue().toString(); 10390 } 10391 out(indent + 10392 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_VALUE.get()); 10393 for (final String line : StaticUtils.wrapLine(signatureString, 78)) 10394 { 10395 out(indent + " " + line); 10396 } 10397 } 10398 10399 final String pkAlg; 10400 final String pkSummary = getPublicKeySummary( 10401 certificate.getPublicKeyAlgorithmOID(), 10402 certificate.getDecodedPublicKey(), 10403 certificate.getPublicKeyAlgorithmParameters()); 10404 if (pkSummary == null) 10405 { 10406 pkAlg = certificate.getPublicKeyAlgorithmNameOrOID(); 10407 } 10408 else 10409 { 10410 pkAlg = certificate.getPublicKeyAlgorithmNameOrOID() + " (" + 10411 pkSummary + ')'; 10412 } 10413 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_PK_ALG.get(pkAlg)); 10414 10415 if (verbose) 10416 { 10417 printPublicKey(certificate.getEncodedPublicKey(), 10418 certificate.getDecodedPublicKey(), 10419 certificate.getPublicKeyAlgorithmParameters(), indent); 10420 10421 if (certificate.getSubjectUniqueID() != null) 10422 { 10423 String subjectUniqueID; 10424 try 10425 { 10426 subjectUniqueID = toColonDelimitedHex( 10427 certificate.getSubjectUniqueID().getBytes()); 10428 } 10429 catch (final Exception e) 10430 { 10431 Debug.debugException(e); 10432 subjectUniqueID = certificate.getSubjectUniqueID().toString(); 10433 } 10434 10435 out(indent + 10436 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_UNIQUE_ID.get()); 10437 for (final String line : StaticUtils.wrapLine(subjectUniqueID, 78)) 10438 { 10439 out(indent + " " + line); 10440 } 10441 } 10442 10443 if (certificate.getIssuerUniqueID() != null) 10444 { 10445 String issuerUniqueID; 10446 try 10447 { 10448 issuerUniqueID = toColonDelimitedHex( 10449 certificate.getIssuerUniqueID().getBytes()); 10450 } 10451 catch (final Exception e) 10452 { 10453 Debug.debugException(e); 10454 issuerUniqueID = certificate.getIssuerUniqueID().toString(); 10455 } 10456 10457 out(indent + 10458 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ISSUER_UNIQUE_ID.get()); 10459 for (final String line : StaticUtils.wrapLine(issuerUniqueID, 78)) 10460 { 10461 out(indent + " " + line); 10462 } 10463 } 10464 10465 printExtensions(certificate.getExtensions(), indent); 10466 } 10467 10468 try 10469 { 10470 out(indent + 10471 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_FINGERPRINT.get("SHA-1", 10472 toColonDelimitedHex(certificate.getSHA1Fingerprint()))); 10473 } 10474 catch (final Exception e) 10475 { 10476 Debug.debugException(e); 10477 } 10478 10479 try 10480 { 10481 out(indent + 10482 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_FINGERPRINT.get("SHA-256", 10483 toColonDelimitedHex(certificate.getSHA256Fingerprint()))); 10484 } 10485 catch (final Exception e) 10486 { 10487 Debug.debugException(e); 10488 } 10489 } 10490 10491 10492 10493 /** 10494 * Prints a string representation of the provided certificate signing request 10495 * to standard output. 10496 * 10497 * @param csr The certificate signing request to be printed. 10498 * @param verbose Indicates whether to display verbose information about 10499 * the contents of the request. 10500 * @param indent The string to place at the beginning of each line to 10501 * indent that line. 10502 */ 10503 private void printCertificateSigningRequest( 10504 @NotNull final PKCS10CertificateSigningRequest csr, 10505 final boolean verbose, @NotNull final String indent) 10506 { 10507 out(indent + 10508 INFO_MANAGE_CERTS_PRINT_CSR_LABEL_VERSION.get( 10509 csr.getVersion().getName())); 10510 out(indent + 10511 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_DN.get( 10512 csr.getSubjectDN())); 10513 out(indent + 10514 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_ALG.get( 10515 csr.getSignatureAlgorithmNameOrOID())); 10516 10517 if (verbose) 10518 { 10519 String signatureString; 10520 try 10521 { 10522 signatureString = 10523 toColonDelimitedHex(csr.getSignatureValue().getBytes()); 10524 } 10525 catch (final Exception e) 10526 { 10527 Debug.debugException(e); 10528 signatureString = csr.getSignatureValue().toString(); 10529 } 10530 out(indent + 10531 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_VALUE.get()); 10532 for (final String line : StaticUtils.wrapLine(signatureString, 78)) 10533 { 10534 out(indent + " " + line); 10535 } 10536 } 10537 10538 final String pkAlg; 10539 final String pkSummary = getPublicKeySummary(csr.getPublicKeyAlgorithmOID(), 10540 csr.getDecodedPublicKey(), csr.getPublicKeyAlgorithmParameters()); 10541 if (pkSummary == null) 10542 { 10543 pkAlg = csr.getPublicKeyAlgorithmNameOrOID(); 10544 } 10545 else 10546 { 10547 pkAlg = csr.getPublicKeyAlgorithmNameOrOID() + " (" + 10548 pkSummary + ')'; 10549 } 10550 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_PK_ALG.get(pkAlg)); 10551 10552 if (verbose) 10553 { 10554 printPublicKey(csr.getEncodedPublicKey(), csr.getDecodedPublicKey(), 10555 csr.getPublicKeyAlgorithmParameters(), indent); 10556 printExtensions(csr.getExtensions(), indent); 10557 } 10558 } 10559 10560 10561 10562 /** 10563 * Prints information about the provided public key. 10564 * 10565 * @param encodedPublicKey The encoded representation of the public key. 10566 * This must not be {@code null}. 10567 * @param decodedPublicKey The decoded representation of the public key, if 10568 * available. 10569 * @param parameters The public key algorithm parameters, if any. 10570 * @param indent The string to place at the beginning of each 10571 * line to indent that line. 10572 */ 10573 private void printPublicKey(@NotNull final ASN1BitString encodedPublicKey, 10574 @Nullable final DecodedPublicKey decodedPublicKey, 10575 @Nullable final ASN1Element parameters, 10576 @NotNull final String indent) 10577 { 10578 if (decodedPublicKey == null) 10579 { 10580 String pkString; 10581 try 10582 { 10583 pkString = toColonDelimitedHex(encodedPublicKey.getBytes()); 10584 } 10585 catch (final Exception e) 10586 { 10587 Debug.debugException(e); 10588 pkString = encodedPublicKey.toString(); 10589 } 10590 10591 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ENCODED_PK.get()); 10592 for (final String line : StaticUtils.wrapLine(pkString, 78)) 10593 { 10594 out(indent + " " + line); 10595 } 10596 10597 return; 10598 } 10599 10600 if (decodedPublicKey instanceof RSAPublicKey) 10601 { 10602 final RSAPublicKey rsaPublicKey = (RSAPublicKey) decodedPublicKey; 10603 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10604 10605 int modulusSizeBits = modulusBytes.length * 8; 10606 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10607 { 10608 modulusSizeBits -= 8; 10609 } 10610 10611 out(indent + 10612 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_RSA_MODULUS.get( 10613 modulusSizeBits)); 10614 final String modulusHex = toColonDelimitedHex(modulusBytes); 10615 for (final String line : StaticUtils.wrapLine(modulusHex, 78)) 10616 { 10617 out(indent + " " + line); 10618 } 10619 10620 out(indent + 10621 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_RSA_EXPONENT.get( 10622 toColonDelimitedHex( 10623 rsaPublicKey.getPublicExponent().toByteArray()))); 10624 } 10625 else if (decodedPublicKey instanceof EllipticCurvePublicKey) 10626 { 10627 final EllipticCurvePublicKey ecPublicKey = 10628 (EllipticCurvePublicKey) decodedPublicKey; 10629 10630 out(indent + 10631 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_IS_COMPRESSED.get( 10632 String.valueOf(ecPublicKey.usesCompressedForm()))); 10633 out(indent + 10634 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_X.get( 10635 String.valueOf(ecPublicKey.getXCoordinate()))); 10636 if (ecPublicKey.getYCoordinate() == null) 10637 { 10638 out(indent + 10639 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_Y_IS_EVEN.get( 10640 String.valueOf(ecPublicKey.yCoordinateIsEven()))); 10641 } 10642 else 10643 { 10644 out(indent + 10645 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_Y.get( 10646 String.valueOf(ecPublicKey.getYCoordinate()))); 10647 } 10648 } 10649 } 10650 10651 10652 10653 /** 10654 * Retrieves a short summary of the provided public key, if available. For 10655 * RSA keys, this will be the modulus size in bits. For elliptic curve keys, 10656 * this will be the named curve, if available. 10657 * 10658 * @param publicKeyAlgorithmOID The OID that identifies the type of public 10659 * key. 10660 * @param publicKey The decoded public key. This may be 10661 * {@code null} if the decoded public key is 10662 * not available. 10663 * @param parameters The encoded public key algorithm parameters. 10664 * This may be {@code null} if no public key 10665 * algorithm parameters are available. 10666 * 10667 * @return A short summary of the provided public key, or {@code null} if 10668 * no summary is available. 10669 */ 10670 @NotNull() 10671 private static String getPublicKeySummary( 10672 @NotNull final OID publicKeyAlgorithmOID, 10673 @Nullable final DecodedPublicKey publicKey, 10674 @Nullable final ASN1Element parameters) 10675 { 10676 if (publicKey instanceof RSAPublicKey) 10677 { 10678 final RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; 10679 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 10680 10681 int modulusSizeBits = modulusBytes.length * 8; 10682 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 10683 { 10684 modulusSizeBits -= 8; 10685 } 10686 10687 return INFO_MANAGE_CERTS_GET_PK_SUMMARY_RSA_MODULUS_SIZE.get( 10688 modulusSizeBits); 10689 } 10690 else if ((parameters != null) && 10691 publicKeyAlgorithmOID.equals(PublicKeyAlgorithmIdentifier.EC.getOID())) 10692 { 10693 try 10694 { 10695 final OID namedCurveOID = 10696 parameters.decodeAsObjectIdentifier().getOID(); 10697 return NamedCurve.getNameOrOID(namedCurveOID); 10698 } 10699 catch (final Exception e) 10700 { 10701 Debug.debugException(e); 10702 } 10703 } 10704 10705 return null; 10706 } 10707 10708 10709 10710 /** 10711 * Prints information about the provided extensions. 10712 * 10713 * @param extensions The list of extensions to be printed. 10714 * @param indent The string to place at the beginning of each line to 10715 * indent that line. 10716 */ 10717 void printExtensions(@NotNull final List<X509CertificateExtension> extensions, 10718 @NotNull final String indent) 10719 { 10720 if (extensions.isEmpty()) 10721 { 10722 return; 10723 } 10724 10725 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXTENSIONS.get()); 10726 for (final X509CertificateExtension extension : extensions) 10727 { 10728 if (extension instanceof AuthorityKeyIdentifierExtension) 10729 { 10730 out(indent + " " + 10731 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_EXT.get()); 10732 out(indent + " " + 10733 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10734 extension.getOID().toString())); 10735 out(indent + " " + 10736 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10737 String.valueOf(extension.isCritical()))); 10738 10739 final AuthorityKeyIdentifierExtension e = 10740 (AuthorityKeyIdentifierExtension) extension; 10741 if (e.getKeyIdentifier() != null) 10742 { 10743 out(indent + " " + 10744 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_ID.get()); 10745 final String idHex = 10746 toColonDelimitedHex(e.getKeyIdentifier().getValue()); 10747 for (final String line : StaticUtils.wrapLine(idHex, 78)) 10748 { 10749 out(indent + " " + line); 10750 } 10751 } 10752 10753 if (e.getAuthorityCertIssuer() != null) 10754 { 10755 out(indent + " " + 10756 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_ISSUER. 10757 get()); 10758 printGeneralNames(e.getAuthorityCertIssuer(), 10759 indent + " "); 10760 } 10761 10762 if (e.getAuthorityCertSerialNumber() != null) 10763 { 10764 out(indent + " " + 10765 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_SERIAL.get( 10766 toColonDelimitedHex(e.getAuthorityCertSerialNumber(). 10767 toByteArray()))); 10768 } 10769 } 10770 else if (extension instanceof BasicConstraintsExtension) 10771 { 10772 out(indent + " " + 10773 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_EXT.get()); 10774 out(indent + " " + 10775 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10776 extension.getOID().toString())); 10777 out(indent + " " + 10778 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10779 String.valueOf(extension.isCritical()))); 10780 10781 final BasicConstraintsExtension e = 10782 (BasicConstraintsExtension) extension; 10783 out(indent + " " + 10784 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_IS_CA.get( 10785 String.valueOf(e.isCA()))); 10786 10787 if (e.getPathLengthConstraint() != null) 10788 { 10789 out(indent + " " + 10790 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_LENGTH.get( 10791 e.getPathLengthConstraint())); 10792 } 10793 } 10794 else if (extension instanceof CRLDistributionPointsExtension) 10795 { 10796 out(indent + " " + 10797 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_EXT.get()); 10798 out(indent + " " + 10799 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10800 extension.getOID().toString())); 10801 out(indent + " " + 10802 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10803 String.valueOf(extension.isCritical()))); 10804 10805 final CRLDistributionPointsExtension crlDPE = 10806 (CRLDistributionPointsExtension) extension; 10807 for (final CRLDistributionPoint dp : 10808 crlDPE.getCRLDistributionPoints()) 10809 { 10810 out(indent + " " + 10811 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_HEADER.get()); 10812 if (dp.getFullName() != null) 10813 { 10814 out(indent + " " + 10815 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_FULL_NAME. 10816 get()); 10817 printGeneralNames(dp.getFullName(), 10818 indent + " "); 10819 } 10820 10821 if (dp.getNameRelativeToCRLIssuer() != null) 10822 { 10823 out(indent + " " + 10824 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_REL_NAME.get( 10825 dp.getNameRelativeToCRLIssuer())); 10826 } 10827 10828 if (! dp.getPotentialRevocationReasons().isEmpty()) 10829 { 10830 out(indent + " " + 10831 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_REASON.get()); 10832 for (final CRLDistributionPointRevocationReason r : 10833 dp.getPotentialRevocationReasons()) 10834 { 10835 out(indent + " " + r.getName()); 10836 } 10837 } 10838 10839 if (dp.getCRLIssuer() != null) 10840 { 10841 out(indent + " " + 10842 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_CRL_ISSUER. 10843 get()); 10844 printGeneralNames(dp.getCRLIssuer(), 10845 indent + " "); 10846 } 10847 } 10848 } 10849 else if (extension instanceof ExtendedKeyUsageExtension) 10850 { 10851 out(indent + " " + 10852 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_EXT.get()); 10853 out(indent + " " + 10854 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10855 extension.getOID().toString())); 10856 out(indent + " " + 10857 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10858 String.valueOf(extension.isCritical()))); 10859 10860 final ExtendedKeyUsageExtension e = 10861 (ExtendedKeyUsageExtension) extension; 10862 for (final OID oid : e.getKeyPurposeIDs()) 10863 { 10864 final ExtendedKeyUsageID id = ExtendedKeyUsageID.forOID(oid); 10865 if (id == null) 10866 { 10867 out(indent + " " + 10868 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_ID.get(oid)); 10869 } 10870 else 10871 { 10872 out(indent + " " + 10873 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_ID.get( 10874 id.getName())); 10875 } 10876 } 10877 } 10878 else if (extension instanceof IssuerAlternativeNameExtension) 10879 { 10880 out(indent + " " + 10881 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IAN_EXT.get()); 10882 out(indent + " " + 10883 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10884 extension.getOID().toString())); 10885 out(indent + " " + 10886 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10887 String.valueOf(extension.isCritical()))); 10888 10889 final IssuerAlternativeNameExtension e = 10890 (IssuerAlternativeNameExtension) extension; 10891 printGeneralNames(e.getGeneralNames(), indent + " "); 10892 } 10893 else if (extension instanceof KeyUsageExtension) 10894 { 10895 out(indent + " " + 10896 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_EXT.get()); 10897 out(indent + " " + 10898 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10899 extension.getOID().toString())); 10900 out(indent + " " + 10901 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10902 String.valueOf(extension.isCritical()))); 10903 10904 out(indent + " " + 10905 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_USAGES.get()); 10906 final KeyUsageExtension kue = (KeyUsageExtension) extension; 10907 if (kue.isDigitalSignatureBitSet()) 10908 { 10909 out(indent + " " + 10910 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DS.get()); 10911 } 10912 10913 if (kue.isNonRepudiationBitSet()) 10914 { 10915 out(indent + " " + 10916 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_NR.get()); 10917 } 10918 10919 if (kue.isKeyEnciphermentBitSet()) 10920 { 10921 out(indent + " " + 10922 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KE.get()); 10923 } 10924 10925 if (kue.isDataEnciphermentBitSet()) 10926 { 10927 out(indent + " " + 10928 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DE.get()); 10929 } 10930 10931 if (kue.isKeyAgreementBitSet()) 10932 { 10933 out(indent + " " + 10934 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KA.get()); 10935 } 10936 10937 if (kue.isKeyCertSignBitSet()) 10938 { 10939 out(indent + " " + 10940 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KCS.get()); 10941 } 10942 10943 if (kue.isCRLSignBitSet()) 10944 { 10945 out(indent + " " + 10946 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_CRL_SIGN.get()); 10947 } 10948 10949 if (kue.isEncipherOnlyBitSet()) 10950 { 10951 out(indent + " " + 10952 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_EO.get()); 10953 } 10954 10955 if (kue.isDecipherOnlyBitSet()) 10956 { 10957 out(indent + " " + 10958 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DO.get()); 10959 } 10960 } 10961 else if (extension instanceof SubjectAlternativeNameExtension) 10962 { 10963 out(indent + " " + 10964 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SAN_EXT.get()); 10965 out(indent + " " + 10966 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10967 extension.getOID().toString())); 10968 out(indent + " " + 10969 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10970 String.valueOf(extension.isCritical()))); 10971 10972 final SubjectAlternativeNameExtension e = 10973 (SubjectAlternativeNameExtension) extension; 10974 printGeneralNames(e.getGeneralNames(), indent + " "); 10975 } 10976 else if (extension instanceof SubjectKeyIdentifierExtension) 10977 { 10978 out(indent + " " + 10979 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SKI_EXT.get()); 10980 out(indent + " " + 10981 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 10982 extension.getOID().toString())); 10983 out(indent + " " + 10984 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 10985 String.valueOf(extension.isCritical()))); 10986 10987 final SubjectKeyIdentifierExtension e = 10988 (SubjectKeyIdentifierExtension) extension; 10989 final String idHex = 10990 toColonDelimitedHex(e.getKeyIdentifier().getValue()); 10991 out(indent + " " + 10992 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SKI_ID.get()); 10993 for (final String line : StaticUtils.wrapLine(idHex, 78)) 10994 { 10995 out(indent + " " + line); 10996 } 10997 } 10998 else 10999 { 11000 out(indent + " " + 11001 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_GENERIC.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 String valueHex = toColonDelimitedHex(extension.getValue()); 11010 out(indent + " " + 11011 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_VALUE.get()); 11012 getOut().print(StaticUtils.toHexPlusASCII(extension.getValue(), 11013 (indent.length() + 15))); 11014 } 11015 } 11016 } 11017 11018 11019 11020 /** 11021 * Prints information about the contents of the provided general names object. 11022 * 11023 * @param generalNames The general names object to print. 11024 * @param indent The string to place at the beginning of each line to 11025 * indent that line. 11026 */ 11027 private void printGeneralNames(@NotNull final GeneralNames generalNames, 11028 @NotNull final String indent) 11029 { 11030 for (final String dnsName : generalNames.getDNSNames()) 11031 { 11032 out(indent + INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_DNS.get(dnsName)); 11033 } 11034 11035 for (final InetAddress ipAddress : generalNames.getIPAddresses()) 11036 { 11037 out(indent + 11038 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_IP.get( 11039 ipAddress.getHostAddress())); 11040 } 11041 11042 for (final String name : generalNames.getRFC822Names()) 11043 { 11044 out(indent + 11045 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_RFC_822_NAME.get(name)); 11046 } 11047 11048 for (final DN dn : generalNames.getDirectoryNames()) 11049 { 11050 out(indent + 11051 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_DIRECTORY_NAME.get( 11052 String.valueOf(dn))); 11053 } 11054 11055 for (final String uri : generalNames.getUniformResourceIdentifiers()) 11056 { 11057 out(indent + INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_URI.get(uri)); 11058 } 11059 11060 for (final OID oid : generalNames.getRegisteredIDs()) 11061 { 11062 out(indent + 11063 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_REGISTERED_ID.get( 11064 oid.toString())); 11065 } 11066 11067 if (! generalNames.getOtherNames().isEmpty()) 11068 { 11069 out(indent + 11070 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_OTHER_NAME_COUNT.get( 11071 generalNames.getOtherNames().size())); 11072 } 11073 11074 if (! generalNames.getX400Addresses().isEmpty()) 11075 { 11076 out(indent + 11077 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_X400_ADDR_COUNT.get( 11078 generalNames.getX400Addresses().size())); 11079 } 11080 11081 if (! generalNames.getEDIPartyNames().isEmpty()) 11082 { 11083 out(indent + 11084 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_EDI_PARTY_NAME_COUNT.get( 11085 generalNames.getEDIPartyNames().size())); 11086 } 11087 } 11088 11089 11090 11091 /** 11092 * Writes a PEM-encoded representation of the provided encoded certificate to 11093 * the given print stream. 11094 * 11095 * @param printStream The print stream to which the PEM-encoded 11096 * certificate should be written. It must not be 11097 * {@code null}. 11098 * @param encodedCertificate The bytes that comprise the encoded 11099 * certificate. It must not be {@code null}. 11100 */ 11101 private static void writePEMCertificate( 11102 @NotNull final PrintStream printStream, 11103 @NotNull final byte[] encodedCertificate) 11104 { 11105 final String certBase64 = Base64.encode(encodedCertificate); 11106 printStream.println("-----BEGIN CERTIFICATE-----"); 11107 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11108 { 11109 printStream.println(line); 11110 } 11111 printStream.println("-----END CERTIFICATE-----"); 11112 } 11113 11114 11115 11116 /** 11117 * Writes a PEM-encoded representation of the provided encoded certificate 11118 * signing request to the given print stream. 11119 * 11120 * @param printStream The print stream to which the PEM-encoded certificate 11121 * signing request should be written. It must not be 11122 * {@code null}. 11123 * @param encodedCSR The bytes that comprise the encoded certificate 11124 * signing request. It must not be {@code null}. 11125 */ 11126 private static void writePEMCertificateSigningRequest( 11127 @NotNull final PrintStream printStream, 11128 @NotNull final byte[] encodedCSR) 11129 { 11130 final String certBase64 = Base64.encode(encodedCSR); 11131 printStream.println("-----BEGIN CERTIFICATE REQUEST-----"); 11132 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11133 { 11134 printStream.println(line); 11135 } 11136 printStream.println("-----END CERTIFICATE REQUEST-----"); 11137 } 11138 11139 11140 11141 /** 11142 * Writes a PEM-encoded representation of the provided encoded private key to 11143 * the given print stream. 11144 * 11145 * @param printStream The print stream to which the PEM-encoded 11146 * private key should be written. It must not be 11147 * {@code null}. 11148 * @param encodedPrivateKey The bytes that comprise the encoded private 11149 * key. It must not be {@code null}. 11150 * @param encryptionPassword The password to use to encrypt the private key. 11151 * It may be {@code null} if the private key 11152 * should not be encrypted. 11153 * 11154 * @throws LDAPException If a problem occurs while trying write the private 11155 * key. 11156 */ 11157 private static void writePEMPrivateKey( 11158 @NotNull final PrintStream printStream, 11159 @NotNull final byte[] encodedPrivateKey, 11160 @Nullable final char[] encryptionPassword) 11161 throws LDAPException 11162 { 11163 if (encryptionPassword == null) 11164 { 11165 final String certBase64 = Base64.encode(encodedPrivateKey); 11166 printStream.println("-----BEGIN PRIVATE KEY-----"); 11167 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 11168 { 11169 printStream.println(line); 11170 } 11171 printStream.println("-----END PRIVATE KEY-----"); 11172 } 11173 else 11174 { 11175 final byte[] encryptedPrivateKey; 11176 try 11177 { 11178 encryptedPrivateKey = PKCS8EncryptionHandler.encryptPrivateKey( 11179 encodedPrivateKey, encryptionPassword, 11180 new PKCS8EncryptionProperties()); 11181 } 11182 catch (final CertException e) 11183 { 11184 Debug.debugException(e); 11185 throw new LDAPException(ResultCode.LOCAL_ERROR, e.getMessage(), e); 11186 } 11187 11188 final String encryptedCertBase64 = Base64.encode(encryptedPrivateKey); 11189 printStream.println("-----BEGIN ENCRYPTED PRIVATE KEY-----"); 11190 for (final String line : StaticUtils.wrapLine(encryptedCertBase64, 64)) 11191 { 11192 printStream.println(line); 11193 } 11194 printStream.println("-----END ENCRYPTED PRIVATE KEY-----"); 11195 } 11196 } 11197 11198 11199 11200 /** 11201 * Displays the keytool command that can be invoked to produce approximately 11202 * equivalent functionality. 11203 * 11204 * @param keytoolArgs The arguments to provide to the keytool command. 11205 */ 11206 private void displayKeytoolCommand(@NotNull final List<String> keytoolArgs) 11207 { 11208 final StringBuilder buffer = new StringBuilder(); 11209 buffer.append("# keytool"); 11210 11211 boolean lastWasArgName = false; 11212 for (final String arg : keytoolArgs) 11213 { 11214 if (arg.startsWith("-")) 11215 { 11216 buffer.append(' '); 11217 buffer.append(StaticUtils.getCommandLineContinuationString()); 11218 buffer.append(StaticUtils.EOL); 11219 buffer.append("# "); 11220 buffer.append(arg); 11221 lastWasArgName = true; 11222 } 11223 else if (lastWasArgName) 11224 { 11225 buffer.append(' '); 11226 buffer.append(StaticUtils.cleanExampleCommandLineArgument(arg)); 11227 lastWasArgName = false; 11228 } 11229 else 11230 { 11231 buffer.append(' '); 11232 buffer.append(StaticUtils.getCommandLineContinuationString()); 11233 buffer.append(StaticUtils.EOL); 11234 buffer.append("# "); 11235 buffer.append(arg); 11236 lastWasArgName = false; 11237 } 11238 } 11239 11240 out(); 11241 out(INFO_MANAGE_CERTS_APPROXIMATE_KEYTOOL_COMMAND.get()); 11242 out(buffer); 11243 out(); 11244 } 11245 11246 11247 11248 /** 11249 * Retrieves the path to the target key store file. 11250 * 11251 * @return The path to the target key store file, or {@code null} if no 11252 * keystore path was configured. 11253 */ 11254 @Nullable() 11255 private File getKeystorePath() 11256 { 11257 return getKeystorePath("keystore"); 11258 } 11259 11260 11261 11262 /** 11263 * Retrieves the path to the target key store file. 11264 * 11265 * @param keystoreArgumentName The name of the argument used to specify the 11266 * path to the target key store. 11267 * 11268 * @return The path to the target keystore file, or {@code null} if no 11269 * keystore path was configured. 11270 */ 11271 @Nullable() 11272 private File getKeystorePath(@NotNull final String keystoreArgumentName) 11273 { 11274 final FileArgument keystoreArgument = 11275 subCommandParser.getFileArgument(keystoreArgumentName); 11276 if ((keystoreArgument != null) && keystoreArgument.isPresent()) 11277 { 11278 return keystoreArgument.getValue(); 11279 } 11280 11281 final BooleanArgument useJVMDefaultTrustStoreArgument = 11282 subCommandParser.getBooleanArgument("useJVMDefaultTrustStore"); 11283 if ((useJVMDefaultTrustStoreArgument != null) && 11284 useJVMDefaultTrustStoreArgument.isPresent()) 11285 { 11286 return JVM_DEFAULT_CACERTS_FILE; 11287 } 11288 11289 return null; 11290 } 11291 11292 11293 11294 /** 11295 * Retrieves the password needed to access the keystore. 11296 * 11297 * @param keystoreFile The path to the keystore file for which to get the 11298 * password. 11299 * 11300 * @return The password needed to access the keystore, or {@code null} if 11301 * no keystore password was configured. 11302 * 11303 * @throws LDAPException If a problem is encountered while trying to get the 11304 * keystore password. 11305 */ 11306 @Nullable() 11307 private char[] getKeystorePassword(@NotNull final File keystoreFile) 11308 throws LDAPException 11309 { 11310 return getKeystorePassword(keystoreFile, null); 11311 } 11312 11313 11314 11315 /** 11316 * Retrieves the password needed to access the keystore. 11317 * 11318 * @param keystoreFile The path to the keystore file for which to get the 11319 * password. 11320 * @param prefix The prefix string to use for the arguments. This may 11321 * be {@code null} if no prefix is needed. 11322 * 11323 * @return The password needed to access the keystore, or {@code null} if 11324 * no keystore password was configured. 11325 * 11326 * @throws LDAPException If a problem is encountered while trying to get the 11327 * keystore password. 11328 */ 11329 @Nullable() 11330 private char[] getKeystorePassword(@NotNull final File keystoreFile, 11331 @Nullable final String prefix) 11332 throws LDAPException 11333 { 11334 final String prefixDash; 11335 if (prefix == null) 11336 { 11337 prefixDash = ""; 11338 } 11339 else 11340 { 11341 prefixDash = prefix + '-'; 11342 } 11343 11344 final StringArgument keystorePasswordArgument = 11345 subCommandParser.getStringArgument(prefixDash + "keystore-password"); 11346 if ((keystorePasswordArgument != null) && 11347 keystorePasswordArgument.isPresent()) 11348 { 11349 final char[] keystorePWChars = 11350 keystorePasswordArgument.getValue().toCharArray(); 11351 if ((! keystoreFile.exists()) && (keystorePWChars.length < 6)) 11352 { 11353 throw new LDAPException(ResultCode.PARAM_ERROR, 11354 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11355 } 11356 11357 return keystorePWChars; 11358 } 11359 11360 11361 final FileArgument keystorePasswordFileArgument = 11362 subCommandParser.getFileArgument( 11363 prefixDash + "keystore-password-file"); 11364 if ((keystorePasswordFileArgument != null) && 11365 keystorePasswordFileArgument.isPresent()) 11366 { 11367 final File f = keystorePasswordFileArgument.getValue(); 11368 try 11369 { 11370 final char[] passwordChars = getPasswordFileReader().readPassword(f); 11371 if (passwordChars.length < 6) 11372 { 11373 throw new LDAPException(ResultCode.PARAM_ERROR, 11374 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11375 } 11376 return passwordChars; 11377 } 11378 catch (final LDAPException e) 11379 { 11380 Debug.debugException(e); 11381 throw e; 11382 } 11383 catch (final Exception e) 11384 { 11385 Debug.debugException(e); 11386 throw new LDAPException(ResultCode.LOCAL_ERROR, 11387 ERR_MANAGE_CERTS_GET_KS_PW_ERROR_READING_FILE.get( 11388 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11389 e); 11390 } 11391 } 11392 11393 11394 final BooleanArgument promptArgument = subCommandParser.getBooleanArgument( 11395 "prompt-for-" + prefixDash + "keystore-password"); 11396 if ((promptArgument != null) && promptArgument.isPresent()) 11397 { 11398 out(); 11399 if (keystoreFile.exists() && (! "new".equals(prefix))) 11400 { 11401 // We're only going to prompt once. 11402 if ((prefix != null) && prefix.equals("current")) 11403 { 11404 return promptForPassword( 11405 INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_CURRENT_PROMPT.get( 11406 keystoreFile.getAbsolutePath()), 11407 false); 11408 } 11409 else 11410 { 11411 return promptForPassword( 11412 INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_PROMPT.get( 11413 keystoreFile.getAbsolutePath()), 11414 false); 11415 } 11416 } 11417 else 11418 { 11419 // We're creating a new keystore, so we should prompt for the password 11420 // twice to prevent setting the wrong password because of a typo. 11421 while (true) 11422 { 11423 final String prompt1; 11424 if ("new".equals(prefix)) 11425 { 11426 prompt1 = INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_NEW_PROMPT.get(); 11427 } 11428 else 11429 { 11430 prompt1 = INFO_MANAGE_CERTS_KEY_KS_PW_NEW_PROMPT_1.get( 11431 keystoreFile.getAbsolutePath()); 11432 } 11433 final char[] pwChars = promptForPassword(prompt1, false); 11434 11435 if (pwChars.length < 6) 11436 { 11437 wrapErr(0, WRAP_COLUMN, 11438 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 11439 err(); 11440 continue; 11441 } 11442 11443 final char[] confirmChars = promptForPassword( 11444 INFO_MANAGE_CERTS_KEY_KS_PW_NEW_PROMPT_2.get(), true); 11445 11446 if (Arrays.equals(pwChars, confirmChars)) 11447 { 11448 Arrays.fill(confirmChars, '\u0000'); 11449 return pwChars; 11450 } 11451 else 11452 { 11453 wrapErr(0, WRAP_COLUMN, 11454 ERR_MANAGE_CERTS_KEY_KS_PW_PROMPT_MISMATCH.get()); 11455 err(); 11456 } 11457 } 11458 } 11459 } 11460 11461 11462 return null; 11463 } 11464 11465 11466 11467 /** 11468 * Retrieves the password used to encrypt a private key. 11469 * 11470 * @param forDecrypt Indicates whether the password will be used to decrypt 11471 * the private key rather than to encrypt it. 11472 * 11473 * @return The password used to encrypt a private key, or {@code null} if no 11474 * encryption password was specified. 11475 * 11476 * @throws LDAPException If a problem is encountered while trying to get the 11477 * keystore password. 11478 */ 11479 @Nullable() 11480 private char[] getPrivateKeyEncryptionPassword(final boolean forDecrypt) 11481 throws LDAPException 11482 { 11483 final StringArgument passwordArgument = 11484 subCommandParser.getStringArgument("encryption-password"); 11485 if ((passwordArgument != null) && passwordArgument.isPresent()) 11486 { 11487 return passwordArgument.getValue().toCharArray(); 11488 } 11489 11490 11491 final FileArgument passwordFileArgument = 11492 subCommandParser.getFileArgument("encryption-password-file"); 11493 if ((passwordFileArgument != null) && passwordFileArgument.isPresent()) 11494 { 11495 final File f = passwordFileArgument.getValue(); 11496 try 11497 { 11498 return getPasswordFileReader().readPassword(f); 11499 } 11500 catch (final LDAPException e) 11501 { 11502 Debug.debugException(e); 11503 throw e; 11504 } 11505 catch (final Exception e) 11506 { 11507 Debug.debugException(e); 11508 throw new LDAPException(ResultCode.LOCAL_ERROR, 11509 ERR_MANAGE_CERTS_GET_PK_ENC_PW_ERROR_READING_FILE.get( 11510 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11511 e); 11512 } 11513 } 11514 11515 11516 final BooleanArgument promptArgument = subCommandParser.getBooleanArgument( 11517 "prompt-for-encryption-password"); 11518 if ((promptArgument != null) && promptArgument.isPresent()) 11519 { 11520 out(); 11521 if (forDecrypt) 11522 { 11523 // We'll be decrypting an existing private key, so we only need to 11524 // prompt for the password once. 11525 return promptForPassword( 11526 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_DECRYPT.get(), false); 11527 } 11528 else 11529 { 11530 // We'll be encrypting the private key, so we need to prompt twice to 11531 // confirm that the entered password is what the user intended. 11532 while (true) 11533 { 11534 final char[] pwChars = promptForPassword( 11535 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_ENCRYPT_1.get(), false); 11536 final char[] confirmChars = promptForPassword( 11537 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_ENCRYPT_2.get(), true); 11538 11539 if (Arrays.equals(pwChars, confirmChars)) 11540 { 11541 Arrays.fill(confirmChars, '\u0000'); 11542 return pwChars; 11543 } 11544 else 11545 { 11546 wrapErr(0, WRAP_COLUMN, 11547 INFO_MANAGE_CERTS_GET_PK_ENC_PW_PROMPT_MISMATCH.get()); 11548 err(); 11549 } 11550 } 11551 } 11552 } 11553 11554 11555 return null; 11556 } 11557 11558 11559 11560 /** 11561 * Prompts for a password and retrieves the value that the user entered. 11562 * 11563 * @param prompt The prompt to display to the user. 11564 * @param allowEmpty Indicates whether to allow the password to be empty. 11565 * 11566 * @return The password that was read, or an empty array if the user did not 11567 * type a password before pressing ENTER. 11568 * 11569 * @throws LDAPException If a problem is encountered while reading the 11570 * password. 11571 */ 11572 @NotNull() 11573 private char[] promptForPassword(@NotNull final String prompt, 11574 final boolean allowEmpty) 11575 throws LDAPException 11576 { 11577 final Iterator<String> iterator = 11578 StaticUtils.wrapLine(prompt, WRAP_COLUMN).iterator(); 11579 while (iterator.hasNext()) 11580 { 11581 final String line = iterator.next(); 11582 if (iterator.hasNext()) 11583 { 11584 out(line); 11585 } 11586 else 11587 { 11588 getOut().print(line); 11589 } 11590 } 11591 11592 final char[] passwordChars = PasswordReader.readPasswordChars(); 11593 if ((passwordChars.length == 0) && (! allowEmpty)) 11594 { 11595 wrapErr(0, WRAP_COLUMN, 11596 ERR_MANAGE_CERTS_PROMPT_FOR_PW_EMPTY_PW.get()); 11597 err(); 11598 return promptForPassword(prompt, allowEmpty); 11599 } 11600 11601 return passwordChars; 11602 } 11603 11604 11605 11606 /** 11607 * Prompts the user for a yes or no response. 11608 * 11609 * @param prompt The prompt to display to the end user. 11610 * 11611 * @return {@code true} if the user chooses the "yes" response, or 11612 * {@code false} if the user chooses the "no" throws. 11613 * 11614 * @throws LDAPException If a problem is encountered while reading data from 11615 * the client. 11616 */ 11617 private boolean promptForYesNo(@NotNull final String prompt) 11618 throws LDAPException 11619 { 11620 while (true) 11621 { 11622 final List<String> lines = 11623 StaticUtils.wrapLine((prompt + ' '), WRAP_COLUMN); 11624 11625 final Iterator<String> lineIterator = lines.iterator(); 11626 while (lineIterator.hasNext()) 11627 { 11628 final String line = lineIterator.next(); 11629 if (lineIterator.hasNext()) 11630 { 11631 out(line); 11632 } 11633 else 11634 { 11635 getOut().print(line); 11636 } 11637 } 11638 11639 try 11640 { 11641 final String response = readLineFromIn(); 11642 if (response.equalsIgnoreCase("yes") || response.equalsIgnoreCase("y")) 11643 { 11644 return true; 11645 } 11646 else if (response.equalsIgnoreCase("no") || 11647 response.equalsIgnoreCase("n")) 11648 { 11649 return false; 11650 } 11651 else 11652 { 11653 err(); 11654 wrapErr(0, WRAP_COLUMN, 11655 ERR_MANAGE_CERTS_PROMPT_FOR_YES_NO_INVALID_RESPONSE.get()); 11656 err(); 11657 } 11658 } 11659 catch (final Exception e) 11660 { 11661 Debug.debugException(e); 11662 throw new LDAPException(ResultCode.LOCAL_ERROR, 11663 ERR_MANAGE_CERTS_PROMPT_FOR_YES_NO_READ_ERROR.get( 11664 StaticUtils.getExceptionMessage(e)), 11665 e); 11666 } 11667 } 11668 } 11669 11670 11671 11672 /** 11673 * Reads a line of input from standard input. 11674 * 11675 * @return The line read from standard input. 11676 * 11677 * @throws IOException If a problem is encountered while reading from 11678 * standard input. 11679 */ 11680 @NotNull() 11681 private String readLineFromIn() 11682 throws IOException 11683 { 11684 final ByteStringBuffer buffer = new ByteStringBuffer(); 11685 while (true) 11686 { 11687 final int byteRead = in.read(); 11688 if (byteRead < 0) 11689 { 11690 if (buffer.isEmpty()) 11691 { 11692 return null; 11693 } 11694 else 11695 { 11696 return buffer.toString(); 11697 } 11698 } 11699 11700 if (byteRead == '\n') 11701 { 11702 return buffer.toString(); 11703 } 11704 else if (byteRead == '\r') 11705 { 11706 final int nextByteRead = in.read(); 11707 Validator.ensureTrue(((nextByteRead < 0) || (nextByteRead == '\n')), 11708 "ERROR: Read a carriage return from standard input that was " + 11709 "not followed by a new line."); 11710 return buffer.toString(); 11711 } 11712 else 11713 { 11714 buffer.append((byte) (byteRead & 0xFF)); 11715 } 11716 } 11717 } 11718 11719 11720 11721 /** 11722 * Retrieves the password needed to access the private key. 11723 * 11724 * @param keystore The keystore that contains the target private 11725 * key. This must not be {@code null}. 11726 * @param alias The alias of the target private key. This must 11727 * not be {@code null}. 11728 * @param keystorePassword The keystore password to use if no specific 11729 * private key password was provided. 11730 * 11731 * @return The password needed to access the private key, or the provided 11732 * keystore password if no arguments were provided to specify a 11733 * different private key password. 11734 * 11735 * @throws LDAPException If a problem is encountered while trying to get the 11736 * private key password. 11737 */ 11738 @Nullable() 11739 private char[] getPrivateKeyPassword(@NotNull final KeyStore keystore, 11740 @NotNull final String alias, 11741 @Nullable final char[] keystorePassword) 11742 throws LDAPException 11743 { 11744 return getPrivateKeyPassword(keystore, alias, null, keystorePassword); 11745 } 11746 11747 11748 11749 /** 11750 * Retrieves the password needed to access the private key. 11751 * 11752 * @param keystore The keystore that contains the target private 11753 * key. This must not be {@code null}. 11754 * @param alias The alias of the target private key. This must 11755 * not be {@code null}. 11756 * @param prefix The prefix string to use for the arguments. This 11757 * may be {@code null} if no prefix is needed. 11758 * @param keystorePassword The keystore password to use if no specific 11759 * private key password was provided. 11760 * 11761 * @return The password needed to access the private key, or the provided 11762 * keystore password if no arguments were provided to specify a 11763 * different private key password. 11764 * 11765 * @throws LDAPException If a problem is encountered while trying to get the 11766 * private key password. 11767 */ 11768 @Nullable() 11769 private char[] getPrivateKeyPassword(@NotNull final KeyStore keystore, 11770 @NotNull final String alias, 11771 @Nullable final String prefix, 11772 @Nullable final char[] keystorePassword) 11773 throws LDAPException 11774 { 11775 final String prefixDash; 11776 if (prefix == null) 11777 { 11778 prefixDash = ""; 11779 } 11780 else 11781 { 11782 prefixDash = prefix + '-'; 11783 } 11784 11785 final StringArgument privateKeyPasswordArgument = 11786 subCommandParser.getStringArgument( 11787 prefixDash + "private-key-password"); 11788 if ((privateKeyPasswordArgument != null) && 11789 privateKeyPasswordArgument.isPresent()) 11790 { 11791 final char[] pkPasswordChars = 11792 privateKeyPasswordArgument.getValue().toCharArray(); 11793 if ((pkPasswordChars.length < 6) && 11794 (! (hasCertificateAlias(keystore, alias) || 11795 hasKeyAlias(keystore, alias)))) 11796 { 11797 throw new LDAPException(ResultCode.PARAM_ERROR, 11798 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 11799 } 11800 11801 return pkPasswordChars; 11802 } 11803 11804 11805 final FileArgument privateKeyPasswordFileArgument = 11806 subCommandParser.getFileArgument( 11807 prefixDash + "private-key-password-file"); 11808 if ((privateKeyPasswordFileArgument != null) && 11809 privateKeyPasswordFileArgument.isPresent()) 11810 { 11811 final File f = privateKeyPasswordFileArgument.getValue(); 11812 try 11813 { 11814 final char[] passwordChars = getPasswordFileReader().readPassword(f); 11815 if (passwordChars.length < 6) 11816 { 11817 throw new LDAPException(ResultCode.PARAM_ERROR, 11818 ERR_MANAGE_CERTS_GET_PK_PW_EMPTY_FILE.get(f.getAbsolutePath())); 11819 } 11820 11821 return passwordChars; 11822 } 11823 catch (final LDAPException e) 11824 { 11825 Debug.debugException(e); 11826 throw e; 11827 } 11828 catch (final Exception e) 11829 { 11830 Debug.debugException(e); 11831 throw new LDAPException(ResultCode.LOCAL_ERROR, 11832 ERR_MANAGE_CERTS_GET_PK_PW_ERROR_READING_FILE.get( 11833 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11834 e); 11835 } 11836 } 11837 11838 11839 final BooleanArgument promptArgument = 11840 subCommandParser.getBooleanArgument( 11841 "prompt-for-" + prefixDash + "private-key-password"); 11842 if ((promptArgument != null) && promptArgument.isPresent()) 11843 { 11844 out(); 11845 11846 try 11847 { 11848 if ((hasKeyAlias(keystore, alias) || 11849 hasCertificateAlias(keystore, alias)) && 11850 (! "new".equals(prefix)) && (! "destination".equals(prefix))) 11851 { 11852 // This means that the private key already exists, so we just need to 11853 // prompt once. 11854 final String prompt; 11855 if ("current".equals(prefix)) 11856 { 11857 prompt = 11858 INFO_MANAGE_CERTS_GET_PK_PW_CURRENT_PROMPT.get(alias); 11859 } 11860 else 11861 { 11862 prompt = 11863 INFO_MANAGE_CERTS_GET_PK_PW_EXISTING_PROMPT.get(alias); 11864 } 11865 11866 return promptForPassword(prompt, false); 11867 } 11868 else 11869 { 11870 // This means that we'll be creating a new private key, so we need to 11871 // prompt twice. 11872 while (true) 11873 { 11874 final String prompt; 11875 if ("new".equals(prefix)) 11876 { 11877 prompt = INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT.get(); 11878 } 11879 else 11880 { 11881 prompt = INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT_1.get(alias); 11882 } 11883 11884 final char[] pwChars = promptForPassword(prompt, false); 11885 if (pwChars.length < 6) 11886 { 11887 wrapErr(0, WRAP_COLUMN, 11888 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 11889 err(); 11890 continue; 11891 } 11892 11893 final char[] confirmChars = promptForPassword( 11894 INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT_2.get(), true); 11895 11896 if (Arrays.equals(pwChars, confirmChars)) 11897 { 11898 Arrays.fill(confirmChars, '\u0000'); 11899 return pwChars; 11900 } 11901 else 11902 { 11903 wrapErr(0, WRAP_COLUMN, 11904 ERR_MANAGE_CERTS_GET_PK_PW_PROMPT_MISMATCH.get()); 11905 err(); 11906 } 11907 } 11908 } 11909 } 11910 catch (final LDAPException le) 11911 { 11912 Debug.debugException(le); 11913 throw le; 11914 } 11915 catch (final Exception e) 11916 { 11917 Debug.debugException(e); 11918 throw new LDAPException(ResultCode.LOCAL_ERROR, 11919 ERR_MANAGE_CERTS_GET_PK_PW_PROMPT_ERROR.get(alias, 11920 StaticUtils.getExceptionMessage(e)), 11921 e); 11922 } 11923 } 11924 11925 11926 return keystorePassword; 11927 } 11928 11929 11930 11931 /** 11932 * Infers the keystore type from the provided keystore file. 11933 * 11934 * @param keystorePath The path to the file to examine. 11935 * 11936 * @return The keystore type inferred from the provided keystore file. 11937 * 11938 * @throws LDAPException If a problem is encountered while trying to infer 11939 * the keystore type. 11940 */ 11941 @NotNull() 11942 private String inferKeystoreType(@NotNull final File keystorePath) 11943 throws LDAPException 11944 { 11945 return inferKeystoreType(keystorePath, null); 11946 } 11947 11948 11949 11950 /** 11951 * Infers the keystore type from the provided keystore file. 11952 * 11953 * @param keystorePath The path to the file to examine. 11954 * @param prefix The prefix string to use for the arguments. This 11955 * may be {@code null} if no prefix is needed. 11956 * 11957 * @return The keystore type inferred from the provided keystore file. 11958 * 11959 * @throws LDAPException If a problem is encountered while trying to infer 11960 * the keystore type. 11961 */ 11962 @NotNull() 11963 private String inferKeystoreType(@NotNull final File keystorePath, 11964 @Nullable final String prefix) 11965 throws LDAPException 11966 { 11967 // If the keystore type argument was specified, then use its value. 11968 final StringArgument keystoreTypeArgument; 11969 if (prefix == null) 11970 { 11971 keystoreTypeArgument = 11972 subCommandParser.getStringArgument("keystore-type"); 11973 } 11974 else 11975 { 11976 keystoreTypeArgument = 11977 subCommandParser.getStringArgument(prefix + "-keystore-type"); 11978 } 11979 11980 if ((keystoreTypeArgument != null) && keystoreTypeArgument.isPresent()) 11981 { 11982 final String ktaValue = keystoreTypeArgument.getValue(); 11983 if (ktaValue.equalsIgnoreCase("PKCS11") || 11984 ktaValue.equalsIgnoreCase("PKCS 11") || 11985 ktaValue.equalsIgnoreCase("PKCS#11") || 11986 ktaValue.equalsIgnoreCase("PKCS #11")) 11987 { 11988 return CryptoHelper.KEY_STORE_TYPE_PKCS_11; 11989 } 11990 else if (ktaValue.equalsIgnoreCase("PKCS12") || 11991 ktaValue.equalsIgnoreCase("PKCS 12") || 11992 ktaValue.equalsIgnoreCase("PKCS#12") || 11993 ktaValue.equalsIgnoreCase("PKCS #12")) 11994 { 11995 return CryptoHelper.KEY_STORE_TYPE_PKCS_12; 11996 } 11997 else if (ktaValue.equalsIgnoreCase(BCFKS_KEYSTORE_TYPE)) 11998 { 11999 return BCFKS_KEYSTORE_TYPE; 12000 } 12001 else 12002 { 12003 return CryptoHelper.KEY_STORE_TYPE_JKS; 12004 } 12005 } 12006 12007 12008 // If we've gotten here, then the keystore type was not explicitly specified 12009 // so we will need to infer it. If the LDAP SDK is running in FIPS mode, 12010 // then we'll always use the BCFKS key store type. 12011 if (CryptoHelper.usingFIPSMode()) 12012 { 12013 return BouncyCastleFIPSHelper.FIPS_KEY_STORE_TYPE; 12014 } 12015 12016 12017 // If the key store file doesn't exist, then we must be creating it. Use 12018 // the default key store type. 12019 if (! keystorePath.exists()) 12020 { 12021 return DEFAULT_KEYSTORE_TYPE; 12022 } 12023 12024 12025 try 12026 { 12027 return CryptoHelper.inferKeyStoreType(keystorePath); 12028 } 12029 catch (final Exception e) 12030 { 12031 Debug.debugException(e); 12032 throw new LDAPException(ResultCode.PARAM_ERROR, e.getMessage(), e); 12033 } 12034 } 12035 12036 12037 12038 /** 12039 * Retrieves a user-friendly representation of the provided keystore type. 12040 * 12041 * @param keystoreType The keystore type for which to get the user-friendly 12042 * name. 12043 * 12044 * @return "JKS" if the provided keystore type is for a JKS keystore, 12045 * "PKCS #12" if the provided keystore type is for a PKCS #12 12046 * keystore, or the provided string if it is for some other keystore 12047 * type. 12048 */ 12049 @NotNull() 12050 static String getUserFriendlyKeystoreType(@NotNull final String keystoreType) 12051 { 12052 if (keystoreType.equalsIgnoreCase("JKS")) 12053 { 12054 return "JKS"; 12055 } 12056 else if (keystoreType.equalsIgnoreCase("PKCS11") || 12057 keystoreType.equalsIgnoreCase("PKCS 11") || 12058 keystoreType.equalsIgnoreCase("PKCS#11") || 12059 keystoreType.equalsIgnoreCase("PKCS #11")) 12060 { 12061 return "PKCS #11"; 12062 } 12063 else if (keystoreType.equalsIgnoreCase("PKCS12") || 12064 keystoreType.equalsIgnoreCase("PKCS 12") || 12065 keystoreType.equalsIgnoreCase("PKCS#12") || 12066 keystoreType.equalsIgnoreCase("PKCS #12")) 12067 { 12068 return "PKCS #12"; 12069 } 12070 else if (keystoreType.equalsIgnoreCase(BCFKS_KEYSTORE_TYPE)) 12071 { 12072 return BCFKS_KEYSTORE_TYPE; 12073 } 12074 else 12075 { 12076 return keystoreType; 12077 } 12078 } 12079 12080 12081 12082 /** 12083 * Gets access to a keystore based on information included in command-line 12084 * arguments. 12085 * 12086 * @param keystoreType The keystore type for the keystore to access. 12087 * @param keystorePath The path to the keystore file. 12088 * @param keystorePassword The password to use to access the keystore. 12089 * 12090 * @return The configured keystore instance. 12091 * 12092 * @throws LDAPException If it is not possible to access the keystore. 12093 */ 12094 @NotNull() 12095 static KeyStore getKeystore(@NotNull final String keystoreType, 12096 @NotNull final File keystorePath, 12097 @Nullable final char[] keystorePassword) 12098 throws LDAPException 12099 { 12100 // Instantiate a keystore instance of the desired keystore type. 12101 final KeyStore keystore; 12102 try 12103 { 12104 if (keystoreType.equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11)) 12105 { 12106 // NOTE: For PKCS #11 key store types, the key store path will be 12107 // treated as the path to the provider configuration file. 12108 final Provider pkcs11Provider = PKCS11KeyManager.getProvider(null, 12109 keystorePath, keystoreType, true); 12110 keystore = CryptoHelper.getKeyStore(keystoreType, pkcs11Provider); 12111 } 12112 else if (keystoreType.equals(BCFKS_KEYSTORE_TYPE)) 12113 { 12114 keystore = CryptoHelper.getKeyStore(keystoreType, 12115 BouncyCastleFIPSHelper.getBouncyCastleFIPSProvider()); 12116 } 12117 else 12118 { 12119 keystore = CryptoHelper.getKeyStore(keystoreType); 12120 } 12121 } 12122 catch (final Exception e) 12123 { 12124 Debug.debugException(e); 12125 throw new LDAPException(ResultCode.LOCAL_ERROR, 12126 ERR_MANAGE_CERTS_CANNOT_INSTANTIATE_KS_TYPE.get(keystoreType, 12127 StaticUtils.getExceptionMessage(e)), 12128 e); 12129 } 12130 12131 12132 // Get an input stream that may be used to access the keystore. 12133 final InputStream inputStream; 12134 try 12135 { 12136 if (keystorePath.exists() && 12137 (! keystoreType.equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11))) 12138 { 12139 inputStream = new FileInputStream(keystorePath); 12140 } 12141 else 12142 { 12143 inputStream = null; 12144 } 12145 } 12146 catch (final Exception e) 12147 { 12148 Debug.debugException(e); 12149 throw new LDAPException(ResultCode.LOCAL_ERROR, 12150 ERR_MANAGE_CERTS_CANNOT_OPEN_KS_FILE_FOR_READING.get( 12151 keystorePath.getAbsolutePath(), 12152 StaticUtils.getExceptionMessage(e)), 12153 e); 12154 } 12155 12156 try 12157 { 12158 keystore.load(inputStream, keystorePassword); 12159 } 12160 catch (final Exception e) 12161 { 12162 Debug.debugException(e); 12163 final Throwable cause = e.getCause(); 12164 if ((e instanceof IOException) && (cause != null) && 12165 (cause instanceof UnrecoverableKeyException) && 12166 (keystorePassword != null)) 12167 { 12168 throw new LDAPException(ResultCode.PARAM_ERROR, 12169 ERR_MANAGE_CERTS_CANNOT_LOAD_KS_WRONG_PW.get( 12170 keystorePath.getAbsolutePath()), 12171 e); 12172 } 12173 else 12174 { 12175 throw new LDAPException(ResultCode.PARAM_ERROR, 12176 ERR_MANAGE_CERTS_ERROR_CANNOT_LOAD_KS.get( 12177 keystorePath.getAbsolutePath(), 12178 StaticUtils.getExceptionMessage(e)), 12179 e); 12180 } 12181 } 12182 finally 12183 { 12184 try 12185 { 12186 if (inputStream != null) 12187 { 12188 inputStream.close(); 12189 } 12190 } 12191 catch (final Exception e) 12192 { 12193 Debug.debugException(e); 12194 } 12195 } 12196 12197 return keystore; 12198 } 12199 12200 12201 12202 /** 12203 * Reads all of the certificates contained in the specified file. The file 12204 * must exist and may contain zero or more certificates that are either all in 12205 * PEM format or all in DER format. 12206 * 12207 * @param f The path to the certificate file to read. It must not be 12208 * {@code null}. 12209 * 12210 * @return A list of the certificates read from the specified file. 12211 * 12212 * @throws LDAPException If a problem is encountered while reading 12213 * certificates from the specified file. 12214 */ 12215 @NotNull() 12216 public static List<X509Certificate> readCertificatesFromFile( 12217 @NotNull final File f) 12218 throws LDAPException 12219 { 12220 // Read the first byte of the file to see if it contains DER-formatted data, 12221 // which we can determine by seeing if the first byte is 0x30. 12222 try (BufferedInputStream inputStream = 12223 new BufferedInputStream(new FileInputStream(f))) 12224 { 12225 inputStream.mark(1); 12226 final int firstByte = inputStream.read(); 12227 12228 if (firstByte < 0) 12229 { 12230 // This means that the file is empty. 12231 return Collections.emptyList(); 12232 } 12233 else 12234 { 12235 inputStream.reset(); 12236 } 12237 12238 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 12239 if ((firstByte & 0xFF) == 0x30) 12240 { 12241 // It is a DER-encoded file. Read ASN.1 elements and decode them as 12242 // X.509 certificates. 12243 while (true) 12244 { 12245 final ASN1Element certElement; 12246 try 12247 { 12248 certElement = ASN1Element.readFrom(inputStream); 12249 } 12250 catch (final Exception e) 12251 { 12252 Debug.debugException(e); 12253 throw new LDAPException(ResultCode.LOCAL_ERROR, 12254 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DER_NOT_VALID_ASN1.get( 12255 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12256 e); 12257 } 12258 12259 if (certElement == null) 12260 { 12261 // We've reached the end of the input stream. 12262 return certList; 12263 } 12264 12265 try 12266 { 12267 certList.add(new X509Certificate(certElement.encode())); 12268 } 12269 catch (final CertException e) 12270 { 12271 Debug.debugException(e); 12272 throw new LDAPException(ResultCode.PARAM_ERROR, 12273 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DER_NOT_VALID_CERT.get( 12274 f.getAbsolutePath(), e.getMessage()), 12275 e); 12276 } 12277 } 12278 } 12279 else 12280 { 12281 try (BufferedReader reader = 12282 new BufferedReader(new InputStreamReader(inputStream))) 12283 { 12284 boolean inCert = false; 12285 final StringBuilder buffer = new StringBuilder(); 12286 while (true) 12287 { 12288 String line = reader.readLine(); 12289 if (line == null) 12290 { 12291 if (inCert) 12292 { 12293 throw new LDAPException(ResultCode.PARAM_ERROR, 12294 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_EOF_WITHOUT_END.get( 12295 f.getAbsolutePath())); 12296 } 12297 12298 return certList; 12299 } 12300 12301 line = line.trim(); 12302 if (line.isEmpty() || line.startsWith("#")) 12303 { 12304 continue; 12305 } 12306 12307 if (line.equals("-----BEGIN CERTIFICATE-----")) 12308 { 12309 if (inCert) 12310 { 12311 throw new LDAPException(ResultCode.PARAM_ERROR, 12312 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_MULTIPLE_BEGIN.get( 12313 f.getAbsolutePath())); 12314 } 12315 else 12316 { 12317 inCert = true; 12318 } 12319 } 12320 else if (line.equals("-----END CERTIFICATE-----")) 12321 { 12322 if (! inCert) 12323 { 12324 throw new LDAPException(ResultCode.PARAM_ERROR, 12325 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_END_WITHOUT_BEGIN. 12326 get(f.getAbsolutePath())); 12327 } 12328 12329 inCert = false; 12330 final byte[] certBytes; 12331 try 12332 { 12333 certBytes = Base64.decode(buffer.toString()); 12334 } 12335 catch (final Exception e) 12336 { 12337 Debug.debugException(e); 12338 throw new LDAPException(ResultCode.PARAM_ERROR, 12339 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_PEM_CERT_NOT_BASE64. 12340 get(f.getAbsolutePath(), 12341 StaticUtils.getExceptionMessage(e)), 12342 e); 12343 } 12344 12345 try 12346 { 12347 certList.add(new X509Certificate(certBytes)); 12348 } 12349 catch (final CertException e) 12350 { 12351 Debug.debugException(e); 12352 throw new LDAPException(ResultCode.PARAM_ERROR, 12353 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_PEM_CERT_NOT_CERT. 12354 get(f.getAbsolutePath(), e.getMessage()), 12355 e); 12356 } 12357 12358 buffer.setLength(0); 12359 } 12360 else if (inCert) 12361 { 12362 buffer.append(line); 12363 } 12364 else 12365 { 12366 throw new LDAPException(ResultCode.PARAM_ERROR, 12367 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12368 f.getAbsolutePath())); 12369 } 12370 } 12371 } 12372 } 12373 } 12374 catch (final LDAPException le) 12375 { 12376 Debug.debugException(le); 12377 throw le; 12378 } 12379 catch (final Exception e) 12380 { 12381 Debug.debugException(e); 12382 throw new LDAPException(ResultCode.LOCAL_ERROR, 12383 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_READ_ERROR.get( 12384 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12385 e); 12386 } 12387 } 12388 12389 12390 12391 /** 12392 * Reads a private key from the specified file. The file must exist and must 12393 * contain exactly one PEM-encoded or DER-encoded PKCS #8 private key. 12394 * 12395 * @param f The path to the private key file to read. It 12396 * must not be {@code null}. 12397 * @param encryptionPassword The password to use to encrypt the private key. 12398 * It may be {@code null} if the private key is 12399 * not encrypted. 12400 * 12401 * @return The private key read from the file. 12402 * 12403 * @throws LDAPException If a problem is encountered while reading the 12404 * private key. 12405 */ 12406 @NotNull() 12407 static PKCS8PrivateKey readPrivateKeyFromFile(@NotNull final File f, 12408 @Nullable final char[] encryptionPassword) 12409 throws LDAPException 12410 { 12411 // Read the first byte of the file to see if it contains DER-formatted data, 12412 // which we can determine by seeing if the first byte is 0x30. 12413 try (BufferedInputStream inputStream = 12414 new BufferedInputStream(new FileInputStream(f))) 12415 { 12416 inputStream.mark(1); 12417 final int firstByte = inputStream.read(); 12418 12419 if (firstByte < 0) 12420 { 12421 // This means that the file is empty. 12422 throw new LDAPException(ResultCode.PARAM_ERROR, 12423 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12424 f.getAbsolutePath())); 12425 } 12426 else 12427 { 12428 inputStream.reset(); 12429 } 12430 12431 PKCS8PrivateKey privateKey = null; 12432 if ((firstByte & 0xFF) == 0x30) 12433 { 12434 // It is a DER-encoded file. Read an ASN.1 element and decode it as a 12435 // certificate. 12436 while (true) 12437 { 12438 final ASN1Element pkElement; 12439 try 12440 { 12441 pkElement = ASN1Element.readFrom(inputStream); 12442 } 12443 catch (final Exception e) 12444 { 12445 Debug.debugException(e); 12446 throw new LDAPException(ResultCode.LOCAL_ERROR, 12447 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DER_NOT_VALID_ASN1.get( 12448 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12449 e); 12450 } 12451 12452 if (pkElement == null) 12453 { 12454 // We've reached the end of the input stream. 12455 if (privateKey == null) 12456 { 12457 throw new LDAPException(ResultCode.PARAM_ERROR, 12458 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12459 f.getAbsolutePath())); 12460 } 12461 else 12462 { 12463 return privateKey; 12464 } 12465 } 12466 else if (privateKey == null) 12467 { 12468 try 12469 { 12470 if (encryptionPassword == null) 12471 { 12472 privateKey = new PKCS8PrivateKey(pkElement.encode()); 12473 } 12474 else 12475 { 12476 privateKey = PKCS8EncryptionHandler.decryptPrivateKey( 12477 pkElement.encode(), encryptionPassword); 12478 } 12479 } 12480 catch (final Exception e) 12481 { 12482 Debug.debugException(e); 12483 throw new LDAPException(ResultCode.PARAM_ERROR, 12484 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DER_NOT_VALID_PK.get( 12485 f.getAbsolutePath(), e.getMessage()), 12486 e); 12487 } 12488 } 12489 else 12490 { 12491 throw new LDAPException(ResultCode.PARAM_ERROR, 12492 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_KEYS.get( 12493 f.getAbsolutePath())); 12494 } 12495 } 12496 } 12497 else 12498 { 12499 try (BufferedReader reader = 12500 new BufferedReader(new InputStreamReader(inputStream))) 12501 { 12502 boolean inKey = false; 12503 boolean isRSAKey = false; 12504 boolean isEncryptedKey = false; 12505 final StringBuilder buffer = new StringBuilder(); 12506 while (true) 12507 { 12508 String line = reader.readLine(); 12509 if (line == null) 12510 { 12511 if (inKey) 12512 { 12513 throw new LDAPException(ResultCode.PARAM_ERROR, 12514 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EOF_WITHOUT_END.get( 12515 f.getAbsolutePath())); 12516 } 12517 12518 if (privateKey == null) 12519 { 12520 throw new LDAPException(ResultCode.PARAM_ERROR, 12521 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 12522 f.getAbsolutePath())); 12523 } 12524 else 12525 { 12526 return privateKey; 12527 } 12528 } 12529 12530 line = line.trim(); 12531 if (line.isEmpty() || line.startsWith("#")) 12532 { 12533 continue; 12534 } 12535 12536 if (line.equals("-----BEGIN PRIVATE KEY-----") || 12537 line.equals("-----BEGIN RSA PRIVATE KEY-----") || 12538 line.equals("-----BEGIN ENCRYPTED PRIVATE KEY-----")) 12539 { 12540 if (inKey) 12541 { 12542 throw new LDAPException(ResultCode.PARAM_ERROR, 12543 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_BEGIN.get( 12544 f.getAbsolutePath())); 12545 } 12546 else if (privateKey != null) 12547 { 12548 throw new LDAPException(ResultCode.PARAM_ERROR, 12549 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_KEYS.get( 12550 f.getAbsolutePath())); 12551 } 12552 else 12553 { 12554 inKey = true; 12555 if (line.equals("-----BEGIN RSA PRIVATE KEY-----")) 12556 { 12557 isRSAKey = true; 12558 } 12559 else if (line.equals("-----BEGIN ENCRYPTED PRIVATE KEY-----")) 12560 { 12561 isEncryptedKey = true; 12562 if (encryptionPassword == null) 12563 { 12564 throw new LDAPException(ResultCode.PARAM_ERROR, 12565 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PK_ENCRYPTED_NO_PW. 12566 get(f.getAbsolutePath())); 12567 } 12568 } 12569 } 12570 } 12571 else if (line.equals("-----END PRIVATE KEY-----") || 12572 line.equals("-----END RSA PRIVATE KEY-----") || 12573 line.equals("-----END ENCRYPTED PRIVATE KEY-----")) 12574 { 12575 if (! inKey) 12576 { 12577 throw new LDAPException(ResultCode.PARAM_ERROR, 12578 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_END_WITHOUT_BEGIN.get( 12579 f.getAbsolutePath())); 12580 } 12581 12582 inKey = false; 12583 byte[] pkBytes; 12584 try 12585 { 12586 pkBytes = Base64.decode(buffer.toString()); 12587 } 12588 catch (final Exception e) 12589 { 12590 Debug.debugException(e); 12591 throw new LDAPException(ResultCode.PARAM_ERROR, 12592 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PEM_PK_NOT_BASE64.get( 12593 f.getAbsolutePath(), 12594 StaticUtils.getExceptionMessage(e)), 12595 e); 12596 } 12597 12598 if (isRSAKey) 12599 { 12600 pkBytes = PKCS8PrivateKey.wrapRSAPrivateKey(pkBytes); 12601 } 12602 12603 try 12604 { 12605 if (isEncryptedKey) 12606 { 12607 privateKey = PKCS8EncryptionHandler. 12608 decryptPrivateKey(pkBytes, encryptionPassword); 12609 } 12610 else 12611 { 12612 privateKey = new PKCS8PrivateKey(pkBytes); 12613 } 12614 } 12615 catch (final CertException e) 12616 { 12617 Debug.debugException(e); 12618 throw new LDAPException(ResultCode.PARAM_ERROR, 12619 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PEM_PK_NOT_PK.get( 12620 f.getAbsolutePath(), e.getMessage()), 12621 e); 12622 } 12623 12624 buffer.setLength(0); 12625 } 12626 else if (inKey) 12627 { 12628 buffer.append(line); 12629 } 12630 else 12631 { 12632 throw new LDAPException(ResultCode.PARAM_ERROR, 12633 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12634 f.getAbsolutePath())); 12635 } 12636 } 12637 } 12638 } 12639 } 12640 catch (final LDAPException le) 12641 { 12642 Debug.debugException(le); 12643 throw le; 12644 } 12645 catch (final Exception e) 12646 { 12647 Debug.debugException(e); 12648 throw new LDAPException(ResultCode.LOCAL_ERROR, 12649 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_READ_ERROR.get( 12650 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12651 e); 12652 } 12653 } 12654 12655 12656 12657 /** 12658 * Reads a certificate signing request from the specified file. The file must 12659 * exist and must contain exactly one PEM-encoded or DER-encoded PKCS #10 12660 * certificate signing request. 12661 * 12662 * @param f The path to the private key file to read. It must not be 12663 * {@code null}. 12664 * 12665 * @return The certificate signing request read from the file. 12666 * 12667 * @throws LDAPException If a problem is encountered while reading the 12668 * certificate signing request. 12669 */ 12670 @NotNull() 12671 public static PKCS10CertificateSigningRequest 12672 readCertificateSigningRequestFromFile( 12673 @NotNull final File f) 12674 throws LDAPException 12675 { 12676 // Read the first byte of the file to see if it contains DER-formatted data, 12677 // which we can determine by seeing if the first byte is 0x30. 12678 try (BufferedInputStream inputStream = 12679 new BufferedInputStream(new FileInputStream(f))) 12680 { 12681 inputStream.mark(1); 12682 final int firstByte = inputStream.read(); 12683 12684 if (firstByte < 0) 12685 { 12686 // This means that the file is empty. 12687 throw new LDAPException(ResultCode.PARAM_ERROR, 12688 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12689 f.getAbsolutePath())); 12690 } 12691 else 12692 { 12693 inputStream.reset(); 12694 } 12695 12696 PKCS10CertificateSigningRequest csr = null; 12697 if ((firstByte & 0xFF) == 0x30) 12698 { 12699 // It is a DER-encoded file. Read an ASN.1 element and decode it as a 12700 // certificate. 12701 while (true) 12702 { 12703 final ASN1Element csrElement; 12704 try 12705 { 12706 csrElement = ASN1Element.readFrom(inputStream); 12707 } 12708 catch (final Exception e) 12709 { 12710 Debug.debugException(e); 12711 throw new LDAPException(ResultCode.LOCAL_ERROR, 12712 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DER_NOT_VALID_ASN1.get( 12713 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12714 e); 12715 } 12716 12717 if (csrElement == null) 12718 { 12719 // We've reached the end of the input stream. 12720 if (csr == null) 12721 { 12722 throw new LDAPException(ResultCode.PARAM_ERROR, 12723 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12724 f.getAbsolutePath())); 12725 } 12726 else 12727 { 12728 return csr; 12729 } 12730 } 12731 else if (csr == null) 12732 { 12733 try 12734 { 12735 csr = new PKCS10CertificateSigningRequest(csrElement.encode()); 12736 } 12737 catch (final Exception e) 12738 { 12739 Debug.debugException(e); 12740 throw new LDAPException(ResultCode.PARAM_ERROR, 12741 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DER_NOT_VALID_CSR.get( 12742 f.getAbsolutePath(), e.getMessage()), 12743 e); 12744 } 12745 } 12746 else 12747 { 12748 throw new LDAPException(ResultCode.PARAM_ERROR, 12749 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_CSRS.get( 12750 f.getAbsolutePath())); 12751 } 12752 } 12753 } 12754 else 12755 { 12756 try (BufferedReader reader = 12757 new BufferedReader(new InputStreamReader(inputStream))) 12758 { 12759 boolean inCSR = false; 12760 final StringBuilder buffer = new StringBuilder(); 12761 while (true) 12762 { 12763 String line = reader.readLine(); 12764 if (line == null) 12765 { 12766 if (inCSR) 12767 { 12768 throw new LDAPException(ResultCode.PARAM_ERROR, 12769 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EOF_WITHOUT_END.get( 12770 f.getAbsolutePath())); 12771 } 12772 12773 if (csr == null) 12774 { 12775 throw new LDAPException(ResultCode.PARAM_ERROR, 12776 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 12777 f.getAbsolutePath())); 12778 } 12779 else 12780 { 12781 return csr; 12782 } 12783 } 12784 12785 line = line.trim(); 12786 if (line.isEmpty() || line.startsWith("#")) 12787 { 12788 continue; 12789 } 12790 12791 if (line.equals("-----BEGIN CERTIFICATE REQUEST-----") || 12792 line.equals("-----BEGIN NEW CERTIFICATE REQUEST-----")) 12793 { 12794 if (inCSR) 12795 { 12796 throw new LDAPException(ResultCode.PARAM_ERROR, 12797 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_BEGIN.get( 12798 f.getAbsolutePath())); 12799 } 12800 else if (csr != null) 12801 { 12802 throw new LDAPException(ResultCode.PARAM_ERROR, 12803 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_CSRS.get( 12804 f.getAbsolutePath())); 12805 } 12806 else 12807 { 12808 inCSR = true; 12809 } 12810 } 12811 else if (line.equals("-----END CERTIFICATE REQUEST-----") || 12812 line.equals("-----END NEW CERTIFICATE REQUEST-----")) 12813 { 12814 if (! inCSR) 12815 { 12816 throw new LDAPException(ResultCode.PARAM_ERROR, 12817 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_END_WITHOUT_BEGIN.get( 12818 f.getAbsolutePath())); 12819 } 12820 12821 inCSR = false; 12822 final byte[] csrBytes; 12823 try 12824 { 12825 csrBytes = Base64.decode(buffer.toString()); 12826 } 12827 catch (final Exception e) 12828 { 12829 Debug.debugException(e); 12830 throw new LDAPException(ResultCode.PARAM_ERROR, 12831 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_PEM_CSR_NOT_BASE64.get( 12832 f.getAbsolutePath(), 12833 StaticUtils.getExceptionMessage(e)), 12834 e); 12835 } 12836 12837 try 12838 { 12839 csr = new PKCS10CertificateSigningRequest(csrBytes); 12840 } 12841 catch (final CertException e) 12842 { 12843 Debug.debugException(e); 12844 throw new LDAPException(ResultCode.PARAM_ERROR, 12845 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_PEM_CSR_NOT_CSR.get( 12846 f.getAbsolutePath(), e.getMessage()), 12847 e); 12848 } 12849 12850 buffer.setLength(0); 12851 } 12852 else if (inCSR) 12853 { 12854 buffer.append(line); 12855 } 12856 else 12857 { 12858 throw new LDAPException(ResultCode.PARAM_ERROR, 12859 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DATA_WITHOUT_BEGIN.get( 12860 f.getAbsolutePath())); 12861 } 12862 } 12863 } 12864 } 12865 } 12866 catch (final LDAPException le) 12867 { 12868 Debug.debugException(le); 12869 throw le; 12870 } 12871 catch (final Exception e) 12872 { 12873 Debug.debugException(e); 12874 throw new LDAPException(ResultCode.LOCAL_ERROR, 12875 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_READ_ERROR.get( 12876 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 12877 e); 12878 } 12879 } 12880 12881 12882 12883 /** 12884 * Retrieves a colon-delimited hexadecimal representation of the contents of 12885 * the provided byte array. 12886 * 12887 * @param bytes The byte array for which to get the hexadecimal 12888 * representation. It must not be {@code null}. 12889 * 12890 * @return A colon-delimited hexadecimal representation of the contents of 12891 * the provided byte array. 12892 */ 12893 @NotNull() 12894 private static String toColonDelimitedHex(@NotNull final byte... bytes) 12895 { 12896 final StringBuilder buffer = new StringBuilder(bytes.length * 3); 12897 StaticUtils.toHex(bytes, ":", buffer); 12898 return buffer.toString(); 12899 } 12900 12901 12902 12903 /** 12904 * Retrieves a formatted representation of the provided date in a 12905 * human-readable format that includes an offset from the current time. 12906 * 12907 * @param d The date to format. It must not be {@code null}. 12908 * 12909 * @return A formatted representation of the provided date. 12910 */ 12911 @NotNull() 12912 private static String formatDateAndTime(@NotNull final Date d) 12913 { 12914 // Example: Sunday, January 1, 2017 12915 final String dateFormatString = "EEEE, MMMM d, yyyy"; 12916 final String formattedDate = 12917 new SimpleDateFormat(dateFormatString).format(d); 12918 12919 // Example: 12:34:56 AM CDT 12920 final String timeFormatString = "hh:mm:ss aa z"; 12921 final String formattedTime = 12922 new SimpleDateFormat(timeFormatString).format(d); 12923 12924 final long providedTime = d.getTime(); 12925 final long currentTime = System.currentTimeMillis(); 12926 if (providedTime > currentTime) 12927 { 12928 final long secondsInFuture = ((providedTime - currentTime) / 1000L); 12929 final String durationInFuture = 12930 StaticUtils.secondsToHumanReadableDuration(secondsInFuture); 12931 return INFO_MANAGE_CERTS_FORMAT_DATE_AND_TIME_IN_FUTURE.get(formattedDate, 12932 formattedTime, durationInFuture); 12933 } 12934 else 12935 { 12936 final long secondsInPast = ((currentTime - providedTime) / 1000L); 12937 final String durationInPast = 12938 StaticUtils.secondsToHumanReadableDuration(secondsInPast); 12939 return INFO_MANAGE_CERTS_FORMAT_DATE_AND_TIME_IN_PAST.get(formattedDate, 12940 formattedTime, durationInPast); 12941 } 12942 } 12943 12944 12945 12946 /** 12947 * Retrieves a formatted representation of the provided date in a format 12948 * suitable for use as the validity start time value provided to the keytool 12949 * command. 12950 * 12951 * @param d The date to format. It must not be {@code null}. 12952 * 12953 * @return A formatted representation of the provided date. 12954 */ 12955 @NotNull() 12956 private static String formatValidityStartTime(@NotNull final Date d) 12957 { 12958 // Example: 2017/01/01 01:23:45 12959 final String dateFormatString = "yyyy'/'MM'/'dd HH':'mm':'ss"; 12960 return new SimpleDateFormat(dateFormatString).format(d); 12961 } 12962 12963 12964 12965 /** 12966 * Retrieves the certificate chain for the specified certificate from the 12967 * given keystore. If any issuer certificate is not in the provided keystore, 12968 * then the JVM-default trust store will be checked to see if it can be found 12969 * there. 12970 * 12971 * @param alias The alias of the certificate for which to get the 12972 * certificate chain. This must not be 12973 * {@code null}. 12974 * @param keystore The keystore from which to get the certificate 12975 * chain. This must not be {@code null}. 12976 * @param missingIssuerRef A reference that will be updated with the DN of a 12977 * missing issuer certificate, if any certificate in 12978 * the chain cannot be located. This must not be 12979 * {@code null}. 12980 * 12981 * @return The certificate chain for the specified certificate, or an empty 12982 * array if no certificate exists with the specified alias. 12983 * 12984 * @throws LDAPException If a problem is encountered while getting the 12985 * certificate chain. 12986 */ 12987 @NotNull() 12988 private static X509Certificate[] getCertificateChain( 12989 @NotNull final String alias, 12990 @NotNull final KeyStore keystore, 12991 @NotNull final AtomicReference<DN> missingIssuerRef) 12992 throws LDAPException 12993 { 12994 try 12995 { 12996 // First, see if the keystore will give us the certificate chain. This 12997 // will only happen if the alias references an entry that includes the 12998 // private key, but it will save us a lot of work. 12999 final Certificate[] chain = keystore.getCertificateChain(alias); 13000 if ((chain != null) && (chain.length > 0)) 13001 { 13002 final X509Certificate[] x509Chain = new X509Certificate[chain.length]; 13003 for (int i=0; i < chain.length; i++) 13004 { 13005 x509Chain[i] = new X509Certificate(chain[i].getEncoded()); 13006 } 13007 return x509Chain; 13008 } 13009 13010 13011 // We couldn't get the keystore to give us the chain, but see if we can 13012 // get a certificate with the specified alias. 13013 final Certificate endCert = keystore.getCertificate(alias); 13014 if (endCert == null) 13015 { 13016 // This means there isn't any certificate with the specified alias. 13017 // Return an empty chain. 13018 return new X509Certificate[0]; 13019 } 13020 13021 final ArrayList<X509Certificate> chainList = new ArrayList<>(5); 13022 X509Certificate certificate = new X509Certificate(endCert.getEncoded()); 13023 chainList.add(certificate); 13024 13025 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 13026 new AtomicReference<>(); 13027 while (true) 13028 { 13029 final X509Certificate issuerCertificate = 13030 getIssuerCertificate(certificate, keystore, 13031 jvmDefaultTrustStoreRef, missingIssuerRef); 13032 if (issuerCertificate == null) 13033 { 13034 break; 13035 } 13036 13037 chainList.add(issuerCertificate); 13038 certificate = issuerCertificate; 13039 } 13040 13041 final X509Certificate[] x509Chain = new X509Certificate[chainList.size()]; 13042 return chainList.toArray(x509Chain); 13043 } 13044 catch (final Exception e) 13045 { 13046 Debug.debugException(e); 13047 throw new LDAPException(ResultCode.LOCAL_ERROR, 13048 ERR_MANAGE_CERTS_GET_CHAIN_ERROR.get(alias, 13049 StaticUtils.getExceptionMessage(e)), 13050 e); 13051 } 13052 } 13053 13054 13055 13056 /** 13057 * Attempts to retrieve the issuer certificate for the provided certificate 13058 * from the given keystore or the JVM-default trust store. 13059 * 13060 * @param certificate The certificate for which to retrieve the 13061 * issuer certificate. 13062 * @param keystore The keystore in which to look for the 13063 * issuer certificate. 13064 * @param jvmDefaultTrustStoreRef A reference that will be used to hold the 13065 * JVM-default trust store if it is obtained 13066 * in the process of retrieving the issuer 13067 * certificate. 13068 * @param missingIssuerRef A reference that will be updated with the 13069 * DN of a missing issuer certificate, if any 13070 * certificate in the chain cannot be 13071 * located. This must not be {@code null}. 13072 * 13073 * @return The issuer certificate for the provided certificate, or 13074 * {@code null} if the issuer certificate could not be retrieved. 13075 * 13076 * @throws Exception If a problem is encountered while trying to retrieve 13077 * the issuer certificate. 13078 */ 13079 @Nullable() 13080 private static X509Certificate getIssuerCertificate( 13081 @NotNull final X509Certificate certificate, 13082 @NotNull final KeyStore keystore, 13083 @NotNull final AtomicReference<KeyStore> jvmDefaultTrustStoreRef, 13084 @NotNull final AtomicReference<DN> missingIssuerRef) 13085 throws Exception 13086 { 13087 final DN subjectDN = certificate.getSubjectDN(); 13088 final DN issuerDN = certificate.getIssuerDN(); 13089 if (subjectDN.equals(issuerDN)) 13090 { 13091 // This means that the certificate is self-signed, so there is no issuer. 13092 return null; 13093 } 13094 13095 13096 // See if we can find the issuer certificate in the provided keystore. 13097 X509Certificate issuerCertificate = getIssuerCertificate(certificate, 13098 keystore); 13099 if (issuerCertificate != null) 13100 { 13101 return issuerCertificate; 13102 } 13103 13104 13105 // See if we can get the JVM-default trust store. 13106 KeyStore jvmDefaultTrustStore = jvmDefaultTrustStoreRef.get(); 13107 if (jvmDefaultTrustStore == null) 13108 { 13109 if (JVM_DEFAULT_CACERTS_FILE == null) 13110 { 13111 missingIssuerRef.set(issuerDN); 13112 return null; 13113 } 13114 13115 final String[] keystoreTypes = 13116 { 13117 CryptoHelper.KEY_STORE_TYPE_JKS, 13118 CryptoHelper.KEY_STORE_TYPE_PKCS_12, 13119 BouncyCastleFIPSHelper.FIPS_KEY_STORE_TYPE 13120 }; 13121 13122 for (final String keystoreType : keystoreTypes) 13123 { 13124 try 13125 { 13126 final KeyStore ks = 13127 CryptoHelper.getKeyStore(keystoreType, null, true); 13128 try (FileInputStream inputStream = 13129 new FileInputStream(JVM_DEFAULT_CACERTS_FILE)) 13130 { 13131 ks.load(inputStream, null); 13132 jvmDefaultTrustStore = ks; 13133 jvmDefaultTrustStoreRef.set(jvmDefaultTrustStore); 13134 break; 13135 } 13136 } 13137 catch (final Exception e) 13138 { 13139 Debug.debugException(e); 13140 } 13141 } 13142 } 13143 13144 if (jvmDefaultTrustStore != null) 13145 { 13146 issuerCertificate = getIssuerCertificate(certificate, 13147 jvmDefaultTrustStore); 13148 } 13149 13150 if (issuerCertificate == null) 13151 { 13152 missingIssuerRef.set(issuerDN); 13153 } 13154 13155 return issuerCertificate; 13156 } 13157 13158 13159 13160 /** 13161 * Attempts to retrieve the issuer certificate for the provided certificate 13162 * from the given keystore. 13163 * 13164 * @param certificate The certificate for which to retrieve the issuer 13165 * certificate. 13166 * @param keystore The keystore in which to look for the issuer 13167 * certificate. 13168 * 13169 * @return The issuer certificate for the provided certificate, or 13170 * {@code null} if the issuer certificate could not be retrieved. 13171 * 13172 * @throws Exception If a problem is encountered while trying to retrieve 13173 * the issuer certificate. 13174 */ 13175 @Nullable() 13176 private static X509Certificate getIssuerCertificate( 13177 @NotNull final X509Certificate certificate, 13178 @NotNull final KeyStore keystore) 13179 throws Exception 13180 { 13181 final Enumeration<String> aliases = keystore.aliases(); 13182 while (aliases.hasMoreElements()) 13183 { 13184 final String alias = aliases.nextElement(); 13185 13186 Certificate[] certs = null; 13187 if (hasCertificateAlias(keystore, alias)) 13188 { 13189 final Certificate c = keystore.getCertificate(alias); 13190 if (c == null) 13191 { 13192 continue; 13193 } 13194 13195 certs = new Certificate[] { c }; 13196 } 13197 else if (hasKeyAlias(keystore, alias)) 13198 { 13199 certs = keystore.getCertificateChain(alias); 13200 } 13201 13202 if (certs != null) 13203 { 13204 for (final Certificate c : certs) 13205 { 13206 final X509Certificate xc = new X509Certificate(c.getEncoded()); 13207 if (xc.isIssuerFor(certificate)) 13208 { 13209 return xc; 13210 } 13211 } 13212 } 13213 } 13214 13215 return null; 13216 } 13217 13218 13219 13220 /** 13221 * Retrieves the authority key identifier value for the provided certificate, 13222 * if present. 13223 * 13224 * @param c The certificate for which to retrieve the authority key 13225 * identifier. 13226 * 13227 * @return The authority key identifier value for the provided certificate, 13228 * or {@code null} if the certificate does not have an authority 13229 * key identifier. 13230 */ 13231 @Nullable() 13232 private static byte[] getAuthorityKeyIdentifier( 13233 @NotNull final X509Certificate c) 13234 { 13235 for (final X509CertificateExtension extension : c.getExtensions()) 13236 { 13237 if (extension instanceof AuthorityKeyIdentifierExtension) 13238 { 13239 final AuthorityKeyIdentifierExtension e = 13240 (AuthorityKeyIdentifierExtension) extension; 13241 if (e.getKeyIdentifier() != null) 13242 { 13243 return e.getKeyIdentifier().getValue(); 13244 } 13245 } 13246 } 13247 13248 return null; 13249 } 13250 13251 13252 13253 /** 13254 * Writes the provided keystore to the specified file. If the keystore file 13255 * already exists, a new temporary file will be created, the old file renamed 13256 * out of the way, the new file renamed into place, and the old file deleted. 13257 * If the keystore file does not exist, then it will simply be created in the 13258 * correct place. 13259 * 13260 * @param keystore The keystore to be written. 13261 * @param keystorePath The path to the keystore file to be written. 13262 * @param keystorePassword The password to use for the keystore. 13263 * 13264 * @throws LDAPException If a problem is encountered while writing the 13265 * keystore. 13266 */ 13267 static void writeKeystore(@NotNull final KeyStore keystore, 13268 @NotNull final File keystorePath, 13269 @Nullable final char[] keystorePassword) 13270 throws LDAPException 13271 { 13272 // If the key store type is PKCS #11, then we don't need to worry about a 13273 // key store file. 13274 if (keystore.getType().equals(CryptoHelper.KEY_STORE_TYPE_PKCS_11)) 13275 { 13276 try 13277 { 13278 keystore.store(null); 13279 return; 13280 } 13281 catch (final Exception e) 13282 { 13283 Debug.debugException(e); 13284 throw new LDAPException(ResultCode.LOCAL_ERROR, 13285 ERR_MANAGE_CERTS_PKCS11_WRITE_ERROR.get( 13286 StaticUtils.getExceptionMessage(e)), 13287 e); 13288 } 13289 } 13290 13291 13292 File copyOfExistingKeystore = null; 13293 final String timestamp = 13294 StaticUtils.encodeGeneralizedTime(System.currentTimeMillis()); 13295 if (keystorePath.exists()) 13296 { 13297 copyOfExistingKeystore = new File(keystorePath.getAbsolutePath() + 13298 ".backup-" + timestamp); 13299 try 13300 { 13301 Files.copy(keystorePath.toPath(), copyOfExistingKeystore.toPath()); 13302 } 13303 catch (final Exception e) 13304 { 13305 Debug.debugException(e); 13306 throw new LDAPException(ResultCode.LOCAL_ERROR, 13307 ERR_MANAGE_CERTS_WRITE_KS_ERROR_COPYING_EXISTING_KS.get( 13308 keystorePath.getAbsolutePath(), 13309 copyOfExistingKeystore.getAbsolutePath(), 13310 StaticUtils.getExceptionMessage(e)), 13311 e); 13312 } 13313 } 13314 13315 try (FileOutputStream outputStream = new FileOutputStream(keystorePath)) 13316 { 13317 keystore.store(outputStream, keystorePassword); 13318 } 13319 catch (final Exception e) 13320 { 13321 Debug.debugException(e); 13322 if (copyOfExistingKeystore == null) 13323 { 13324 throw new LDAPException(ResultCode.LOCAL_ERROR, 13325 ERR_MANAGE_CERTS_WRITE_KS_ERROR_WRITING_NEW_KS.get( 13326 keystorePath.getAbsolutePath(), 13327 StaticUtils.getExceptionMessage(e)), 13328 e); 13329 } 13330 else 13331 { 13332 throw new LDAPException(ResultCode.LOCAL_ERROR, 13333 ERR_MANAGE_CERTS_WRITE_KS_ERROR_OVERWRITING_KS.get( 13334 keystorePath.getAbsolutePath(), 13335 StaticUtils.getExceptionMessage(e), 13336 copyOfExistingKeystore.getAbsolutePath()), 13337 e); 13338 } 13339 } 13340 13341 if (copyOfExistingKeystore != null) 13342 { 13343 try 13344 { 13345 Files.delete(copyOfExistingKeystore.toPath()); 13346 } 13347 catch (final Exception e) 13348 { 13349 Debug.debugException(e); 13350 throw new LDAPException(ResultCode.LOCAL_ERROR, 13351 ERR_MANAGE_CERTS_WRITE_KS_ERROR_DELETING_KS_BACKUP.get( 13352 copyOfExistingKeystore.getAbsolutePath(), 13353 keystorePath.getAbsolutePath(), 13354 StaticUtils.getExceptionMessage(e)), 13355 e); 13356 } 13357 } 13358 } 13359 13360 13361 13362 /** 13363 * Indicates whether the provided keystore has a certificate entry with the 13364 * specified alias. 13365 * 13366 * @param keystore The keystore to examine. 13367 * @param alias The alias for which to make the determination. 13368 * 13369 * @return {@code true} if the keystore has a certificate entry with the 13370 * specified alias, or {@code false} if the alias doesn't exist or 13371 * is associated with some other type of entry (like a key). 13372 */ 13373 private static boolean hasCertificateAlias(@NotNull final KeyStore keystore, 13374 @NotNull final String alias) 13375 { 13376 try 13377 { 13378 return keystore.isCertificateEntry(alias); 13379 } 13380 catch (final Exception e) 13381 { 13382 // This should never happen. If it does, then we'll assume the alias 13383 // doesn't exist or isn't associated with a certificate. 13384 Debug.debugException(e); 13385 return false; 13386 } 13387 } 13388 13389 13390 13391 /** 13392 * Indicates whether the provided keystore has a key entry with the specified 13393 * alias. 13394 * 13395 * @param keystore The keystore to examine. 13396 * @param alias The alias for which to make the determination. 13397 * 13398 * @return {@code true} if the keystore has a key entry with the specified 13399 * alias, or {@code false} if the alias doesn't exist or is 13400 * associated with some other type of entry (like a certificate). 13401 */ 13402 private static boolean hasKeyAlias(@NotNull final KeyStore keystore, 13403 @NotNull final String alias) 13404 { 13405 try 13406 { 13407 return keystore.isKeyEntry(alias); 13408 } 13409 catch (final Exception e) 13410 { 13411 // This should never happen. If it does, then we'll assume the alias 13412 // doesn't exist or isn't associated with a key. 13413 Debug.debugException(e); 13414 return false; 13415 } 13416 } 13417 13418 13419 13420 /** 13421 * Adds arguments for each of the provided extensions to the given list. 13422 * 13423 * @param keytoolArguments The list to which the extension arguments should 13424 * be added. 13425 * @param basicConstraints The basic constraints extension to include. It 13426 * may be {@code null} if this extension should not 13427 * be included. 13428 * @param keyUsage The key usage extension to include. It may be 13429 * {@code null} if this extension should not be 13430 * included. 13431 * @param extendedKeyUsage The extended key usage extension to include. It 13432 * may be {@code null} if this extension should not 13433 * be included. 13434 * @param sanValues The list of subject alternative name values to 13435 * include. It must not be {@code null} but may be 13436 * empty. 13437 * @param ianValues The list of issuer alternative name values to 13438 * include. It must not be {@code null} but may be 13439 * empty. 13440 * @param genericExtensions The list of generic extensions to include. It 13441 * must not be {@code null} but may be empty. 13442 */ 13443 private static void addExtensionArguments( 13444 @NotNull final List<String> keytoolArguments, 13445 @Nullable final BasicConstraintsExtension basicConstraints, 13446 @Nullable final KeyUsageExtension keyUsage, 13447 @Nullable final ExtendedKeyUsageExtension extendedKeyUsage, 13448 @NotNull final Set<String> sanValues, 13449 @NotNull final Set<String> ianValues, 13450 @NotNull final List<X509CertificateExtension> genericExtensions) 13451 { 13452 if (basicConstraints != null) 13453 { 13454 final StringBuilder basicConstraintsValue = new StringBuilder(); 13455 basicConstraintsValue.append("ca:"); 13456 basicConstraintsValue.append(basicConstraints.isCA()); 13457 13458 if (basicConstraints.getPathLengthConstraint() != null) 13459 { 13460 basicConstraintsValue.append(",pathlen:"); 13461 basicConstraintsValue.append( 13462 basicConstraints.getPathLengthConstraint()); 13463 } 13464 13465 keytoolArguments.add("-ext"); 13466 keytoolArguments.add("BasicConstraints=" + basicConstraintsValue); 13467 } 13468 13469 if (keyUsage != null) 13470 { 13471 final StringBuilder keyUsageValue = new StringBuilder(); 13472 if (keyUsage.isDigitalSignatureBitSet()) 13473 { 13474 commaAppend(keyUsageValue, "digitalSignature"); 13475 } 13476 13477 if (keyUsage.isNonRepudiationBitSet()) 13478 { 13479 commaAppend(keyUsageValue, "nonRepudiation"); 13480 } 13481 13482 if (keyUsage.isKeyEnciphermentBitSet()) 13483 { 13484 commaAppend(keyUsageValue, "keyEncipherment"); 13485 } 13486 13487 if (keyUsage.isDataEnciphermentBitSet()) 13488 { 13489 commaAppend(keyUsageValue, "dataEncipherment"); 13490 } 13491 13492 if (keyUsage.isKeyAgreementBitSet()) 13493 { 13494 commaAppend(keyUsageValue, "keyAgreement"); 13495 } 13496 13497 if (keyUsage.isKeyCertSignBitSet()) 13498 { 13499 commaAppend(keyUsageValue, "keyCertSign"); 13500 } 13501 13502 if (keyUsage.isCRLSignBitSet()) 13503 { 13504 commaAppend(keyUsageValue, "cRLSign"); 13505 } 13506 13507 if (keyUsage.isEncipherOnlyBitSet()) 13508 { 13509 commaAppend(keyUsageValue, "encipherOnly"); 13510 } 13511 13512 if (keyUsage.isEncipherOnlyBitSet()) 13513 { 13514 commaAppend(keyUsageValue, "decipherOnly"); 13515 } 13516 13517 keytoolArguments.add("-ext"); 13518 keytoolArguments.add("KeyUsage=" + keyUsageValue); 13519 } 13520 13521 if (extendedKeyUsage != null) 13522 { 13523 final StringBuilder extendedKeyUsageValue = new StringBuilder(); 13524 for (final OID oid : extendedKeyUsage.getKeyPurposeIDs()) 13525 { 13526 final ExtendedKeyUsageID id = ExtendedKeyUsageID.forOID(oid); 13527 if (id == null) 13528 { 13529 commaAppend(extendedKeyUsageValue, oid.toString()); 13530 } 13531 else 13532 { 13533 switch (id) 13534 { 13535 case TLS_SERVER_AUTHENTICATION: 13536 commaAppend(extendedKeyUsageValue, "serverAuth"); 13537 break; 13538 case TLS_CLIENT_AUTHENTICATION: 13539 commaAppend(extendedKeyUsageValue, "clientAuth"); 13540 break; 13541 case CODE_SIGNING: 13542 commaAppend(extendedKeyUsageValue, "codeSigning"); 13543 break; 13544 case EMAIL_PROTECTION: 13545 commaAppend(extendedKeyUsageValue, "emailProtection"); 13546 break; 13547 case TIME_STAMPING: 13548 commaAppend(extendedKeyUsageValue, "timeStamping"); 13549 break; 13550 case OCSP_SIGNING: 13551 commaAppend(extendedKeyUsageValue, "OCSPSigning"); 13552 break; 13553 default: 13554 // This should never happen. 13555 commaAppend(extendedKeyUsageValue, id.getOID().toString()); 13556 break; 13557 } 13558 } 13559 } 13560 13561 keytoolArguments.add("-ext"); 13562 keytoolArguments.add("ExtendedKeyUsage=" + extendedKeyUsageValue); 13563 } 13564 13565 if (! sanValues.isEmpty()) 13566 { 13567 final StringBuilder subjectAltNameValue = new StringBuilder(); 13568 for (final String sanValue : sanValues) 13569 { 13570 commaAppend(subjectAltNameValue, sanValue); 13571 } 13572 13573 keytoolArguments.add("-ext"); 13574 keytoolArguments.add("SAN=" + subjectAltNameValue); 13575 } 13576 13577 if (! ianValues.isEmpty()) 13578 { 13579 final StringBuilder issuerAltNameValue = new StringBuilder(); 13580 for (final String ianValue : ianValues) 13581 { 13582 commaAppend(issuerAltNameValue, ianValue); 13583 } 13584 13585 keytoolArguments.add("-ext"); 13586 keytoolArguments.add("IAN=" + issuerAltNameValue); 13587 } 13588 13589 for (final X509CertificateExtension e : genericExtensions) 13590 { 13591 keytoolArguments.add("-ext"); 13592 if (e.isCritical()) 13593 { 13594 keytoolArguments.add(e.getOID().toString() + ":critical=" + 13595 toColonDelimitedHex(e.getValue())); 13596 } 13597 else 13598 { 13599 keytoolArguments.add(e.getOID().toString() + '=' + 13600 toColonDelimitedHex(e.getValue())); 13601 } 13602 } 13603 } 13604 13605 13606 13607 /** 13608 * Appends the provided value to the given buffer. If the buffer is not 13609 * empty, the new value will be preceded by a comma. There will not be any 13610 * spaces on either side of the comma. 13611 * 13612 * @param buffer The buffer to which the value should be appended. 13613 * @param value The value to append to the buffer. 13614 */ 13615 private static void commaAppend(@NotNull final StringBuilder buffer, 13616 @NotNull final String value) 13617 { 13618 if (buffer.length() > 0) 13619 { 13620 buffer.append(','); 13621 } 13622 13623 buffer.append(value); 13624 } 13625 13626 13627 13628 /** 13629 * Retrieves a set of information that may be used to generate example usage 13630 * information. Each element in the returned map should consist of a map 13631 * between an example set of arguments and a string that describes the 13632 * behavior of the tool when invoked with that set of arguments. 13633 * 13634 * @return A set of information that may be used to generate example usage 13635 * information. It may be {@code null} or empty if no example usage 13636 * information is available. 13637 */ 13638 @Override() 13639 @NotNull() 13640 public LinkedHashMap<String[],String> getExampleUsages() 13641 { 13642 final String keystorePath = getPlatformSpecificPath("config", "keystore"); 13643 final String keystorePWPath = 13644 getPlatformSpecificPath("config", "keystore.pin"); 13645 final String privateKeyPWPath = 13646 getPlatformSpecificPath("config", "server-cert-private-key.pin"); 13647 final String exportCertOutputFile = 13648 getPlatformSpecificPath("server-cert.crt"); 13649 final String exportKeyOutputFile = 13650 getPlatformSpecificPath("server-cert.private-key"); 13651 final String genCSROutputFile = getPlatformSpecificPath("server-cert.csr"); 13652 final String truststorePath = 13653 getPlatformSpecificPath("config", "truststore"); 13654 final String truststorePWPath = 13655 getPlatformSpecificPath("config", "truststore.pin"); 13656 13657 final LinkedHashMap<String[],String> examples = 13658 new LinkedHashMap<>(StaticUtils.computeMapCapacity(20)); 13659 13660 examples.put( 13661 new String[] 13662 { 13663 "list-certificates", 13664 "--keystore", keystorePath, 13665 "--keystore-password-file", keystorePWPath, 13666 "--verbose", 13667 "--display-keytool-command" 13668 }, 13669 INFO_MANAGE_CERTS_EXAMPLE_LIST_1.get(keystorePath)); 13670 13671 examples.put( 13672 new String[] 13673 { 13674 "export-certificate", 13675 "--keystore", keystorePath, 13676 "--keystore-password-file", keystorePWPath, 13677 "--alias", "server-cert", 13678 "--output-file", exportCertOutputFile, 13679 "--output-format", "PEM", 13680 "--verbose", 13681 "--display-keytool-command" 13682 }, 13683 INFO_MANAGE_CERTS_EXAMPLE_EXPORT_CERT_1.get(keystorePath, 13684 exportCertOutputFile)); 13685 13686 examples.put( 13687 new String[] 13688 { 13689 "export-private-key", 13690 "--keystore", keystorePath, 13691 "--keystore-password-file", keystorePWPath, 13692 "--private-key-password-file", privateKeyPWPath, 13693 "--alias", "server-cert", 13694 "--output-file", exportKeyOutputFile, 13695 "--output-format", "PEM", 13696 "--verbose", 13697 "--display-keytool-command" 13698 }, 13699 INFO_MANAGE_CERTS_EXAMPLE_EXPORT_KEY_1.get(keystorePath, 13700 exportKeyOutputFile)); 13701 13702 examples.put( 13703 new String[] 13704 { 13705 "import-certificate", 13706 "--keystore", keystorePath, 13707 "--keystore-type", "JKS", 13708 "--keystore-password-file", keystorePWPath, 13709 "--alias", "server-cert", 13710 "--certificate-file", exportCertOutputFile, 13711 "--private-key-file", exportKeyOutputFile, 13712 "--display-keytool-command" 13713 }, 13714 INFO_MANAGE_CERTS_EXAMPLE_IMPORT_1.get(exportCertOutputFile, 13715 exportKeyOutputFile, keystorePath)); 13716 13717 examples.put( 13718 new String[] 13719 { 13720 "delete-certificate", 13721 "--keystore", keystorePath, 13722 "--keystore-password-file", keystorePWPath, 13723 "--alias", "server-cert" 13724 }, 13725 INFO_MANAGE_CERTS_EXAMPLE_DELETE_1.get(keystorePath)); 13726 13727 examples.put( 13728 new String[] 13729 { 13730 "generate-self-signed-certificate", 13731 "--keystore", keystorePath, 13732 "--keystore-type", "PKCS12", 13733 "--keystore-password-file", keystorePWPath, 13734 "--alias", "ca-cert", 13735 "--subject-dn", "CN=Example Authority,O=Example Corporation,C=US", 13736 "--days-valid", "7300", 13737 "--validity-start-time", "20170101000000", 13738 "--key-algorithm", "RSA", 13739 "--key-size-bits", "4096", 13740 "--signature-algorithm", "SHA256withRSA", 13741 "--basic-constraints-is-ca", "true", 13742 "--key-usage", "key-cert-sign", 13743 "--key-usage", "crl-sign", 13744 "--display-keytool-command" 13745 }, 13746 INFO_MANAGE_CERTS_EXAMPLE_GEN_CERT_1.get(keystorePath)); 13747 13748 examples.put( 13749 new String[] 13750 { 13751 "generate-certificate-signing-request", 13752 "--keystore", keystorePath, 13753 "--keystore-type", "PKCS12", 13754 "--keystore-password-file", keystorePWPath, 13755 "--output-file", genCSROutputFile, 13756 "--alias", "server-cert", 13757 "--subject-dn", "CN=ldap.example.com,O=Example Corporation,C=US", 13758 "--key-algorithm", "EC", 13759 "--key-size-bits", "256", 13760 "--signature-algorithm", "SHA256withECDSA", 13761 "--subject-alternative-name-dns", "ldap1.example.com", 13762 "--subject-alternative-name-dns", "ldap2.example.com", 13763 "--extended-key-usage", "server-auth", 13764 "--extended-key-usage", "client-auth", 13765 "--display-keytool-command" 13766 }, 13767 INFO_MANAGE_CERTS_EXAMPLE_GEN_CSR_1.get(keystorePath, 13768 genCSROutputFile)); 13769 13770 examples.put( 13771 new String[] 13772 { 13773 "generate-certificate-signing-request", 13774 "--keystore", keystorePath, 13775 "--keystore-password-file", keystorePWPath, 13776 "--alias", "server-cert", 13777 "--use-existing-key-pair", 13778 "--inherit-extensions", 13779 "--display-keytool-command" 13780 }, 13781 INFO_MANAGE_CERTS_EXAMPLE_GEN_CSR_2.get(keystorePath)); 13782 13783 examples.put( 13784 new String[] 13785 { 13786 "sign-certificate-signing-request", 13787 "--keystore", keystorePath, 13788 "--keystore-password-file", keystorePWPath, 13789 "--request-input-file", genCSROutputFile, 13790 "--certificate-output-file", exportCertOutputFile, 13791 "--alias", "ca-cert", 13792 "--days-valid", "730", 13793 "--include-requested-extensions", 13794 "--display-keytool-command" 13795 }, 13796 INFO_MANAGE_CERTS_EXAMPLE_SIGN_CERT_1.get(keystorePath, 13797 genCSROutputFile, exportCertOutputFile)); 13798 13799 examples.put( 13800 new String[] 13801 { 13802 "change-certificate-alias", 13803 "--keystore", keystorePath, 13804 "--keystore-password-file", keystorePWPath, 13805 "--current-alias", "server-cert", 13806 "--new-alias", "server-certificate", 13807 "--display-keytool-command" 13808 }, 13809 INFO_MANAGE_CERTS_EXAMPLE_CHANGE_ALIAS_1.get(keystorePath, 13810 genCSROutputFile, exportCertOutputFile)); 13811 13812 examples.put( 13813 new String[] 13814 { 13815 "change-keystore-password", 13816 "--keystore", getPlatformSpecificPath("config", "keystore"), 13817 "--current-keystore-password-file", 13818 getPlatformSpecificPath("config", "current.pin"), 13819 "--new-keystore-password-file", 13820 getPlatformSpecificPath("config", "new.pin"), 13821 "--display-keytool-command" 13822 }, 13823 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_EXAMPLE_1.get( 13824 getPlatformSpecificPath("config", "keystore"), 13825 getPlatformSpecificPath("config", "current.pin"), 13826 getPlatformSpecificPath("config", "new.pin"))); 13827 13828 examples.put( 13829 new String[] 13830 { 13831 "retrieve-server-certificate", 13832 "--hostname", "ds.example.com", 13833 "--port", "636" 13834 }, 13835 INFO_MANAGE_CERTS_SC_RETRIEVE_CERT_EXAMPLE_1.get( 13836 getPlatformSpecificPath("config", "truststore"))); 13837 13838 examples.put( 13839 new String[] 13840 { 13841 "copy-keystore", 13842 "--source-keystore", 13843 getPlatformSpecificPath("config", "keystore.jks"), 13844 "--source-keystore-password-file", 13845 getPlatformSpecificPath("config", "keystore.pin"), 13846 "--source-keystore-type", "JKS", 13847 "--destination-keystore", 13848 getPlatformSpecificPath("config", "keystore.p12"), 13849 "--destination-keystore-password-file", 13850 getPlatformSpecificPath("config", "keystore.pin"), 13851 "--destination-keystore-type", "PKCS12" 13852 }, 13853 INFO_MANAGE_CERTS_SC_COPY_KS_EXAMPLE_1.get("keystore.jks", 13854 "keystore.p12")); 13855 13856 examples.put( 13857 new String[] 13858 { 13859 "trust-server-certificate", 13860 "--hostname", "ldap.example.com", 13861 "--port", "636", 13862 "--keystore", truststorePath, 13863 "--keystore-password-file", truststorePWPath, 13864 "--alias", "ldap.example.com:636" 13865 }, 13866 INFO_MANAGE_CERTS_EXAMPLE_TRUST_SERVER_1.get(truststorePath)); 13867 13868 examples.put( 13869 new String[] 13870 { 13871 "check-certificate-usability", 13872 "--keystore", keystorePath, 13873 "--keystore-password-file", keystorePWPath, 13874 "--alias", "server-cert" 13875 }, 13876 INFO_MANAGE_CERTS_EXAMPLE_CHECK_USABILITY_1.get(keystorePath)); 13877 13878 examples.put( 13879 new String[] 13880 { 13881 "display-certificate-file", 13882 "--certificate-file", exportCertOutputFile, 13883 "--verbose", 13884 "--display-keytool-command" 13885 }, 13886 INFO_MANAGE_CERTS_EXAMPLE_DISPLAY_CERT_1.get(keystorePath)); 13887 13888 examples.put( 13889 new String[] 13890 { 13891 "display-certificate-signing-request-file", 13892 "--certificate-signing-request-file", genCSROutputFile, 13893 "--display-keytool-command" 13894 }, 13895 INFO_MANAGE_CERTS_EXAMPLE_DISPLAY_CSR_1.get(keystorePath)); 13896 13897 examples.put( 13898 new String[] 13899 { 13900 "--help-subcommands" 13901 }, 13902 INFO_MANAGE_CERTS_EXAMPLE_HELP_SUBCOMMANDS_1.get(keystorePath)); 13903 13904 return examples; 13905 } 13906}