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