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