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