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