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