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