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