001/* 002 * Copyright 2017-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2017-2018 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.util.ssl.cert; 022 023 024 025import java.io.BufferedInputStream; 026import java.io.BufferedReader; 027import java.io.ByteArrayInputStream; 028import java.io.File; 029import java.io.FileInputStream; 030import java.io.FileOutputStream; 031import java.io.FileReader; 032import java.io.InputStream; 033import java.io.InputStreamReader; 034import java.io.IOException; 035import java.io.OutputStream; 036import java.io.PrintStream; 037import java.nio.file.Files; 038import java.net.InetAddress; 039import java.security.Key; 040import java.security.KeyPair; 041import java.security.KeyStore; 042import java.security.PrivateKey; 043import java.security.PublicKey; 044import java.security.UnrecoverableKeyException; 045import java.security.cert.Certificate; 046import java.text.SimpleDateFormat; 047import java.util.ArrayList; 048import java.util.Arrays; 049import java.util.Collections; 050import java.util.Date; 051import java.util.Enumeration; 052import java.util.Iterator; 053import java.util.LinkedHashMap; 054import java.util.LinkedHashSet; 055import java.util.List; 056import java.util.Map; 057import java.util.Set; 058import java.util.concurrent.LinkedBlockingQueue; 059import java.util.concurrent.TimeUnit; 060import java.util.concurrent.atomic.AtomicReference; 061 062import com.unboundid.asn1.ASN1BitString; 063import com.unboundid.asn1.ASN1Element; 064import com.unboundid.ldap.sdk.DN; 065import com.unboundid.ldap.sdk.LDAPException; 066import com.unboundid.ldap.sdk.ResultCode; 067import com.unboundid.ldap.sdk.Version; 068import com.unboundid.util.Base64; 069import com.unboundid.util.ByteStringBuffer; 070import com.unboundid.util.CommandLineTool; 071import com.unboundid.util.Debug; 072import com.unboundid.util.OID; 073import com.unboundid.util.ObjectPair; 074import com.unboundid.util.PasswordReader; 075import com.unboundid.util.StaticUtils; 076import com.unboundid.util.ThreadSafety; 077import com.unboundid.util.ThreadSafetyLevel; 078import com.unboundid.util.Validator; 079import com.unboundid.util.args.ArgumentException; 080import com.unboundid.util.args.ArgumentParser; 081import com.unboundid.util.args.BooleanArgument; 082import com.unboundid.util.args.BooleanValueArgument; 083import com.unboundid.util.args.DNArgument; 084import com.unboundid.util.args.FileArgument; 085import com.unboundid.util.args.IPAddressArgumentValueValidator; 086import com.unboundid.util.args.IntegerArgument; 087import com.unboundid.util.args.OIDArgumentValueValidator; 088import com.unboundid.util.args.StringArgument; 089import com.unboundid.util.args.TimestampArgument; 090import com.unboundid.util.args.SubCommand; 091import com.unboundid.util.ssl.JVMDefaultTrustManager; 092 093import static com.unboundid.util.ssl.cert.CertMessages.*; 094 095 096 097/** 098 * This class provides a tool that can be used to manage X.509 certificates for 099 * use in TLS communication. 100 */ 101@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 102public final class ManageCertificates 103 extends CommandLineTool 104{ 105 /** 106 * The path to the keystore with the JVM's set of default trusted issuer 107 * certificates. 108 */ 109 private static final File JVM_DEFAULT_CACERTS_FILE; 110 static 111 { 112 File caCertsFile; 113 try 114 { 115 caCertsFile = JVMDefaultTrustManager.getInstance().getCACertsFile(); 116 } 117 catch (final Exception e) 118 { 119 Debug.debugException(e); 120 caCertsFile = null; 121 } 122 123 JVM_DEFAULT_CACERTS_FILE = caCertsFile; 124 } 125 126 127 128 /** 129 * The name of a system property that can be used to specify the default 130 * keystore type for new keystores. 131 */ 132 private static final String PROPERTY_DEFAULT_KEYSTORE_TYPE = 133 ManageCertificates.class.getName() + ".defaultKeystoreType"; 134 135 136 137 /** 138 * The default keystore type that will be used for new keystores when the 139 * type is not specified. 140 */ 141 private static final String DEFAULT_KEYSTORE_TYPE; 142 static 143 { 144 final String propertyValue = 145 System.getProperty(PROPERTY_DEFAULT_KEYSTORE_TYPE); 146 if ((propertyValue != null) && 147 (propertyValue.equalsIgnoreCase("PKCS12") || 148 propertyValue.equalsIgnoreCase("PKCS#12") || 149 propertyValue.equalsIgnoreCase("PKCS #12") || 150 propertyValue.equalsIgnoreCase("PKCS 12"))) 151 { 152 DEFAULT_KEYSTORE_TYPE = "PKCS12"; 153 } 154 else 155 { 156 DEFAULT_KEYSTORE_TYPE = "JKS"; 157 } 158 } 159 160 161 162 /** 163 * The column at which to wrap long lines of output. 164 */ 165 private static final int WRAP_COLUMN = StaticUtils.TERMINAL_WIDTH_COLUMNS - 1; 166 167 168 169 // The global argument parser used by this tool. 170 private volatile ArgumentParser globalParser = null; 171 172 // The argument parser for the selected subcommand. 173 private volatile ArgumentParser subCommandParser = null; 174 175 // The input stream to use for standard input. 176 private final InputStream in; 177 178 179 180 /** 181 * Invokes this tool with the default standard output and standard error and 182 * the provided set of arguments. 183 * 184 * @param args The command-line arguments provided to this program. 185 */ 186 public static void main(final String... args) 187 { 188 final ResultCode resultCode = main(System.in, System.out, System.err, args); 189 if (resultCode != ResultCode.SUCCESS) 190 { 191 System.exit(Math.max(1, Math.min(resultCode.intValue(), 255))); 192 } 193 } 194 195 196 197 /** 198 * Invokes this tool with the provided output and error streams and set of 199 * arguments. 200 * 201 * @param in The input stream to use for standard input. It may be 202 * {@code null} if no input stream should be available. 203 * @param out The output stream to use for standard output. It may be 204 * {@code null} if standard output should be suppressed. 205 * @param err The output stream to use for standard error. It may be 206 * {@code null} if standard error should be suppressed. 207 * @param args The command-line arguments provided to this program. 208 * 209 * @return The result code obtained from tool processing. 210 */ 211 public static ResultCode main(final InputStream in, final OutputStream out, 212 final OutputStream err, final String... args) 213 { 214 final ManageCertificates manageCertificates = 215 new ManageCertificates(in, out, err); 216 return manageCertificates.runTool(args); 217 } 218 219 220 221 /** 222 * Creates a new instance of this tool with the provided output and error 223 * streams. 224 * 225 * @param in The input stream to use for standard input. It may be 226 * {@code null} if no input stream should be available. 227 * @param out The output stream to use for standard output. It may be 228 * {@code null} if standard output should be suppressed. 229 * @param err The output stream to use for standard error. It may be 230 * {@code null} if standard error should be suppressed. 231 */ 232 public ManageCertificates(final InputStream in, final OutputStream out, 233 final OutputStream err) 234 { 235 super(out, err); 236 237 if (in == null) 238 { 239 this.in = new ByteArrayInputStream(StaticUtils.NO_BYTES); 240 } 241 else 242 { 243 this.in = in; 244 } 245 } 246 247 248 249 /** 250 * Retrieves the name of this tool. It should be the name of the command used 251 * to invoke this tool. 252 * 253 * @return The name for this tool. 254 */ 255 @Override() 256 public String getToolName() 257 { 258 return "manage-certificates"; 259 } 260 261 262 263 /** 264 * Retrieves a human-readable description for this tool. 265 * 266 * @return A human-readable description for this tool. 267 */ 268 @Override() 269 public String getToolDescription() 270 { 271 return INFO_MANAGE_CERTS_TOOL_DESC.get(); 272 } 273 274 275 276 /** 277 * Retrieves a version string for this tool, if available. 278 * 279 * @return A version string for this tool, or {@code null} if none is 280 * available. 281 */ 282 @Override() 283 public String getToolVersion() 284 { 285 return Version.NUMERIC_VERSION_STRING; 286 } 287 288 289 290 /** 291 * Indicates whether this tool should provide support for an interactive mode, 292 * in which the tool offers a mode in which the arguments can be provided in 293 * a text-driven menu rather than requiring them to be given on the command 294 * line. If interactive mode is supported, it may be invoked using the 295 * "--interactive" argument. Alternately, if interactive mode is supported 296 * and {@link #defaultsToInteractiveMode()} returns {@code true}, then 297 * interactive mode may be invoked by simply launching the tool without any 298 * arguments. 299 * 300 * @return {@code true} if this tool supports interactive mode, or 301 * {@code false} if not. 302 */ 303 @Override() 304 public boolean supportsInteractiveMode() 305 { 306 return true; 307 } 308 309 310 311 /** 312 * Indicates whether this tool defaults to launching in interactive mode if 313 * the tool is invoked without any command-line arguments. This will only be 314 * used if {@link #supportsInteractiveMode()} returns {@code true}. 315 * 316 * @return {@code true} if this tool defaults to using interactive mode if 317 * launched without any command-line arguments, or {@code false} if 318 * not. 319 */ 320 @Override() 321 public boolean defaultsToInteractiveMode() 322 { 323 return true; 324 } 325 326 327 328 /** 329 * Indicates whether this tool supports the use of a properties file for 330 * specifying default values for arguments that aren't specified on the 331 * command line. 332 * 333 * @return {@code true} if this tool supports the use of a properties file 334 * for specifying default values for arguments that aren't specified 335 * on the command line, or {@code false} if not. 336 */ 337 @Override() 338 public boolean supportsPropertiesFile() 339 { 340 return true; 341 } 342 343 344 345 /** 346 * Indicates whether this tool should provide arguments for redirecting output 347 * to a file. If this method returns {@code true}, then the tool will offer 348 * an "--outputFile" argument that will specify the path to a file to which 349 * all standard output and standard error content will be written, and it will 350 * also offer a "--teeToStandardOut" argument that can only be used if the 351 * "--outputFile" argument is present and will cause all output to be written 352 * to both the specified output file and to standard output. 353 * 354 * @return {@code true} if this tool should provide arguments for redirecting 355 * output to a file, or {@code false} if not. 356 */ 357 @Override() 358 protected boolean supportsOutputFile() 359 { 360 return false; 361 } 362 363 364 365 /** 366 * Indicates whether to log messages about the launch and completion of this 367 * tool into the invocation log of Ping Identity server products that may 368 * include it. This method is not needed for tools that are not expected to 369 * be part of the Ping Identity server products suite. Further, this value 370 * may be overridden by settings in the server's 371 * tool-invocation-logging.properties file. 372 * <BR><BR> 373 * This method should generally return {@code true} for tools that may alter 374 * the server configuration, data, or other state information, and 375 * {@code false} for tools that do not make any changes. 376 * 377 * @return {@code true} if Ping Identity server products should include 378 * messages about the launch and completion of this tool in tool 379 * invocation log files by default, or {@code false} if not. 380 */ 381 @Override() 382 protected boolean logToolInvocationByDefault() 383 { 384 return true; 385 } 386 387 388 389 /** 390 * Adds the command-line arguments supported for use with this tool to the 391 * provided argument parser. The tool may need to retain references to the 392 * arguments (and/or the argument parser, if trailing arguments are allowed) 393 * to it in order to obtain their values for use in later processing. 394 * 395 * @param parser The argument parser to which the arguments are to be added. 396 * 397 * @throws ArgumentException If a problem occurs while adding any of the 398 * tool-specific arguments to the provided 399 * argument parser. 400 */ 401 @Override() 402 public void addToolArguments(final ArgumentParser parser) 403 throws ArgumentException 404 { 405 globalParser = parser; 406 407 408 // Define the "list-certificates" subcommand and all of its arguments. 409 final ArgumentParser listCertsParser = new ArgumentParser( 410 "list-certificates", INFO_MANAGE_CERTS_SC_LIST_CERTS_DESC.get()); 411 412 final FileArgument listCertsKeystore = new FileArgument(null, "keystore", 413 true, 1, null, INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_DESC.get(), 414 true, true, true, false); 415 listCertsKeystore.addLongIdentifier("keystore-path", true); 416 listCertsKeystore.addLongIdentifier("keystorePath", true); 417 listCertsKeystore.addLongIdentifier("keystore-file", true); 418 listCertsKeystore.addLongIdentifier("keystoreFile", true); 419 listCertsParser.addArgument(listCertsKeystore); 420 421 final StringArgument listCertsKeystorePassword = new StringArgument(null, 422 "keystore-password", false, 1, 423 INFO_MANAGE_CERTS_PLACEHOLDER_PASSWORD.get(), 424 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_PW_DESC.get()); 425 listCertsKeystorePassword.addLongIdentifier("keystorePassword", true); 426 listCertsKeystorePassword.addLongIdentifier("keystore-passphrase", true); 427 listCertsKeystorePassword.addLongIdentifier("keystorePassphrase", true); 428 listCertsKeystorePassword.addLongIdentifier("keystore-pin", true); 429 listCertsKeystorePassword.addLongIdentifier("keystorePIN", true); 430 listCertsKeystorePassword.addLongIdentifier("storepass", true); 431 listCertsKeystorePassword.setSensitive(true); 432 listCertsParser.addArgument(listCertsKeystorePassword); 433 434 final FileArgument listCertsKeystorePasswordFile = new FileArgument(null, 435 "keystore-password-file", false, 1, null, 436 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_KS_PW_FILE_DESC.get(), true, true, 437 true, false); 438 listCertsKeystorePasswordFile.addLongIdentifier("keystorePasswordFile", 439 true); 440 listCertsKeystorePasswordFile.addLongIdentifier("keystore-passphrase-file", 441 true); 442 listCertsKeystorePasswordFile.addLongIdentifier("keystorePassphraseFile", 443 true); 444 listCertsKeystorePasswordFile.addLongIdentifier("keystore-pin-file", 445 true); 446 listCertsKeystorePasswordFile.addLongIdentifier("keystorePINFile", true); 447 listCertsParser.addArgument(listCertsKeystorePasswordFile); 448 449 final BooleanArgument listCertsPromptForKeystorePassword = 450 new BooleanArgument(null, "prompt-for-keystore-password", 451 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_PROMPT_FOR_KS_PW_DESC.get()); 452 listCertsPromptForKeystorePassword.addLongIdentifier( 453 "promptForKeystorePassword", true); 454 listCertsPromptForKeystorePassword.addLongIdentifier( 455 "prompt-for-keystore-passphrase", true); 456 listCertsPromptForKeystorePassword.addLongIdentifier( 457 "promptForKeystorePassphrase", true); 458 listCertsPromptForKeystorePassword.addLongIdentifier( 459 "prompt-for-keystore-pin", true); 460 listCertsPromptForKeystorePassword.addLongIdentifier( 461 "promptForKeystorePIN", true); 462 listCertsParser.addArgument(listCertsPromptForKeystorePassword); 463 464 final StringArgument listCertsAlias = new StringArgument(null, "alias", 465 false, 0, INFO_MANAGE_CERTS_PLACEHOLDER_ALIAS.get(), 466 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_ALIAS_DESC.get()); 467 listCertsAlias.addLongIdentifier("nickname", true); 468 listCertsParser.addArgument(listCertsAlias); 469 470 final BooleanArgument listCertsDisplayPEM = new BooleanArgument(null, 471 "display-pem-certificate", 1, 472 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_DISPLAY_PEM_DESC.get()); 473 listCertsDisplayPEM.addLongIdentifier("displayPEMCertificate", true); 474 listCertsDisplayPEM.addLongIdentifier("display-pem", true); 475 listCertsDisplayPEM.addLongIdentifier("displayPEM", true); 476 listCertsDisplayPEM.addLongIdentifier("show-pem-certificate", true); 477 listCertsDisplayPEM.addLongIdentifier("showPEMCertificate", true); 478 listCertsDisplayPEM.addLongIdentifier("show-pem", true); 479 listCertsDisplayPEM.addLongIdentifier("showPEM", true); 480 listCertsDisplayPEM.addLongIdentifier("pem", true); 481 listCertsDisplayPEM.addLongIdentifier("rfc", true); 482 listCertsParser.addArgument(listCertsDisplayPEM); 483 484 final BooleanArgument listCertsVerbose = new BooleanArgument(null, 485 "verbose", 1, INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_VERBOSE_DESC.get()); 486 listCertsParser.addArgument(listCertsVerbose); 487 488 final BooleanArgument listCertsDisplayCommand = new BooleanArgument(null, 489 "display-keytool-command", 1, 490 INFO_MANAGE_CERTS_SC_LIST_CERTS_ARG_DISPLAY_COMMAND_DESC.get()); 491 listCertsDisplayCommand.addLongIdentifier("displayKeytoolCommand", true); 492 listCertsDisplayCommand.addLongIdentifier("show-keytool-command", true); 493 listCertsDisplayCommand.addLongIdentifier("showKeytoolCommand", true); 494 listCertsParser.addArgument(listCertsDisplayCommand); 495 496 listCertsParser.addExclusiveArgumentSet(listCertsKeystorePassword, 497 listCertsKeystorePasswordFile, listCertsPromptForKeystorePassword); 498 499 final LinkedHashMap<String[],String> listCertsExamples = 500 new LinkedHashMap<>(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(InetAddress.getByName(value)); 5882 sanValues.add("IP:" + value); 5883 } 5884 catch (final Exception e) 5885 { 5886 // This should never happen. 5887 Debug.debugException(e); 5888 throw new RuntimeException(e); 5889 } 5890 } 5891 } 5892 5893 final StringArgument sanEmailArgument = subCommandParser.getStringArgument( 5894 "subject-alternative-name-email-address"); 5895 if ((sanEmailArgument != null) && sanEmailArgument.isPresent()) 5896 { 5897 for (final String value : sanEmailArgument.getValues()) 5898 { 5899 sanBuilder.addRFC822Name(value); 5900 sanValues.add("EMAIL:" + value); 5901 } 5902 } 5903 5904 final StringArgument sanURIArgument = 5905 subCommandParser.getStringArgument("subject-alternative-name-uri"); 5906 if ((sanURIArgument != null) && sanURIArgument.isPresent()) 5907 { 5908 for (final String value : sanURIArgument.getValues()) 5909 { 5910 sanBuilder.addUniformResourceIdentifier(value); 5911 sanValues.add("URI:" + value); 5912 } 5913 } 5914 5915 final StringArgument sanOIDArgument = 5916 subCommandParser.getStringArgument("subject-alternative-name-oid"); 5917 if ((sanOIDArgument != null) && sanOIDArgument.isPresent()) 5918 { 5919 for (final String value : sanOIDArgument.getValues()) 5920 { 5921 sanBuilder.addRegisteredID(new OID(value)); 5922 sanValues.add("OID:" + value); 5923 } 5924 } 5925 5926 if (! sanValues.isEmpty()) 5927 { 5928 try 5929 { 5930 extensionList.add( 5931 new SubjectAlternativeNameExtension(false, sanBuilder.build())); 5932 } 5933 catch (final Exception e) 5934 { 5935 // This should never happen. 5936 Debug.debugException(e); 5937 throw new RuntimeException(e); 5938 } 5939 } 5940 5941 // Build a set of issuer alternative name extension values. 5942 final GeneralNamesBuilder ianBuilder = new GeneralNamesBuilder(); 5943 final LinkedHashSet<String> ianValues = 5944 new LinkedHashSet<>(StaticUtils.computeMapCapacity(10)); 5945 final StringArgument ianDNSArgument = 5946 subCommandParser.getStringArgument("issuer-alternative-name-dns"); 5947 if ((ianDNSArgument != null) && ianDNSArgument.isPresent()) 5948 { 5949 for (final String value : ianDNSArgument.getValues()) 5950 { 5951 ianBuilder.addDNSName(value); 5952 ianValues.add("DNS:" + value); 5953 } 5954 } 5955 5956 final StringArgument ianIPArgument = subCommandParser.getStringArgument( 5957 "issuer-alternative-name-ip-address"); 5958 if ((ianIPArgument != null) && ianIPArgument.isPresent()) 5959 { 5960 for (final String value : ianIPArgument.getValues()) 5961 { 5962 try 5963 { 5964 ianBuilder.addIPAddress(InetAddress.getByName(value)); 5965 ianValues.add("IP:" + value); 5966 } 5967 catch (final Exception e) 5968 { 5969 // This should never happen. 5970 Debug.debugException(e); 5971 throw new RuntimeException(e); 5972 } 5973 } 5974 } 5975 5976 final StringArgument ianEmailArgument = subCommandParser.getStringArgument( 5977 "issuer-alternative-name-email-address"); 5978 if ((ianEmailArgument != null) && ianEmailArgument.isPresent()) 5979 { 5980 for (final String value : ianEmailArgument.getValues()) 5981 { 5982 ianBuilder.addRFC822Name(value); 5983 ianValues.add("EMAIL:" + value); 5984 } 5985 } 5986 5987 final StringArgument ianURIArgument = 5988 subCommandParser.getStringArgument("issuer-alternative-name-uri"); 5989 if ((ianURIArgument != null) && ianURIArgument.isPresent()) 5990 { 5991 for (final String value : ianURIArgument.getValues()) 5992 { 5993 ianBuilder.addUniformResourceIdentifier(value); 5994 ianValues.add("URI:" + value); 5995 } 5996 } 5997 5998 final StringArgument ianOIDArgument = 5999 subCommandParser.getStringArgument("issuer-alternative-name-oid"); 6000 if ((ianOIDArgument != null) && ianOIDArgument.isPresent()) 6001 { 6002 for (final String value : ianOIDArgument.getValues()) 6003 { 6004 ianBuilder.addRegisteredID(new OID(value)); 6005 ianValues.add("OID:" + value); 6006 } 6007 } 6008 6009 if (! ianValues.isEmpty()) 6010 { 6011 try 6012 { 6013 extensionList.add( 6014 new IssuerAlternativeNameExtension(false, ianBuilder.build())); 6015 } 6016 catch (final Exception e) 6017 { 6018 // This should never happen. 6019 Debug.debugException(e); 6020 throw new RuntimeException(e); 6021 } 6022 } 6023 6024 6025 // Build a basic constraints extension, if appropriate. 6026 BasicConstraintsExtension basicConstraints = null; 6027 final BooleanValueArgument basicConstraintsIsCAArgument = 6028 subCommandParser.getBooleanValueArgument("basic-constraints-is-ca"); 6029 if ((basicConstraintsIsCAArgument != null) && 6030 basicConstraintsIsCAArgument.isPresent()) 6031 { 6032 final boolean isCA = basicConstraintsIsCAArgument.getValue(); 6033 6034 Integer pathLength = null; 6035 final IntegerArgument pathLengthArgument = 6036 subCommandParser.getIntegerArgument( 6037 "basic-constraints-maximum-path-length"); 6038 if ((pathLengthArgument != null) && pathLengthArgument.isPresent()) 6039 { 6040 if (isCA) 6041 { 6042 pathLength = pathLengthArgument.getValue(); 6043 } 6044 else 6045 { 6046 wrapErr(0, WRAP_COLUMN, 6047 ERR_MANAGE_CERTS_GEN_CERT_BC_PATH_LENGTH_WITHOUT_CA.get()); 6048 return ResultCode.PARAM_ERROR; 6049 } 6050 } 6051 6052 basicConstraints = new BasicConstraintsExtension(false, isCA, pathLength); 6053 extensionList.add(basicConstraints); 6054 } 6055 6056 6057 // Build a key usage extension, if appropriate. 6058 KeyUsageExtension keyUsage = null; 6059 final StringArgument keyUsageArgument = 6060 subCommandParser.getStringArgument("key-usage"); 6061 if ((keyUsageArgument != null) && keyUsageArgument.isPresent()) 6062 { 6063 boolean digitalSignature = false; 6064 boolean nonRepudiation = false; 6065 boolean keyEncipherment = false; 6066 boolean dataEncipherment = false; 6067 boolean keyAgreement = false; 6068 boolean keyCertSign = false; 6069 boolean crlSign = false; 6070 boolean encipherOnly = false; 6071 boolean decipherOnly = false; 6072 6073 for (final String value : keyUsageArgument.getValues()) 6074 { 6075 if (value.equalsIgnoreCase("digital-signature") || 6076 value.equalsIgnoreCase("digitalSignature")) 6077 { 6078 digitalSignature = true; 6079 } 6080 else if (value.equalsIgnoreCase("non-repudiation") || 6081 value.equalsIgnoreCase("nonRepudiation") || 6082 value.equalsIgnoreCase("content-commitment") || 6083 value.equalsIgnoreCase("contentCommitment")) 6084 { 6085 nonRepudiation = true; 6086 } 6087 else if (value.equalsIgnoreCase("key-encipherment") || 6088 value.equalsIgnoreCase("keyEncipherment")) 6089 { 6090 keyEncipherment = true; 6091 } 6092 else if (value.equalsIgnoreCase("data-encipherment") || 6093 value.equalsIgnoreCase("dataEncipherment")) 6094 { 6095 dataEncipherment = true; 6096 } 6097 else if (value.equalsIgnoreCase("key-agreement") || 6098 value.equalsIgnoreCase("keyAgreement")) 6099 { 6100 keyAgreement = true; 6101 } 6102 else if (value.equalsIgnoreCase("key-cert-sign") || 6103 value.equalsIgnoreCase("keyCertSign")) 6104 { 6105 keyCertSign = true; 6106 } 6107 else if (value.equalsIgnoreCase("crl-sign") || 6108 value.equalsIgnoreCase("crlSign")) 6109 { 6110 crlSign = true; 6111 } 6112 else if (value.equalsIgnoreCase("encipher-only") || 6113 value.equalsIgnoreCase("encipherOnly")) 6114 { 6115 encipherOnly = true; 6116 } 6117 else if (value.equalsIgnoreCase("decipher-only") || 6118 value.equalsIgnoreCase("decipherOnly")) 6119 { 6120 decipherOnly = true; 6121 } 6122 else 6123 { 6124 wrapErr(0, WRAP_COLUMN, 6125 ERR_MANAGE_CERTS_GEN_CERT_INVALID_KEY_USAGE.get(value)); 6126 return ResultCode.PARAM_ERROR; 6127 } 6128 } 6129 6130 keyUsage = new KeyUsageExtension(false, digitalSignature, nonRepudiation, 6131 keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, 6132 crlSign, encipherOnly, decipherOnly); 6133 extensionList.add(keyUsage); 6134 } 6135 6136 6137 // Build an extended key usage extension, if appropriate. 6138 ExtendedKeyUsageExtension extendedKeyUsage = null; 6139 final StringArgument extendedKeyUsageArgument = 6140 subCommandParser.getStringArgument("extended-key-usage"); 6141 if ((extendedKeyUsageArgument != null) && 6142 extendedKeyUsageArgument.isPresent()) 6143 { 6144 final List<String> values = extendedKeyUsageArgument.getValues(); 6145 final ArrayList<OID> keyPurposeIDs = new ArrayList<>(values.size()); 6146 for (final String value : values) 6147 { 6148 if (value.equalsIgnoreCase("server-auth") || 6149 value.equalsIgnoreCase("serverAuth") || 6150 value.equalsIgnoreCase("server-authentication") || 6151 value.equalsIgnoreCase("serverAuthentication") || 6152 value.equalsIgnoreCase("tls-server-authentication") || 6153 value.equalsIgnoreCase("tlsServerAuthentication")) 6154 { 6155 keyPurposeIDs.add( 6156 ExtendedKeyUsageID.TLS_SERVER_AUTHENTICATION.getOID()); 6157 } 6158 else if (value.equalsIgnoreCase("client-auth") || 6159 value.equalsIgnoreCase("clientAuth") || 6160 value.equalsIgnoreCase("client-authentication") || 6161 value.equalsIgnoreCase("clientAuthentication") || 6162 value.equalsIgnoreCase("tls-client-authentication") || 6163 value.equalsIgnoreCase("tlsClientAuthentication")) 6164 { 6165 keyPurposeIDs.add( 6166 ExtendedKeyUsageID.TLS_CLIENT_AUTHENTICATION.getOID()); 6167 } 6168 else if (value.equalsIgnoreCase("code-signing") || 6169 value.equalsIgnoreCase("codeSigning")) 6170 { 6171 keyPurposeIDs.add(ExtendedKeyUsageID.CODE_SIGNING.getOID()); 6172 } 6173 else if (value.equalsIgnoreCase("email-protection") || 6174 value.equalsIgnoreCase("emailProtection")) 6175 { 6176 keyPurposeIDs.add(ExtendedKeyUsageID.EMAIL_PROTECTION.getOID()); 6177 } 6178 else if (value.equalsIgnoreCase("time-stamping") || 6179 value.equalsIgnoreCase("timeStamping")) 6180 { 6181 keyPurposeIDs.add(ExtendedKeyUsageID.TIME_STAMPING.getOID()); 6182 } 6183 else if (value.equalsIgnoreCase("ocsp-signing") || 6184 value.equalsIgnoreCase("ocspSigning")) 6185 { 6186 keyPurposeIDs.add(ExtendedKeyUsageID.OCSP_SIGNING.getOID()); 6187 } 6188 else if (OID.isStrictlyValidNumericOID(value)) 6189 { 6190 keyPurposeIDs.add(new OID(value)); 6191 } 6192 else 6193 { 6194 wrapErr(0, WRAP_COLUMN, 6195 ERR_MANAGE_CERTS_GEN_CERT_INVALID_EXTENDED_KEY_USAGE.get(value)); 6196 return ResultCode.PARAM_ERROR; 6197 } 6198 } 6199 6200 try 6201 { 6202 extendedKeyUsage = new ExtendedKeyUsageExtension(false, keyPurposeIDs); 6203 } 6204 catch (final Exception e) 6205 { 6206 // This should never happen. 6207 Debug.debugException(e); 6208 wrapErr(0, WRAP_COLUMN, 6209 ERR_MANAGE_CERTS_GEN_CERT_EXTENDED_KEY_USAGE_ERROR.get()); 6210 e.printStackTrace(getErr()); 6211 return ResultCode.PARAM_ERROR; 6212 } 6213 6214 extensionList.add(extendedKeyUsage); 6215 } 6216 6217 6218 // Build a list of generic extensions. 6219 final ArrayList<X509CertificateExtension> genericExtensions = 6220 new ArrayList<>(5); 6221 final StringArgument extensionArgument = 6222 subCommandParser.getStringArgument("extension"); 6223 if ((extensionArgument != null) && extensionArgument.isPresent()) 6224 { 6225 for (final String value : extensionArgument.getValues()) 6226 { 6227 try 6228 { 6229 final int firstColonPos = value.indexOf(':'); 6230 final int secondColonPos = value.indexOf(':', firstColonPos + 1); 6231 final OID oid = new OID(value.substring(0, firstColonPos)); 6232 if (! oid.isStrictlyValidNumericOID()) 6233 { 6234 wrapErr(0, WRAP_COLUMN, 6235 ERR_MANAGE_CERTS_GEN_CERT_EXT_MALFORMED_OID.get(value, 6236 oid.toString())); 6237 return ResultCode.PARAM_ERROR; 6238 } 6239 6240 final boolean criticality; 6241 final String criticalityString = 6242 value.substring(firstColonPos + 1, secondColonPos); 6243 if (criticalityString.equalsIgnoreCase("true") || 6244 criticalityString.equalsIgnoreCase("t") || 6245 criticalityString.equalsIgnoreCase("yes") || 6246 criticalityString.equalsIgnoreCase("y") || 6247 criticalityString.equalsIgnoreCase("on") || 6248 criticalityString.equalsIgnoreCase("1")) 6249 { 6250 criticality = true; 6251 } 6252 else if (criticalityString.equalsIgnoreCase("false") || 6253 criticalityString.equalsIgnoreCase("f") || 6254 criticalityString.equalsIgnoreCase("no") || 6255 criticalityString.equalsIgnoreCase("n") || 6256 criticalityString.equalsIgnoreCase("off") || 6257 criticalityString.equalsIgnoreCase("0")) 6258 { 6259 criticality = false; 6260 } 6261 else 6262 { 6263 wrapErr(0, WRAP_COLUMN, 6264 ERR_MANAGE_CERTS_GEN_CERT_EXT_INVALID_CRITICALITY.get( 6265 value, criticalityString)); 6266 return ResultCode.PARAM_ERROR; 6267 } 6268 6269 final byte[] valueBytes; 6270 try 6271 { 6272 valueBytes = StaticUtils.fromHex(value.substring(secondColonPos+1)); 6273 } 6274 catch (final Exception e) 6275 { 6276 Debug.debugException(e); 6277 wrapErr(0, WRAP_COLUMN, 6278 ERR_MANAGE_CERTS_GEN_CERT_EXT_INVALID_VALUE.get(value)); 6279 return ResultCode.PARAM_ERROR; 6280 } 6281 6282 final X509CertificateExtension extension = 6283 new X509CertificateExtension(oid, criticality, valueBytes); 6284 genericExtensions.add(extension); 6285 extensionList.add(extension); 6286 } 6287 catch (final Exception e) 6288 { 6289 Debug.debugException(e); 6290 wrapErr(0, WRAP_COLUMN, 6291 ERR_MANAGE_CERTS_GEN_CERT_EXT_MALFORMED.get(value)); 6292 return ResultCode.PARAM_ERROR; 6293 } 6294 } 6295 } 6296 6297 6298 final String keystoreType; 6299 try 6300 { 6301 keystoreType = inferKeystoreType(keystorePath); 6302 } 6303 catch (final LDAPException le) 6304 { 6305 Debug.debugException(le); 6306 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6307 return le.getResultCode(); 6308 } 6309 6310 final char[] keystorePassword; 6311 try 6312 { 6313 keystorePassword = getKeystorePassword(keystorePath); 6314 } 6315 catch (final LDAPException le) 6316 { 6317 Debug.debugException(le); 6318 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6319 return le.getResultCode(); 6320 } 6321 6322 6323 // Get the keystore. 6324 final KeyStore keystore; 6325 try 6326 { 6327 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 6328 } 6329 catch (final LDAPException le) 6330 { 6331 Debug.debugException(le); 6332 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6333 return le.getResultCode(); 6334 } 6335 6336 6337 // If there is a private key, then see if we need to use a private key 6338 // password that is different from the keystore password. 6339 final char[] privateKeyPassword; 6340 try 6341 { 6342 privateKeyPassword = 6343 getPrivateKeyPassword(keystore, alias, keystorePassword); 6344 } 6345 catch (final LDAPException le) 6346 { 6347 Debug.debugException(le); 6348 wrapErr(0, WRAP_COLUMN, le.getMessage()); 6349 return le.getResultCode(); 6350 } 6351 6352 6353 // If we're going to replace an existing certificate in the keystore, then 6354 // perform the appropriate processing for that. 6355 if (replaceExistingCertificate) 6356 { 6357 // Make sure that the keystore already has a private key entry with the 6358 // specified alias. 6359 if (! hasKeyAlias(keystore, alias)) 6360 { 6361 if (hasCertificateAlias(keystore, alias)) 6362 { 6363 wrapErr(0, WRAP_COLUMN, 6364 ERR_MANAGE_CERTS_GEN_CERT_REPLACE_ALIAS_IS_CERT.get(alias, 6365 keystorePath.getAbsolutePath())); 6366 return ResultCode.PARAM_ERROR; 6367 } 6368 else 6369 { 6370 wrapErr(0, WRAP_COLUMN, 6371 ERR_MANAGE_CERTS_GEN_CERT_REPLACE_NO_SUCH_ALIAS.get(alias, 6372 keystorePath.getAbsolutePath())); 6373 return ResultCode.PARAM_ERROR; 6374 } 6375 } 6376 6377 6378 // Get the certificate to replace, along with its key pair. 6379 final X509Certificate certToReplace; 6380 final KeyPair keyPair; 6381 try 6382 { 6383 final Certificate[] chain = keystore.getCertificateChain(alias); 6384 certToReplace = new X509Certificate(chain[0].getEncoded()); 6385 6386 final PublicKey publicKey = chain[0].getPublicKey(); 6387 final PrivateKey privateKey = 6388 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 6389 keyPair = new KeyPair(publicKey, privateKey); 6390 } 6391 catch (final Exception e) 6392 { 6393 Debug.debugException(e); 6394 wrapErr(0, WRAP_COLUMN, 6395 ERR_MANAGE_CERTS_GEN_CERT_REPLACE_COULD_NOT_GET_CERT.get(alias)); 6396 e.printStackTrace(getErr()); 6397 return ResultCode.LOCAL_ERROR; 6398 } 6399 6400 6401 // Assign the remaining values using information in the existing 6402 // certificate. 6403 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forOID( 6404 certToReplace.getSignatureAlgorithmOID()); 6405 if (signatureAlgorithmIdentifier == null) 6406 { 6407 wrapErr(0, WRAP_COLUMN, 6408 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG_IN_CERT.get( 6409 certToReplace.getSignatureAlgorithmOID())); 6410 return ResultCode.PARAM_ERROR; 6411 } 6412 else 6413 { 6414 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 6415 } 6416 6417 if (subjectDN == null) 6418 { 6419 subjectDN = certToReplace.getSubjectDN(); 6420 } 6421 6422 if (inheritExtensions) 6423 { 6424 for (final X509CertificateExtension extension : 6425 certToReplace.getExtensions()) 6426 { 6427 if ((extension instanceof AuthorityKeyIdentifierExtension) || 6428 (extension instanceof IssuerAlternativeNameExtension)) 6429 { 6430 // This extension applies to the issuer. We won't include this in 6431 // the set of inherited extensions. 6432 } 6433 else if (extension instanceof SubjectKeyIdentifierExtension) 6434 { 6435 // The generated certificate will automatically include a subject 6436 // key identifier extension, so we don't need to include it. 6437 } 6438 else if (extension instanceof BasicConstraintsExtension) 6439 { 6440 // Don't override a value already provided on the command line. 6441 if (basicConstraints == null) 6442 { 6443 basicConstraints = (BasicConstraintsExtension) extension; 6444 extensionList.add(basicConstraints); 6445 } 6446 } 6447 else if (extension instanceof ExtendedKeyUsageExtension) 6448 { 6449 // Don't override a value already provided on the command line. 6450 if (extendedKeyUsage == null) 6451 { 6452 extendedKeyUsage = (ExtendedKeyUsageExtension) extension; 6453 extensionList.add(extendedKeyUsage); 6454 } 6455 } 6456 else if (extension instanceof KeyUsageExtension) 6457 { 6458 // Don't override a value already provided on the command line. 6459 if (keyUsage == null) 6460 { 6461 keyUsage = (KeyUsageExtension) extension; 6462 extensionList.add(keyUsage); 6463 } 6464 } 6465 else if (extension instanceof SubjectAlternativeNameExtension) 6466 { 6467 // Although we could merge values, it's safer to not do that if any 6468 // subject alternative name values were provided on the command 6469 // line. 6470 if (sanValues.isEmpty()) 6471 { 6472 final SubjectAlternativeNameExtension e = 6473 (SubjectAlternativeNameExtension) extension; 6474 for (final String dnsName : e.getDNSNames()) 6475 { 6476 sanValues.add("DNS:" + dnsName); 6477 } 6478 6479 for (final InetAddress ipAddress : e.getIPAddresses()) 6480 { 6481 sanValues.add("IP:" + ipAddress.getHostAddress()); 6482 } 6483 6484 for (final String emailAddress : e.getRFC822Names()) 6485 { 6486 sanValues.add("EMAIL:" + emailAddress); 6487 } 6488 6489 for (final String uri : e.getUniformResourceIdentifiers()) 6490 { 6491 sanValues.add("URI:" + uri); 6492 } 6493 6494 for (final OID oid : e.getRegisteredIDs()) 6495 { 6496 sanValues.add("OID:" + oid.toString()); 6497 } 6498 6499 extensionList.add(extension); 6500 } 6501 } 6502 else 6503 { 6504 genericExtensions.add(extension); 6505 extensionList.add(extension); 6506 } 6507 } 6508 } 6509 6510 6511 // Create an array with the final set of extensions to include in the 6512 // certificate or certificate signing request. 6513 final X509CertificateExtension[] extensions = 6514 new X509CertificateExtension[extensionList.size()]; 6515 extensionList.toArray(extensions); 6516 6517 6518 // If we're generating a self-signed certificate or a certificate signing 6519 // request, then we should now have everything we need to do that. Build 6520 // a keytool command that we could use to accomplish it. 6521 if (isGenerateCertificate) 6522 { 6523 if (displayKeytoolCommand) 6524 { 6525 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 6526 keytoolArguments.add("-selfcert"); 6527 keytoolArguments.add("-keystore"); 6528 keytoolArguments.add(keystorePath.getAbsolutePath()); 6529 keytoolArguments.add("-storetype"); 6530 keytoolArguments.add(keystoreType); 6531 keytoolArguments.add("-storepass"); 6532 keytoolArguments.add("*****REDACTED*****"); 6533 keytoolArguments.add("-keypass"); 6534 keytoolArguments.add("*****REDACTED*****"); 6535 keytoolArguments.add("-alias"); 6536 keytoolArguments.add(alias); 6537 keytoolArguments.add("-dname"); 6538 keytoolArguments.add(subjectDN.toString()); 6539 keytoolArguments.add("-sigalg"); 6540 keytoolArguments.add(signatureAlgorithmName); 6541 keytoolArguments.add("-validity"); 6542 keytoolArguments.add(String.valueOf(daysValid)); 6543 6544 if (validityStartTime != null) 6545 { 6546 keytoolArguments.add("-startdate"); 6547 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 6548 } 6549 6550 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 6551 extendedKeyUsage, sanValues, ianValues, genericExtensions); 6552 6553 displayKeytoolCommand(keytoolArguments); 6554 } 6555 6556 6557 // Generate the self-signed certificate. 6558 final long notBefore; 6559 if (validityStartTime == null) 6560 { 6561 notBefore = System.currentTimeMillis(); 6562 } 6563 else 6564 { 6565 notBefore = validityStartTime.getTime(); 6566 } 6567 6568 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 6569 6570 final X509Certificate certificate; 6571 final Certificate[] chain; 6572 try 6573 { 6574 certificate = X509Certificate.generateSelfSignedCertificate( 6575 signatureAlgorithmIdentifier, keyPair, subjectDN, notBefore, 6576 notAfter, extensions); 6577 chain = new Certificate[] { certificate.toCertificate() }; 6578 } 6579 catch (final Exception e) 6580 { 6581 Debug.debugException(e); 6582 wrapErr(0, WRAP_COLUMN, 6583 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CERT.get()); 6584 e.printStackTrace(getErr()); 6585 return ResultCode.LOCAL_ERROR; 6586 } 6587 6588 6589 // Update the keystore with the new certificate. 6590 try 6591 { 6592 keystore.setKeyEntry(alias, keyPair.getPrivate(), privateKeyPassword, 6593 chain); 6594 writeKeystore(keystore, keystorePath, keystorePassword); 6595 } 6596 catch (final Exception e) 6597 { 6598 Debug.debugException(e); 6599 wrapErr(0, WRAP_COLUMN, 6600 ERR_MANAGE_CERTS_GEN_CERT_ERROR_UPDATING_KEYSTORE.get()); 6601 e.printStackTrace(getErr()); 6602 return ResultCode.LOCAL_ERROR; 6603 } 6604 6605 6606 // Display the certificate we just generated to the end user. 6607 out(); 6608 wrapOut(0, WRAP_COLUMN, 6609 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_SELF_CERT. 6610 get()); 6611 printCertificate(certificate, "", false); 6612 return ResultCode.SUCCESS; 6613 } 6614 else 6615 { 6616 // Build the keytool command used to generate the certificate signing 6617 // request. 6618 Validator.ensureTrue(isGenerateCSR); 6619 if (displayKeytoolCommand) 6620 { 6621 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 6622 keytoolArguments.add("-certreq"); 6623 keytoolArguments.add("-keystore"); 6624 keytoolArguments.add(keystorePath.getAbsolutePath()); 6625 keytoolArguments.add("-storetype"); 6626 keytoolArguments.add(keystoreType); 6627 keytoolArguments.add("-storepass"); 6628 keytoolArguments.add("*****REDACTED*****"); 6629 keytoolArguments.add("-keypass"); 6630 keytoolArguments.add("*****REDACTED*****"); 6631 keytoolArguments.add("-alias"); 6632 keytoolArguments.add(alias); 6633 keytoolArguments.add("-dname"); 6634 keytoolArguments.add(subjectDN.toString()); 6635 keytoolArguments.add("-sigalg"); 6636 keytoolArguments.add(signatureAlgorithmName); 6637 6638 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 6639 extendedKeyUsage, sanValues, ianValues, genericExtensions); 6640 6641 if (outputFile != null) 6642 { 6643 keytoolArguments.add("-file"); 6644 keytoolArguments.add(outputFile.getAbsolutePath()); 6645 } 6646 6647 displayKeytoolCommand(keytoolArguments); 6648 } 6649 6650 6651 // Generate the certificate signing request. 6652 final PKCS10CertificateSigningRequest certificateSigningRequest; 6653 try 6654 { 6655 certificateSigningRequest = PKCS10CertificateSigningRequest. 6656 generateCertificateSigningRequest(signatureAlgorithmIdentifier, 6657 keyPair, subjectDN, extensions); 6658 } 6659 catch (final Exception e) 6660 { 6661 Debug.debugException(e); 6662 wrapErr(0, WRAP_COLUMN, 6663 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CSR.get()); 6664 e.printStackTrace(getErr()); 6665 return ResultCode.LOCAL_ERROR; 6666 } 6667 6668 6669 // Write the generated certificate signing request to the appropriate 6670 // location. 6671 try 6672 { 6673 final PrintStream ps; 6674 if (outputFile == null) 6675 { 6676 ps = getOut(); 6677 } 6678 else 6679 { 6680 ps = new PrintStream(outputFile); 6681 } 6682 6683 if (outputPEM) 6684 { 6685 writePEMCertificateSigningRequest(ps, 6686 certificateSigningRequest. 6687 getPKCS10CertificateSigningRequestBytes()); 6688 } 6689 else 6690 { 6691 ps.write(certificateSigningRequest. 6692 getPKCS10CertificateSigningRequestBytes()); 6693 } 6694 6695 if (outputFile != null) 6696 { 6697 ps.close(); 6698 } 6699 } 6700 catch (final Exception e) 6701 { 6702 Debug.debugException(e); 6703 wrapErr(0, WRAP_COLUMN, 6704 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CSR.get()); 6705 e.printStackTrace(getErr()); 6706 return ResultCode.LOCAL_ERROR; 6707 } 6708 6709 6710 // If the certificate signing request was written to an output file, 6711 // then let the user know that it was successful. If it was written to 6712 // standard output, then we don't need to tell them because they'll be 6713 // able to see it. 6714 if (outputFile != null) 6715 { 6716 out(); 6717 wrapOut(0, WRAP_COLUMN, 6718 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_CSR.get( 6719 outputFile.getAbsolutePath())); 6720 } 6721 6722 return ResultCode.SUCCESS; 6723 } 6724 } 6725 6726 6727 // If we've gotten here, then we know we're not replacing an existing 6728 // certificate. Perform any remaining argument assignment and validation. 6729 if ((subjectDN == null) && (! isSignCSR)) 6730 { 6731 wrapErr(0, WRAP_COLUMN, 6732 ERR_MANAGE_CERTS_GEN_CERT_NO_SUBJECT_DN_WITHOUT_REPLACE.get()); 6733 return ResultCode.PARAM_ERROR; 6734 } 6735 6736 if (keyAlgorithmIdentifier == null) 6737 { 6738 keyAlgorithmIdentifier = PublicKeyAlgorithmIdentifier.RSA; 6739 keyAlgorithmName = keyAlgorithmIdentifier.getName(); 6740 } 6741 6742 if (keySizeBits == null) 6743 { 6744 keySizeBits = 2048; 6745 } 6746 6747 if ((signatureAlgorithmIdentifier == null) && (! isSignCSR)) 6748 { 6749 signatureAlgorithmIdentifier = 6750 SignatureAlgorithmIdentifier.SHA_256_WITH_RSA; 6751 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 6752 } 6753 6754 6755 // If we're going to generate a self-signed certificate or a certificate 6756 // signing request, then we first need to generate a key pair. Put together 6757 // the appropriate set of keytool arguments and then generate a self-signed 6758 // certificate. 6759 if (isGenerateCertificate || isGenerateCSR) 6760 { 6761 // Make sure that the specified alias is not already in use in the 6762 // keystore. 6763 if (hasKeyAlias(keystore, alias) || hasCertificateAlias(keystore, alias)) 6764 { 6765 wrapErr(0, WRAP_COLUMN, 6766 ERR_MANAGE_CERTS_GEN_CERT_ALIAS_EXISTS_WITHOUT_REPLACE.get(alias)); 6767 return ResultCode.PARAM_ERROR; 6768 } 6769 6770 6771 if (displayKeytoolCommand) 6772 { 6773 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 6774 keytoolArguments.add("-genkeypair"); 6775 keytoolArguments.add("-keystore"); 6776 keytoolArguments.add(keystorePath.getAbsolutePath()); 6777 keytoolArguments.add("-storetype"); 6778 keytoolArguments.add(keystoreType); 6779 keytoolArguments.add("-storepass"); 6780 keytoolArguments.add("*****REDACTED*****"); 6781 keytoolArguments.add("-keypass"); 6782 keytoolArguments.add("*****REDACTED*****"); 6783 keytoolArguments.add("-alias"); 6784 keytoolArguments.add(alias); 6785 keytoolArguments.add("-dname"); 6786 keytoolArguments.add(subjectDN.toString()); 6787 keytoolArguments.add("-keyalg"); 6788 keytoolArguments.add(keyAlgorithmName); 6789 keytoolArguments.add("-keysize"); 6790 keytoolArguments.add(String.valueOf(keySizeBits)); 6791 keytoolArguments.add("-sigalg"); 6792 keytoolArguments.add(signatureAlgorithmName); 6793 keytoolArguments.add("-validity"); 6794 keytoolArguments.add(String.valueOf(daysValid)); 6795 6796 if (validityStartTime != null) 6797 { 6798 keytoolArguments.add("-startdate"); 6799 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 6800 } 6801 6802 addExtensionArguments(keytoolArguments, basicConstraints, 6803 keyUsage, extendedKeyUsage, sanValues, ianValues, 6804 genericExtensions); 6805 6806 displayKeytoolCommand(keytoolArguments); 6807 } 6808 6809 6810 // Generate the self-signed certificate. 6811 final long notBefore; 6812 if (validityStartTime == null) 6813 { 6814 notBefore = System.currentTimeMillis(); 6815 } 6816 else 6817 { 6818 notBefore = validityStartTime.getTime(); 6819 } 6820 6821 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 6822 6823 final X509CertificateExtension[] extensions = 6824 new X509CertificateExtension[extensionList.size()]; 6825 extensionList.toArray(extensions); 6826 6827 final Certificate[] chain; 6828 final KeyPair keyPair; 6829 final X509Certificate certificate; 6830 try 6831 { 6832 final ObjectPair<X509Certificate,KeyPair> p = 6833 X509Certificate.generateSelfSignedCertificate( 6834 signatureAlgorithmIdentifier, keyAlgorithmIdentifier, 6835 keySizeBits, subjectDN, notBefore, notAfter, extensions); 6836 certificate = p.getFirst(); 6837 chain = new Certificate[] { certificate.toCertificate() }; 6838 keyPair = p.getSecond(); 6839 } 6840 catch (final Exception e) 6841 { 6842 Debug.debugException(e); 6843 wrapErr(0, WRAP_COLUMN, 6844 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CERT.get()); 6845 e.printStackTrace(getErr()); 6846 return ResultCode.LOCAL_ERROR; 6847 } 6848 6849 6850 // Update the keystore with the new certificate. 6851 try 6852 { 6853 keystore.setKeyEntry(alias, keyPair.getPrivate(), privateKeyPassword, 6854 chain); 6855 writeKeystore(keystore, keystorePath, keystorePassword); 6856 } 6857 catch (final Exception e) 6858 { 6859 Debug.debugException(e); 6860 wrapErr(0, WRAP_COLUMN, 6861 ERR_MANAGE_CERTS_GEN_CERT_ERROR_UPDATING_KEYSTORE.get()); 6862 e.printStackTrace(getErr()); 6863 return ResultCode.LOCAL_ERROR; 6864 } 6865 6866 if (isNewKeystore) 6867 { 6868 out(); 6869 wrapOut(0, WRAP_COLUMN, 6870 INFO_MANAGE_CERTS_GEN_CERT_CERT_CREATED_KEYSTORE.get( 6871 getUserFriendlyKeystoreType(keystoreType))); 6872 } 6873 6874 6875 // If we're just generating a self-signed certificate, then display the 6876 // certificate that we generated. 6877 if (isGenerateCertificate) 6878 { 6879 out(); 6880 wrapOut(0, WRAP_COLUMN, 6881 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_SELF_CERT.get()); 6882 printCertificate(certificate, "", false); 6883 6884 return ResultCode.SUCCESS; 6885 } 6886 6887 6888 // If we're generating a certificate signing request, then put together 6889 // the appropriate set of arguments for that. 6890 Validator.ensureTrue(isGenerateCSR); 6891 out(); 6892 wrapOut(0, WRAP_COLUMN, 6893 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_KEYPAIR.get()); 6894 6895 if (displayKeytoolCommand) 6896 { 6897 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 6898 keytoolArguments.add("-certreq"); 6899 keytoolArguments.add("-keystore"); 6900 keytoolArguments.add(keystorePath.getAbsolutePath()); 6901 keytoolArguments.add("-storetype"); 6902 keytoolArguments.add(keystoreType); 6903 keytoolArguments.add("-storepass"); 6904 keytoolArguments.add("*****REDACTED*****"); 6905 keytoolArguments.add("-keypass"); 6906 keytoolArguments.add("*****REDACTED*****"); 6907 keytoolArguments.add("-alias"); 6908 keytoolArguments.add(alias); 6909 keytoolArguments.add("-dname"); 6910 keytoolArguments.add(subjectDN.toString()); 6911 keytoolArguments.add("-sigalg"); 6912 keytoolArguments.add(signatureAlgorithmName); 6913 6914 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 6915 extendedKeyUsage, sanValues, ianValues, genericExtensions); 6916 6917 if (outputFile != null) 6918 { 6919 keytoolArguments.add("-file"); 6920 keytoolArguments.add(outputFile.getAbsolutePath()); 6921 } 6922 6923 displayKeytoolCommand(keytoolArguments); 6924 } 6925 6926 6927 // Generate the certificate signing request. 6928 final PKCS10CertificateSigningRequest certificateSigningRequest; 6929 try 6930 { 6931 certificateSigningRequest = PKCS10CertificateSigningRequest. 6932 generateCertificateSigningRequest(signatureAlgorithmIdentifier, 6933 keyPair, subjectDN, extensions); 6934 } 6935 catch (final Exception e) 6936 { 6937 Debug.debugException(e); 6938 wrapErr(0, WRAP_COLUMN, 6939 ERR_MANAGE_CERTS_GEN_CERT_ERROR_GENERATING_CSR.get()); 6940 e.printStackTrace(getErr()); 6941 return ResultCode.LOCAL_ERROR; 6942 } 6943 6944 6945 // Write the generated certificate signing request to the appropriate 6946 // location. 6947 try 6948 { 6949 final PrintStream ps; 6950 if (outputFile == null) 6951 { 6952 ps = getOut(); 6953 } 6954 else 6955 { 6956 ps = new PrintStream(outputFile); 6957 } 6958 6959 if (outputPEM) 6960 { 6961 writePEMCertificateSigningRequest(ps, 6962 certificateSigningRequest. 6963 getPKCS10CertificateSigningRequestBytes()); 6964 } 6965 else 6966 { 6967 ps.write(certificateSigningRequest. 6968 getPKCS10CertificateSigningRequestBytes()); 6969 } 6970 6971 if (outputFile != null) 6972 { 6973 ps.close(); 6974 } 6975 } 6976 catch (final Exception e) 6977 { 6978 Debug.debugException(e); 6979 wrapErr(0, WRAP_COLUMN, 6980 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_CSR.get()); 6981 e.printStackTrace(getErr()); 6982 return ResultCode.LOCAL_ERROR; 6983 } 6984 6985 6986 // If the certificate signing request was written to an output file, 6987 // then let the user know that it was successful. If it was written to 6988 // standard output, then we don't need to tell them because they'll be 6989 // able to see it. 6990 if (outputFile != null) 6991 { 6992 out(); 6993 wrapOut(0, WRAP_COLUMN, 6994 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_GENERATED_CSR.get( 6995 outputFile.getAbsolutePath())); 6996 } 6997 6998 return ResultCode.SUCCESS; 6999 } 7000 7001 7002 // If we've gotten here, then we should be signing a certificate signing 7003 // request. Make sure that the keystore already has a private key entry 7004 // with the specified alias. 7005 Validator.ensureTrue(isSignCSR); 7006 if (! hasKeyAlias(keystore, alias)) 7007 { 7008 if (hasCertificateAlias(keystore, alias)) 7009 { 7010 wrapErr(0, WRAP_COLUMN, 7011 ERR_MANAGE_CERTS_GEN_CERT_SIGN_ALIAS_IS_CERT.get(alias, 7012 keystorePath.getAbsolutePath())); 7013 return ResultCode.PARAM_ERROR; 7014 } 7015 else 7016 { 7017 wrapErr(0, WRAP_COLUMN, 7018 ERR_MANAGE_CERTS_GEN_CERT_SIGN_NO_SUCH_ALIAS.get(alias, 7019 keystorePath.getAbsolutePath())); 7020 return ResultCode.PARAM_ERROR; 7021 } 7022 } 7023 7024 7025 // Get the signing certificate and its key pair. 7026 final PrivateKey issuerPrivateKey; 7027 final X509Certificate issuerCertificate; 7028 try 7029 { 7030 final Certificate[] chain = keystore.getCertificateChain(alias); 7031 issuerCertificate = new X509Certificate(chain[0].getEncoded()); 7032 7033 issuerPrivateKey = 7034 (PrivateKey) keystore.getKey(alias, privateKeyPassword); 7035 } 7036 catch (final Exception e) 7037 { 7038 Debug.debugException(e); 7039 wrapErr(0, WRAP_COLUMN, 7040 ERR_MANAGE_CERTS_GEN_CERT_SIGN_CANNOT_GET_SIGNING_CERT.get(alias)); 7041 e.printStackTrace(getErr()); 7042 return ResultCode.LOCAL_ERROR; 7043 } 7044 7045 7046 // Make sure that we can decode the certificate signing request. 7047 final PKCS10CertificateSigningRequest csr; 7048 try 7049 { 7050 csr = readCertificateSigningRequestFromFile(inputFile); 7051 } 7052 catch (final LDAPException le) 7053 { 7054 Debug.debugException(le); 7055 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7056 return le.getResultCode(); 7057 } 7058 7059 7060 // Make sure that we can verify the certificate signing request's signature. 7061 try 7062 { 7063 csr.verifySignature(); 7064 } 7065 catch (final CertException ce) 7066 { 7067 Debug.debugException(ce); 7068 wrapErr(0, WRAP_COLUMN, ce.getMessage()); 7069 return ResultCode.PARAM_ERROR; 7070 } 7071 7072 7073 // Prompt about whether to sign the request, if appropriate. 7074 if (! noPrompt) 7075 { 7076 out(); 7077 wrapOut(0, WRAP_COLUMN, 7078 INFO_MANAGE_CERTS_GEN_CERT_SIGN_CONFIRM.get()); 7079 out(); 7080 printCertificateSigningRequest(csr, false, ""); 7081 out(); 7082 7083 try 7084 { 7085 if (! promptForYesNo( 7086 INFO_MANAGE_CERTS_GEN_CERT_PROMPT_SIGN.get())) 7087 { 7088 wrapErr(0, WRAP_COLUMN, 7089 ERR_MANAGE_CERTS_GEN_CERT_SIGN_CANCELED.get()); 7090 return ResultCode.USER_CANCELED; 7091 } 7092 } 7093 catch (final LDAPException le) 7094 { 7095 Debug.debugException(le); 7096 err(); 7097 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7098 return le.getResultCode(); 7099 } 7100 } 7101 7102 7103 // Read the certificate signing request and see if we need to take values 7104 // from it. 7105 if ((subjectDN == null) || (signatureAlgorithmIdentifier == null) || 7106 includeRequestedExtensions) 7107 { 7108 if (subjectDN == null) 7109 { 7110 subjectDN = csr.getSubjectDN(); 7111 } 7112 7113 if (signatureAlgorithmIdentifier == null) 7114 { 7115 signatureAlgorithmIdentifier = SignatureAlgorithmIdentifier.forOID( 7116 csr.getSignatureAlgorithmOID()); 7117 if (signatureAlgorithmIdentifier == null) 7118 { 7119 wrapErr(0, WRAP_COLUMN, 7120 ERR_MANAGE_CERTS_GEN_CERT_UNKNOWN_SIG_ALG_IN_CSR.get( 7121 csr.getSignatureAlgorithmOID())); 7122 return ResultCode.PARAM_ERROR; 7123 } 7124 else 7125 { 7126 signatureAlgorithmName = signatureAlgorithmIdentifier.getJavaName(); 7127 } 7128 } 7129 7130 if (includeRequestedExtensions) 7131 { 7132 for (final X509CertificateExtension extension : csr.getExtensions()) 7133 { 7134 if ((extension instanceof AuthorityKeyIdentifierExtension) || 7135 (extension instanceof IssuerAlternativeNameExtension)) 7136 { 7137 // This extension applies to the issuer. We won't include this in 7138 // the set of inherited extensions. 7139 } 7140 else if (extension instanceof SubjectKeyIdentifierExtension) 7141 { 7142 // The generated certificate will automatically include a subject 7143 // key identifier extension, so we don't need to include it. 7144 } 7145 else if (extension instanceof BasicConstraintsExtension) 7146 { 7147 // Don't override a value already provided on the command line. 7148 if (basicConstraints == null) 7149 { 7150 basicConstraints = (BasicConstraintsExtension) extension; 7151 extensionList.add(basicConstraints); 7152 } 7153 } 7154 else if (extension instanceof ExtendedKeyUsageExtension) 7155 { 7156 // Don't override a value already provided on the command line. 7157 if (extendedKeyUsage == null) 7158 { 7159 extendedKeyUsage = (ExtendedKeyUsageExtension) extension; 7160 extensionList.add(extendedKeyUsage); 7161 } 7162 } 7163 else if (extension instanceof KeyUsageExtension) 7164 { 7165 // Don't override a value already provided on the command line. 7166 if (keyUsage == null) 7167 { 7168 keyUsage = (KeyUsageExtension) extension; 7169 extensionList.add(keyUsage); 7170 } 7171 } 7172 else if (extension instanceof SubjectAlternativeNameExtension) 7173 { 7174 // Although we could merge values, it's safer to not do that if any 7175 // subject alternative name values were provided on the command 7176 // line. 7177 if (sanValues.isEmpty()) 7178 { 7179 final SubjectAlternativeNameExtension e = 7180 (SubjectAlternativeNameExtension) extension; 7181 for (final String dnsName : e.getDNSNames()) 7182 { 7183 sanBuilder.addDNSName(dnsName); 7184 sanValues.add("DNS:" + dnsName); 7185 } 7186 7187 for (final InetAddress ipAddress : e.getIPAddresses()) 7188 { 7189 sanBuilder.addIPAddress(ipAddress); 7190 sanValues.add("IP:" + ipAddress.getHostAddress()); 7191 } 7192 7193 for (final String emailAddress : e.getRFC822Names()) 7194 { 7195 sanBuilder.addRFC822Name(emailAddress); 7196 sanValues.add("EMAIL:" + emailAddress); 7197 } 7198 7199 for (final String uri : e.getUniformResourceIdentifiers()) 7200 { 7201 sanBuilder.addUniformResourceIdentifier(uri); 7202 sanValues.add("URI:" + uri); 7203 } 7204 7205 for (final OID oid : e.getRegisteredIDs()) 7206 { 7207 sanBuilder.addRegisteredID(oid); 7208 sanValues.add("OID:" + oid.toString()); 7209 } 7210 7211 try 7212 { 7213 extensionList.add( 7214 new SubjectAlternativeNameExtension(false, 7215 sanBuilder.build())); 7216 } 7217 catch (final Exception ex) 7218 { 7219 // This should never happen. 7220 Debug.debugException(ex); 7221 throw new RuntimeException(ex); 7222 } 7223 } 7224 } 7225 else 7226 { 7227 genericExtensions.add(extension); 7228 extensionList.add(extension); 7229 } 7230 } 7231 } 7232 } 7233 7234 7235 // Generate the keytool arguments to use to sign the requested certificate. 7236 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7237 keytoolArguments.add("-gencert"); 7238 keytoolArguments.add("-keystore"); 7239 keytoolArguments.add(keystorePath.getAbsolutePath()); 7240 keytoolArguments.add("-storetype"); 7241 keytoolArguments.add(keystoreType); 7242 keytoolArguments.add("-storepass"); 7243 keytoolArguments.add("*****REDACTED*****"); 7244 keytoolArguments.add("-keypass"); 7245 keytoolArguments.add("*****REDACTED*****"); 7246 keytoolArguments.add("-alias"); 7247 keytoolArguments.add(alias); 7248 keytoolArguments.add("-dname"); 7249 keytoolArguments.add(subjectDN.toString()); 7250 keytoolArguments.add("-sigalg"); 7251 keytoolArguments.add(signatureAlgorithmName); 7252 keytoolArguments.add("-validity"); 7253 keytoolArguments.add(String.valueOf(daysValid)); 7254 7255 if (validityStartTime != null) 7256 { 7257 keytoolArguments.add("-startdate"); 7258 keytoolArguments.add(formatValidityStartTime(validityStartTime)); 7259 } 7260 7261 addExtensionArguments(keytoolArguments, basicConstraints, keyUsage, 7262 extendedKeyUsage, sanValues, ianValues, genericExtensions); 7263 7264 keytoolArguments.add("-infile"); 7265 keytoolArguments.add(inputFile.getAbsolutePath()); 7266 7267 if (outputFile != null) 7268 { 7269 keytoolArguments.add("-outfile"); 7270 keytoolArguments.add(outputFile.getAbsolutePath()); 7271 } 7272 7273 if (outputPEM) 7274 { 7275 keytoolArguments.add("-rfc"); 7276 } 7277 7278 if (displayKeytoolCommand) 7279 { 7280 displayKeytoolCommand(keytoolArguments); 7281 } 7282 7283 7284 // Generate the signed certificate. 7285 final long notBefore; 7286 if (validityStartTime == null) 7287 { 7288 notBefore = System.currentTimeMillis(); 7289 } 7290 else 7291 { 7292 notBefore = validityStartTime.getTime(); 7293 } 7294 7295 final long notAfter = notBefore + TimeUnit.DAYS.toMillis(daysValid); 7296 7297 final X509CertificateExtension[] extensions = 7298 new X509CertificateExtension[extensionList.size()]; 7299 extensionList.toArray(extensions); 7300 7301 final X509Certificate signedCertificate; 7302 try 7303 { 7304 signedCertificate = X509Certificate.generateIssuerSignedCertificate( 7305 signatureAlgorithmIdentifier, issuerCertificate, issuerPrivateKey, 7306 csr.getPublicKeyAlgorithmOID(), 7307 csr.getPublicKeyAlgorithmParameters(), csr.getEncodedPublicKey(), 7308 csr.getDecodedPublicKey(), subjectDN, notBefore, notAfter, 7309 extensions); 7310 } 7311 catch (final Exception e) 7312 { 7313 Debug.debugException(e); 7314 wrapErr(0, WRAP_COLUMN, 7315 ERR_MANAGE_CERTS_GEN_CERT_ERROR_SIGNING_CERT.get()); 7316 e.printStackTrace(getErr()); 7317 return ResultCode.LOCAL_ERROR; 7318 } 7319 7320 7321 // Write the signed certificate signing request to the appropriate location. 7322 try 7323 { 7324 final PrintStream ps; 7325 if (outputFile == null) 7326 { 7327 ps = getOut(); 7328 } 7329 else 7330 { 7331 ps = new PrintStream(outputFile); 7332 } 7333 7334 if (outputPEM) 7335 { 7336 writePEMCertificate(ps, signedCertificate.getX509CertificateBytes()); 7337 } 7338 else 7339 { 7340 ps.write(signedCertificate.getX509CertificateBytes()); 7341 } 7342 7343 if (outputFile != null) 7344 { 7345 ps.close(); 7346 } 7347 } 7348 catch (final Exception e) 7349 { 7350 Debug.debugException(e); 7351 wrapErr(0, WRAP_COLUMN, 7352 ERR_MANAGE_CERTS_GEN_CERT_ERROR_WRITING_SIGNED_CERT.get()); 7353 e.printStackTrace(getErr()); 7354 return ResultCode.LOCAL_ERROR; 7355 } 7356 7357 7358 // If the certificate signing request was written to an output file, 7359 // then let the user know that it was successful. If it was written to 7360 // standard output, then we don't need to tell them because they'll be 7361 // able to see it. 7362 if (outputFile != null) 7363 { 7364 out(); 7365 wrapOut(0, WRAP_COLUMN, 7366 INFO_MANAGE_CERTS_GEN_CERT_SUCCESSFULLY_SIGNED_CERT.get( 7367 outputFile.getAbsolutePath())); 7368 } 7369 7370 return ResultCode.SUCCESS; 7371 } 7372 7373 7374 7375 /** 7376 * Performs the necessary processing for the change-certificate-alias 7377 * subcommand. 7378 * 7379 * @return A result code that indicates whether the processing completed 7380 * successfully. 7381 */ 7382 private ResultCode doChangeCertificateAlias() 7383 { 7384 // Get the values of a number of configured arguments. 7385 final StringArgument currentAliasArgument = 7386 subCommandParser.getStringArgument("current-alias"); 7387 final String currentAlias = currentAliasArgument.getValue(); 7388 7389 final StringArgument newAliasArgument = 7390 subCommandParser.getStringArgument("new-alias"); 7391 final String newAlias = newAliasArgument.getValue(); 7392 7393 final String keystoreType; 7394 final File keystorePath = getKeystorePath(); 7395 try 7396 { 7397 keystoreType = inferKeystoreType(keystorePath); 7398 } 7399 catch (final LDAPException le) 7400 { 7401 Debug.debugException(le); 7402 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7403 return le.getResultCode(); 7404 } 7405 7406 final char[] keystorePassword; 7407 try 7408 { 7409 keystorePassword = getKeystorePassword(keystorePath); 7410 } 7411 catch (final LDAPException le) 7412 { 7413 Debug.debugException(le); 7414 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7415 return le.getResultCode(); 7416 } 7417 7418 7419 // Get the keystore. 7420 final KeyStore keystore; 7421 try 7422 { 7423 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 7424 } 7425 catch (final LDAPException le) 7426 { 7427 Debug.debugException(le); 7428 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7429 return le.getResultCode(); 7430 } 7431 7432 7433 // See if we need to use a private key password that is different from the 7434 // keystore password. 7435 final char[] privateKeyPassword; 7436 try 7437 { 7438 privateKeyPassword = 7439 getPrivateKeyPassword(keystore, currentAlias, keystorePassword); 7440 } 7441 catch (final LDAPException le) 7442 { 7443 Debug.debugException(le); 7444 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7445 return le.getResultCode(); 7446 } 7447 7448 7449 // Make sure that the keystore has an existing entry with the current alias. 7450 // It must be either a certificate entry or a private key entry. 7451 final Certificate existingCertificate; 7452 final Certificate[] existingCertificateChain; 7453 final PrivateKey existingPrivateKey; 7454 try 7455 { 7456 if (hasCertificateAlias(keystore, currentAlias)) 7457 { 7458 existingCertificate = keystore.getCertificate(currentAlias); 7459 existingCertificateChain = null; 7460 existingPrivateKey = null; 7461 } 7462 else if (hasKeyAlias(keystore, currentAlias)) 7463 { 7464 existingCertificateChain = keystore.getCertificateChain(currentAlias); 7465 existingPrivateKey = 7466 (PrivateKey) keystore.getKey(currentAlias, privateKeyPassword); 7467 existingCertificate = null; 7468 } 7469 else 7470 { 7471 wrapErr(0, WRAP_COLUMN, 7472 ERR_MANAGE_CERTS_CHANGE_ALIAS_NO_SUCH_ALIAS.get(currentAlias)); 7473 return ResultCode.PARAM_ERROR; 7474 } 7475 } 7476 catch (final Exception e) 7477 { 7478 Debug.debugException(e); 7479 wrapErr(0, WRAP_COLUMN, 7480 ERR_MANAGE_CERTS_CHANGE_ALIAS_CANNOT_GET_EXISTING_ENTRY.get( 7481 currentAlias)); 7482 e.printStackTrace(getErr()); 7483 return ResultCode.LOCAL_ERROR; 7484 } 7485 7486 7487 // Make sure that the keystore does not have an entry with the new alias. 7488 if (hasCertificateAlias(keystore, newAlias) || 7489 hasKeyAlias(keystore, newAlias)) 7490 { 7491 wrapErr(0, WRAP_COLUMN, 7492 ERR_MANAGE_CERTS_CHANGE_ALIAS_NEW_ALIAS_IN_USE.get(newAlias)); 7493 return ResultCode.PARAM_ERROR; 7494 } 7495 7496 7497 // Generate the keytool arguments to use to change the certificate alias. 7498 final BooleanArgument displayKeytoolCommandArgument = 7499 subCommandParser.getBooleanArgument("display-keytool-command"); 7500 if ((displayKeytoolCommandArgument != null) && 7501 displayKeytoolCommandArgument.isPresent()) 7502 { 7503 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7504 keytoolArguments.add("-changealias"); 7505 keytoolArguments.add("-keystore"); 7506 keytoolArguments.add(keystorePath.getAbsolutePath()); 7507 keytoolArguments.add("-storetype"); 7508 keytoolArguments.add(keystoreType); 7509 keytoolArguments.add("-storepass"); 7510 keytoolArguments.add("*****REDACTED*****"); 7511 keytoolArguments.add("-keypass"); 7512 keytoolArguments.add("*****REDACTED*****"); 7513 keytoolArguments.add("-alias"); 7514 keytoolArguments.add(currentAlias); 7515 keytoolArguments.add("-destalias"); 7516 keytoolArguments.add(newAlias); 7517 7518 displayKeytoolCommand(keytoolArguments); 7519 } 7520 7521 7522 // Update the keystore to remove the entry with the current alias and 7523 // re-write it with the new alias. 7524 try 7525 { 7526 keystore.deleteEntry(currentAlias); 7527 if (existingCertificate != null) 7528 { 7529 keystore.setCertificateEntry(newAlias, existingCertificate); 7530 } 7531 else 7532 { 7533 keystore.setKeyEntry(newAlias, existingPrivateKey, 7534 privateKeyPassword, existingCertificateChain); 7535 } 7536 7537 writeKeystore(keystore, keystorePath, keystorePassword); 7538 } 7539 catch (final Exception e) 7540 { 7541 Debug.debugException(e); 7542 wrapErr(0, WRAP_COLUMN, 7543 ERR_MANAGE_CERTS_CHANGE_ALIAS_CANNOT_UPDATE_KEYSTORE.get()); 7544 e.printStackTrace(getErr()); 7545 return ResultCode.LOCAL_ERROR; 7546 } 7547 7548 wrapOut(0, WRAP_COLUMN, 7549 INFO_MANAGE_CERTS_CHANGE_ALIAS_SUCCESSFUL.get(currentAlias, 7550 newAlias)); 7551 return ResultCode.SUCCESS; 7552 } 7553 7554 7555 7556 /** 7557 * Performs the necessary processing for the change-keystore-password 7558 * subcommand. 7559 * 7560 * @return A result code that indicates whether the processing completed 7561 * successfully. 7562 */ 7563 private ResultCode doChangeKeystorePassword() 7564 { 7565 // Get the values of a number of configured arguments. 7566 final String keystoreType; 7567 final File keystorePath = getKeystorePath(); 7568 try 7569 { 7570 keystoreType = inferKeystoreType(keystorePath); 7571 } 7572 catch (final LDAPException le) 7573 { 7574 Debug.debugException(le); 7575 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7576 return le.getResultCode(); 7577 } 7578 7579 final char[] currentKeystorePassword; 7580 try 7581 { 7582 currentKeystorePassword = getKeystorePassword(keystorePath, "current"); 7583 } 7584 catch (final LDAPException le) 7585 { 7586 Debug.debugException(le); 7587 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7588 return le.getResultCode(); 7589 } 7590 7591 final char[] newKeystorePassword; 7592 try 7593 { 7594 newKeystorePassword = getKeystorePassword(keystorePath, "new"); 7595 } 7596 catch (final LDAPException le) 7597 { 7598 Debug.debugException(le); 7599 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7600 return le.getResultCode(); 7601 } 7602 7603 7604 // Get the keystore. 7605 final KeyStore keystore; 7606 try 7607 { 7608 keystore = getKeystore(keystoreType, keystorePath, 7609 currentKeystorePassword); 7610 } 7611 catch (final LDAPException le) 7612 { 7613 Debug.debugException(le); 7614 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7615 return le.getResultCode(); 7616 } 7617 7618 7619 // Generate the keytool arguments to use to change the keystore password. 7620 final BooleanArgument displayKeytoolCommandArgument = 7621 subCommandParser.getBooleanArgument("display-keytool-command"); 7622 if ((displayKeytoolCommandArgument != null) && 7623 displayKeytoolCommandArgument.isPresent()) 7624 { 7625 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7626 keytoolArguments.add("-storepasswd"); 7627 keytoolArguments.add("-keystore"); 7628 keytoolArguments.add(keystorePath.getAbsolutePath()); 7629 keytoolArguments.add("-storetype"); 7630 keytoolArguments.add(keystoreType); 7631 keytoolArguments.add("-storepass"); 7632 keytoolArguments.add("*****REDACTED*****"); 7633 keytoolArguments.add("-new"); 7634 keytoolArguments.add("*****REDACTED*****"); 7635 7636 displayKeytoolCommand(keytoolArguments); 7637 } 7638 7639 7640 // Rewrite the keystore with the new password. 7641 try 7642 { 7643 writeKeystore(keystore, keystorePath, newKeystorePassword); 7644 } 7645 catch (final LDAPException le) 7646 { 7647 Debug.debugException(le); 7648 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7649 return le.getResultCode(); 7650 } 7651 7652 wrapOut(0, WRAP_COLUMN, 7653 INFO_MANAGE_CERTS_CHANGE_KS_PW_SUCCESSFUL.get( 7654 keystorePath.getAbsolutePath())); 7655 return ResultCode.SUCCESS; 7656 } 7657 7658 7659 7660 /** 7661 * Performs the necessary processing for the change-private-key-password 7662 * subcommand. 7663 * 7664 * @return A result code that indicates whether the processing completed 7665 * successfully. 7666 */ 7667 private ResultCode doChangePrivateKeyPassword() 7668 { 7669 // Get the values of a number of configured arguments. 7670 final StringArgument aliasArgument = 7671 subCommandParser.getStringArgument("alias"); 7672 final String alias = aliasArgument.getValue(); 7673 7674 final String keystoreType; 7675 final File keystorePath = getKeystorePath(); 7676 try 7677 { 7678 keystoreType = inferKeystoreType(keystorePath); 7679 } 7680 catch (final LDAPException le) 7681 { 7682 Debug.debugException(le); 7683 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7684 return le.getResultCode(); 7685 } 7686 7687 final char[] keystorePassword; 7688 try 7689 { 7690 keystorePassword = getKeystorePassword(keystorePath); 7691 } 7692 catch (final LDAPException le) 7693 { 7694 Debug.debugException(le); 7695 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7696 return le.getResultCode(); 7697 } 7698 7699 7700 // Get the keystore. 7701 final KeyStore keystore; 7702 try 7703 { 7704 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 7705 } 7706 catch (final LDAPException le) 7707 { 7708 Debug.debugException(le); 7709 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7710 return le.getResultCode(); 7711 } 7712 7713 7714 // Make sure that the keystore has a key entry with the specified alias. 7715 if (hasCertificateAlias(keystore, alias)) 7716 { 7717 wrapErr(0, WRAP_COLUMN, 7718 ERR_MANAGE_CERTS_CHANGE_PK_PW_ALIAS_IS_CERT.get(alias)); 7719 return ResultCode.PARAM_ERROR; 7720 } 7721 else if (! hasKeyAlias(keystore, alias)) 7722 { 7723 wrapErr(0, WRAP_COLUMN, 7724 ERR_MANAGE_CERTS_CHANGE_PK_PW_NO_SUCH_ALIAS.get(alias)); 7725 return ResultCode.PARAM_ERROR; 7726 } 7727 7728 7729 // Get the current and new private key passwords. 7730 final char[] currentPrivateKeyPassword; 7731 try 7732 { 7733 currentPrivateKeyPassword = 7734 getPrivateKeyPassword(keystore, alias, "current", keystorePassword); 7735 } 7736 catch (final LDAPException le) 7737 { 7738 Debug.debugException(le); 7739 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7740 return le.getResultCode(); 7741 } 7742 7743 final char[] newPrivateKeyPassword; 7744 try 7745 { 7746 newPrivateKeyPassword = 7747 getPrivateKeyPassword(keystore, alias, "new", keystorePassword); 7748 } 7749 catch (final LDAPException le) 7750 { 7751 Debug.debugException(le); 7752 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7753 return le.getResultCode(); 7754 } 7755 7756 7757 // Generate the keytool arguments to use to change the private key. 7758 final BooleanArgument displayKeytoolCommandArgument = 7759 subCommandParser.getBooleanArgument("display-keytool-command"); 7760 if ((displayKeytoolCommandArgument != null) && 7761 displayKeytoolCommandArgument.isPresent()) 7762 { 7763 final ArrayList<String> keytoolArguments = new ArrayList<>(30); 7764 keytoolArguments.add("-keypasswd"); 7765 keytoolArguments.add("-keystore"); 7766 keytoolArguments.add(keystorePath.getAbsolutePath()); 7767 keytoolArguments.add("-storetype"); 7768 keytoolArguments.add(keystoreType); 7769 keytoolArguments.add("-storepass"); 7770 keytoolArguments.add("*****REDACTED*****"); 7771 keytoolArguments.add("-alias"); 7772 keytoolArguments.add(alias); 7773 keytoolArguments.add("-keypass"); 7774 keytoolArguments.add("*****REDACTED*****"); 7775 keytoolArguments.add("-new"); 7776 keytoolArguments.add("*****REDACTED*****"); 7777 7778 displayKeytoolCommand(keytoolArguments); 7779 } 7780 7781 7782 // Get the contents of the private key entry. 7783 final Certificate[] chain; 7784 final PrivateKey privateKey; 7785 try 7786 { 7787 chain = keystore.getCertificateChain(alias); 7788 privateKey = 7789 (PrivateKey) keystore.getKey(alias, currentPrivateKeyPassword); 7790 } 7791 catch (final UnrecoverableKeyException e) 7792 { 7793 Debug.debugException(e); 7794 wrapErr(0, WRAP_COLUMN, 7795 ERR_MANAGE_CERTS_CHANGE_PK_PW_WRONG_PK_PW.get(alias)); 7796 return ResultCode.PARAM_ERROR; 7797 } 7798 catch (final Exception e) 7799 { 7800 Debug.debugException(e); 7801 wrapErr(0, WRAP_COLUMN, 7802 ERR_MANAGE_CERTS_CHANGE_PK_PW_CANNOT_GET_PK.get(alias)); 7803 e.printStackTrace(getErr()); 7804 return ResultCode.LOCAL_ERROR; 7805 } 7806 7807 7808 // Remove the existing key entry and re-add it with the new password. 7809 try 7810 { 7811 keystore.deleteEntry(alias); 7812 keystore.setKeyEntry(alias, privateKey, newPrivateKeyPassword, chain); 7813 writeKeystore(keystore, keystorePath, keystorePassword); 7814 } 7815 catch (final Exception e) 7816 { 7817 Debug.debugException(e); 7818 wrapErr(0, WRAP_COLUMN, 7819 ERR_MANAGE_CERTS_CHANGE_PK_PW_CANNOT_UPDATE_KS.get()); 7820 e.printStackTrace(getErr()); 7821 return ResultCode.LOCAL_ERROR; 7822 } 7823 7824 wrapOut(0, WRAP_COLUMN, 7825 INFO_MANAGE_CERTS_CHANGE_PK_PW_SUCCESSFUL.get(alias)); 7826 return ResultCode.SUCCESS; 7827 } 7828 7829 7830 7831 /** 7832 * Performs the necessary processing for the trust-server-certificate 7833 * subcommand. 7834 * 7835 * @return A result code that indicates whether the processing completed 7836 * successfully. 7837 */ 7838 private ResultCode doTrustServerCertificate() 7839 { 7840 // Get the values of a number of configured arguments. 7841 final StringArgument hostnameArgument = 7842 subCommandParser.getStringArgument("hostname"); 7843 final String hostname = hostnameArgument.getValue(); 7844 7845 final IntegerArgument portArgument = 7846 subCommandParser.getIntegerArgument("port"); 7847 final int port = portArgument.getValue(); 7848 7849 final String alias; 7850 final StringArgument aliasArgument = 7851 subCommandParser.getStringArgument("alias"); 7852 if ((aliasArgument != null) && aliasArgument.isPresent()) 7853 { 7854 alias = aliasArgument.getValue(); 7855 } 7856 else 7857 { 7858 alias = hostname + ':' + port; 7859 } 7860 7861 final BooleanArgument useLDAPStartTLSArgument = 7862 subCommandParser.getBooleanArgument("use-ldap-start-tls"); 7863 final boolean useLDAPStartTLS = 7864 ((useLDAPStartTLSArgument != null) && 7865 useLDAPStartTLSArgument.isPresent()); 7866 7867 final BooleanArgument issuersOnlyArgument = 7868 subCommandParser.getBooleanArgument("issuers-only"); 7869 final boolean issuersOnly = 7870 ((issuersOnlyArgument != null) && issuersOnlyArgument.isPresent()); 7871 7872 final BooleanArgument noPromptArgument = 7873 subCommandParser.getBooleanArgument("no-prompt"); 7874 final boolean noPrompt = 7875 ((noPromptArgument != null) && noPromptArgument.isPresent()); 7876 7877 final BooleanArgument verboseArgument = 7878 subCommandParser.getBooleanArgument("verbose"); 7879 final boolean verbose = 7880 ((verboseArgument != null) && verboseArgument.isPresent()); 7881 7882 final String keystoreType; 7883 final File keystorePath = getKeystorePath(); 7884 final boolean isNewKeystore = (! keystorePath.exists()); 7885 try 7886 { 7887 keystoreType = inferKeystoreType(keystorePath); 7888 } 7889 catch (final LDAPException le) 7890 { 7891 Debug.debugException(le); 7892 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7893 return le.getResultCode(); 7894 } 7895 7896 final char[] keystorePassword; 7897 try 7898 { 7899 keystorePassword = getKeystorePassword(keystorePath); 7900 } 7901 catch (final LDAPException le) 7902 { 7903 Debug.debugException(le); 7904 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7905 return le.getResultCode(); 7906 } 7907 7908 7909 // Get the keystore. 7910 final KeyStore keystore; 7911 try 7912 { 7913 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 7914 } 7915 catch (final LDAPException le) 7916 { 7917 Debug.debugException(le); 7918 wrapErr(0, WRAP_COLUMN, le.getMessage()); 7919 return le.getResultCode(); 7920 } 7921 7922 7923 // Make sure that the specified alias is not already in use. 7924 if (hasCertificateAlias(keystore, alias) || 7925 hasKeyAlias(keystore, alias)) 7926 { 7927 wrapErr(0, WRAP_COLUMN, 7928 ERR_MANAGE_CERTS_TRUST_SERVER_ALIAS_IN_USE.get(alias)); 7929 return ResultCode.PARAM_ERROR; 7930 } 7931 7932 7933 // Spawn a background thread to establish a connection and get the 7934 // certificate chain from the target server. 7935 final LinkedBlockingQueue<Object> responseQueue = 7936 new LinkedBlockingQueue<>(10); 7937 final ManageCertificatesServerCertificateCollector certificateCollector = 7938 new ManageCertificatesServerCertificateCollector(this, hostname, port, 7939 useLDAPStartTLS, verbose, responseQueue); 7940 certificateCollector.start(); 7941 7942 Object responseObject = 7943 ERR_MANAGE_CERTS_TRUST_SERVER_NO_CERT_CHAIN_RECEIVED.get( 7944 hostname + ':' + port); 7945 try 7946 { 7947 responseObject = responseQueue.poll(90L, TimeUnit.SECONDS); 7948 } 7949 catch (final Exception e) 7950 { 7951 Debug.debugException(e); 7952 } 7953 7954 final X509Certificate[] chain; 7955 if (responseObject instanceof X509Certificate[]) 7956 { 7957 chain = (X509Certificate[]) responseObject; 7958 } 7959 else if (responseObject instanceof CertException) 7960 { 7961 // The error message will have already been recorded by the collector 7962 // thread, so we can just return a non-success result. 7963 return ResultCode.LOCAL_ERROR; 7964 } 7965 else 7966 { 7967 wrapErr(0, WRAP_COLUMN, String.valueOf(responseObject)); 7968 return ResultCode.LOCAL_ERROR; 7969 } 7970 7971 7972 // If we should prompt the user about whether to trust the certificates, 7973 // then do so now. 7974 if (! noPrompt) 7975 { 7976 out(); 7977 wrapOut(0, WRAP_COLUMN, 7978 INFO_MANAGE_CERTS_TRUST_SERVER_RETRIEVED_CHAIN.get( 7979 hostname + ':' + port)); 7980 7981 boolean isFirst = true; 7982 for (final X509Certificate c : chain) 7983 { 7984 out(); 7985 7986 if (isFirst) 7987 { 7988 isFirst = false; 7989 if (issuersOnly && (chain.length > 1)) 7990 { 7991 wrapOut(0, WRAP_COLUMN, 7992 INFO_MANAGE_CERTS_TRUST_SERVER_NOTE_OMITTED.get()); 7993 out(); 7994 } 7995 } 7996 7997 printCertificate(c, "", verbose); 7998 } 7999 8000 out(); 8001 8002 try 8003 { 8004 if (! promptForYesNo(INFO_MANAGE_CERTS_TRUST_SERVER_PROMPT_TRUST.get())) 8005 { 8006 wrapErr(0, WRAP_COLUMN, 8007 ERR_MANAGE_CERTS_TRUST_SERVER_CHAIN_REJECTED.get()); 8008 return ResultCode.USER_CANCELED; 8009 } 8010 } 8011 catch (final LDAPException le) 8012 { 8013 Debug.debugException(le); 8014 err(); 8015 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8016 return le.getResultCode(); 8017 } 8018 } 8019 8020 8021 // Add the certificates to the keystore. 8022 final LinkedHashMap<String,X509Certificate> certsByAlias = 8023 new LinkedHashMap<>(StaticUtils.computeMapCapacity(chain.length)); 8024 for (int i=0; i < chain.length; i++) 8025 { 8026 if (i == 0) 8027 { 8028 if (issuersOnly && (chain.length > 1)) 8029 { 8030 continue; 8031 } 8032 8033 certsByAlias.put(alias, chain[i]); 8034 } 8035 else if ((i == 1) && (chain.length == 2)) 8036 { 8037 certsByAlias.put(alias + "-issuer", chain[i]); 8038 } 8039 else 8040 { 8041 certsByAlias.put(alias + "-issuer-" + i, chain[i]); 8042 } 8043 } 8044 8045 for (final Map.Entry<String,X509Certificate> e : certsByAlias.entrySet()) 8046 { 8047 final String certAlias = e.getKey(); 8048 final X509Certificate cert = e.getValue(); 8049 8050 try 8051 { 8052 Validator.ensureFalse( 8053 (hasCertificateAlias(keystore, certAlias) || 8054 hasKeyAlias(keystore, certAlias)), 8055 "ERROR: Alias '" + certAlias + "' is already in use in the " + 8056 "keystore."); 8057 keystore.setCertificateEntry(certAlias, cert.toCertificate()); 8058 } 8059 catch (final Exception ex) 8060 { 8061 Debug.debugException(ex); 8062 wrapErr(0, WRAP_COLUMN, 8063 ERR_MANAGE_CERTS_TRUST_SERVER_ERROR_ADDING_CERT_TO_KS.get( 8064 cert.getSubjectDN())); 8065 ex.printStackTrace(getErr()); 8066 return ResultCode.LOCAL_ERROR; 8067 } 8068 } 8069 8070 8071 // Save the updated keystore. 8072 try 8073 { 8074 writeKeystore(keystore, keystorePath, keystorePassword); 8075 } 8076 catch (final LDAPException le) 8077 { 8078 Debug.debugException(le); 8079 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8080 return le.getResultCode(); 8081 } 8082 8083 if (isNewKeystore) 8084 { 8085 out(); 8086 wrapOut(0, WRAP_COLUMN, 8087 INFO_MANAGE_CERTS_TRUST_SERVER_CERT_CREATED_KEYSTORE.get( 8088 getUserFriendlyKeystoreType(keystoreType))); 8089 } 8090 8091 out(); 8092 if (certsByAlias.size() == 1) 8093 { 8094 wrapOut(0, WRAP_COLUMN, 8095 INFO_MANAGE_CERTS_TRUST_SERVER_ADDED_CERT_TO_KS.get()); 8096 } 8097 else 8098 { 8099 wrapOut(0, WRAP_COLUMN, 8100 INFO_MANAGE_CERTS_TRUST_SERVER_ADDED_CERTS_TO_KS.get( 8101 certsByAlias.size())); 8102 } 8103 8104 return ResultCode.SUCCESS; 8105 } 8106 8107 8108 8109 /** 8110 * Performs the necessary processing for the check-certificate-usability 8111 * subcommand. 8112 * 8113 * @return A result code that indicates whether the processing completed 8114 * successfully. 8115 */ 8116 private ResultCode doCheckCertificateUsability() 8117 { 8118 // Get the values of a number of configured arguments. 8119 final StringArgument aliasArgument = 8120 subCommandParser.getStringArgument("alias"); 8121 final String alias = aliasArgument.getValue(); 8122 8123 final String keystoreType; 8124 final File keystorePath = getKeystorePath(); 8125 try 8126 { 8127 keystoreType = inferKeystoreType(keystorePath); 8128 } 8129 catch (final LDAPException le) 8130 { 8131 Debug.debugException(le); 8132 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8133 return le.getResultCode(); 8134 } 8135 8136 final char[] keystorePassword; 8137 try 8138 { 8139 keystorePassword = getKeystorePassword(keystorePath); 8140 } 8141 catch (final LDAPException le) 8142 { 8143 Debug.debugException(le); 8144 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8145 return le.getResultCode(); 8146 } 8147 8148 8149 // Get the keystore. 8150 final KeyStore keystore; 8151 try 8152 { 8153 keystore = getKeystore(keystoreType, keystorePath, keystorePassword); 8154 } 8155 catch (final LDAPException le) 8156 { 8157 Debug.debugException(le); 8158 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8159 return le.getResultCode(); 8160 } 8161 8162 8163 // Make sure that the specified entry exists in the keystore and is 8164 // associated with a certificate chain and a private key. 8165 final X509Certificate[] chain; 8166 if (hasKeyAlias(keystore, alias)) 8167 { 8168 try 8169 { 8170 final Certificate[] genericChain = keystore.getCertificateChain(alias); 8171 Validator.ensureTrue((genericChain.length > 0), 8172 "ERROR: The keystore has a private key entry for alias '" + 8173 alias + "', but the associated certificate chain is empty."); 8174 8175 chain = new X509Certificate[genericChain.length]; 8176 for (int i=0; i < genericChain.length; i++) 8177 { 8178 chain[i] = new X509Certificate(genericChain[i].getEncoded()); 8179 } 8180 8181 out(); 8182 wrapOut(0, WRAP_COLUMN, 8183 INFO_MANAGE_CERTS_CHECK_USABILITY_GOT_CHAIN.get(alias)); 8184 8185 for (final X509Certificate c : chain) 8186 { 8187 out(); 8188 printCertificate(c, "", false); 8189 } 8190 } 8191 catch (final Exception e) 8192 { 8193 Debug.debugException(e); 8194 wrapErr(0, WRAP_COLUMN, 8195 ERR_MANAGE_CERTS_CHECK_USABILITY_CANNOT_GET_CHAIN.get(alias)); 8196 e.printStackTrace(getErr()); 8197 return ResultCode.LOCAL_ERROR; 8198 } 8199 } 8200 else if (hasCertificateAlias(keystore, alias)) 8201 { 8202 wrapErr(0, WRAP_COLUMN, 8203 ERR_MANAGE_CERTS_CHECK_USABILITY_NO_PRIVATE_KEY.get(alias)); 8204 return ResultCode.PARAM_ERROR; 8205 } 8206 else 8207 { 8208 wrapErr(0, WRAP_COLUMN, 8209 ERR_MANAGE_CERTS_CHECK_USABILITY_NO_SUCH_ALIAS.get(alias)); 8210 return ResultCode.PARAM_ERROR; 8211 } 8212 8213 8214 // Check to see if the certificate is self-signed. If so, then that's a 8215 // warning. If not, then make sure that the chain is complete and that each 8216 // subsequent certificate is the issuer of the previous. 8217 int numWarnings = 0; 8218 int numErrors = 0; 8219 if (chain[0].isSelfSigned()) 8220 { 8221 err(); 8222 wrapErr(0, WRAP_COLUMN, 8223 WARN_MANAGE_CERTS_CHECK_USABILITY_CERT_IS_SELF_SIGNED.get( 8224 chain[0].getSubjectDN())); 8225 numWarnings++; 8226 } 8227 else if ((chain.length == 1) || (! chain[chain.length - 1].isSelfSigned())) 8228 { 8229 err(); 8230 wrapErr(0, WRAP_COLUMN, 8231 ERR_MANAGE_CERTS_CHECK_USABILITY_END_OF_CHAIN_NOT_SELF_SIGNED.get( 8232 alias)); 8233 numErrors++; 8234 } 8235 else 8236 { 8237 boolean chainError = false; 8238 final StringBuilder nonMatchReason = new StringBuilder(); 8239 for (int i=1; i < chain.length; i++) 8240 { 8241 if (! chain[i].isIssuerFor(chain[i-1], nonMatchReason)) 8242 { 8243 err(); 8244 wrapErr(0, WRAP_COLUMN, 8245 ERR_MANAGE_CERTS_CHECK_USABILITY_CHAIN_ISSUER_MISMATCH.get( 8246 alias, chain[i].getSubjectDN(), chain[i-1].getSubjectDN(), 8247 nonMatchReason)); 8248 numErrors++; 8249 chainError = true; 8250 } 8251 } 8252 8253 if (! chainError) 8254 { 8255 out(); 8256 wrapOut(0, WRAP_COLUMN, 8257 INFO_MANAGE_CERTS_CHECK_USABILITY_CHAIN_COMPLETE.get()); 8258 } 8259 } 8260 8261 8262 // Make sure that the signature is valid for each certificate in the 8263 // chain. If any certificate has an invalid signature, then that's an 8264 // error. 8265 for (int i=0; i < chain.length; i++) 8266 { 8267 final X509Certificate c = chain[i]; 8268 8269 try 8270 { 8271 if (c.isSelfSigned()) 8272 { 8273 c.verifySignature(null); 8274 } 8275 else if ((i + 1) < chain.length) 8276 { 8277 c.verifySignature(chain[i+1]); 8278 } 8279 8280 out(); 8281 wrapOut(0, WRAP_COLUMN, 8282 INFO_MANAGE_CERTS_CHECK_USABILITY_CERT_SIGNATURE_VALID.get( 8283 c.getSubjectDN())); 8284 } 8285 catch (final CertException ce) 8286 { 8287 err(); 8288 wrapErr(0, WRAP_COLUMN, ce.getMessage()); 8289 numErrors++; 8290 } 8291 } 8292 8293 8294 // Check the validity window for each certificate in the chain. If any of 8295 // them is expired or not yet valid, then that's an error. If any of them 8296 // will expire in the near future, then that's a warning. 8297 final long currentTime = System.currentTimeMillis(); 8298 final long thirtyDaysFromNow = 8299 currentTime + (30L * 24L * 60L * 60L * 1000L); 8300 for (int i=0; i < chain.length; i++) 8301 { 8302 final X509Certificate c = chain[i]; 8303 if (c.getNotBeforeTime() > currentTime) 8304 { 8305 err(); 8306 if (i == 0) 8307 { 8308 wrapErr(0, WRAP_COLUMN, 8309 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_NOT_YET_VALID.get( 8310 c.getSubjectDN(), formatDateAndTime(c.getNotBeforeDate()))); 8311 } 8312 else 8313 { 8314 wrapErr(0, WRAP_COLUMN, 8315 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_NOT_YET_VALID.get( 8316 c.getSubjectDN(), formatDateAndTime(c.getNotBeforeDate()))); 8317 } 8318 8319 numErrors++; 8320 } 8321 else if (c.getNotAfterTime() < currentTime) 8322 { 8323 err(); 8324 if (i == 0) 8325 { 8326 wrapErr(0, WRAP_COLUMN, 8327 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_EXPIRED.get( 8328 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 8329 } 8330 else 8331 { 8332 wrapErr(0, WRAP_COLUMN, 8333 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_EXPIRED.get( 8334 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 8335 } 8336 8337 numErrors++; 8338 } 8339 else if (c.getNotAfterTime() < thirtyDaysFromNow) 8340 { 8341 err(); 8342 if (i == 0) 8343 { 8344 wrapErr(0, WRAP_COLUMN, 8345 WARN_MANAGE_CERTS_CHECK_USABILITY_END_CERT_NEAR_EXPIRATION.get( 8346 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 8347 } 8348 else 8349 { 8350 wrapErr(0, WRAP_COLUMN, 8351 WARN_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_NEAR_EXPIRATION. 8352 get(c.getSubjectDN(), 8353 formatDateAndTime(c.getNotAfterDate()))); 8354 } 8355 8356 numWarnings++; 8357 } 8358 else 8359 { 8360 if (i == 0) 8361 { 8362 out(); 8363 wrapOut(0, WRAP_COLUMN, 8364 INFO_MANAGE_CERTS_CHECK_USABILITY_END_CERT_VALIDITY_OK.get( 8365 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 8366 } 8367 else 8368 { 8369 out(); 8370 wrapOut(0, WRAP_COLUMN, 8371 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_VALIDITY_OK.get( 8372 c.getSubjectDN(), formatDateAndTime(c.getNotAfterDate()))); 8373 } 8374 } 8375 } 8376 8377 8378 // Look at all of the extensions for all of the certificates and perform the 8379 // following validation: 8380 // - If the certificate at the head of the chain has an extended key usage 8381 // extension, then make sure it includes the serverAuth usage. If it 8382 // does not include an extended key usage extension, then warn that it 8383 // should. 8384 // - If any of the issuer certificates has a basic constraints extension, 8385 // then make sure it indicates that the associated certificate is a 8386 // certification authority. Further, if it has a path length constraint, 8387 // then make sure the chain does not exceed that length. If any issuer 8388 // certificate does not have a basic constraints extension, then warn that 8389 // it should. 8390 // - If any of the issuer certificates has a key usage extension, then 8391 // make sure it has the certSign usage. If any issuer certificate does 8392 // not have a key usage extension, then warn that it should. 8393 // - TODO: If any certificate has a CRL distribution points extension, then 8394 // retrieve the CRL and make sure the certificate hasn't been revoked. 8395 // - TODO: If any certificate has an authority information access 8396 // extension that points to an OCSP service, then consult that service to 8397 // determine whether the certificate has been revoked. 8398 for (int i=0; i < chain.length; i++) 8399 { 8400 boolean basicConstraintsFound = false; 8401 boolean extendedKeyUsageFound = false; 8402 boolean keyUsageFound = false; 8403 final X509Certificate c = chain[i]; 8404 for (final X509CertificateExtension extension : c.getExtensions()) 8405 { 8406 if (extension instanceof ExtendedKeyUsageExtension) 8407 { 8408 extendedKeyUsageFound = true; 8409 if (i == 0) 8410 { 8411 final ExtendedKeyUsageExtension e = 8412 (ExtendedKeyUsageExtension) extension; 8413 if (!e.getKeyPurposeIDs().contains( 8414 ExtendedKeyUsageID.TLS_SERVER_AUTHENTICATION.getOID())) 8415 { 8416 err(); 8417 wrapErr(0, WRAP_COLUMN, 8418 ERR_MANAGE_CERTS_CHECK_USABILITY_END_CERT_BAD_EKU.get( 8419 c.getSubjectDN())); 8420 numErrors++; 8421 } 8422 else 8423 { 8424 out(); 8425 wrapOut(0, WRAP_COLUMN, 8426 INFO_MANAGE_CERTS_CHECK_USABILITY_END_CERT_GOOD_EKU.get( 8427 c.getSubjectDN())); 8428 } 8429 } 8430 } 8431 else if (extension instanceof BasicConstraintsExtension) 8432 { 8433 basicConstraintsFound = true; 8434 if (i > 0) 8435 { 8436 final BasicConstraintsExtension e = 8437 (BasicConstraintsExtension) extension; 8438 if (!e.isCA()) 8439 { 8440 err(); 8441 wrapErr(0, WRAP_COLUMN, 8442 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_BAD_BC_CA.get( 8443 c.getSubjectDN())); 8444 numErrors++; 8445 } 8446 else if ((e.getPathLengthConstraint() != null) && 8447 ((i - 1) > e.getPathLengthConstraint())) 8448 { 8449 err(); 8450 wrapErr(0, WRAP_COLUMN, 8451 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_BAD_BC_LENGTH. 8452 get(c.getSubjectDN(), e.getPathLengthConstraint(), 8453 chain[0].getSubjectDN(), (i-1))); 8454 numErrors++; 8455 } 8456 else 8457 { 8458 out(); 8459 wrapOut(0, WRAP_COLUMN, 8460 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_CERT_GOOD_BC.get( 8461 c.getSubjectDN())); 8462 } 8463 } 8464 } 8465 else if (extension instanceof KeyUsageExtension) 8466 { 8467 keyUsageFound = true; 8468 if (i > 0) 8469 { 8470 final KeyUsageExtension e = (KeyUsageExtension) extension; 8471 if (! e.isKeyCertSignBitSet()) 8472 { 8473 err(); 8474 wrapErr(0, WRAP_COLUMN, 8475 ERR_MANAGE_CERTS_CHECK_USABILITY_ISSUER_NO_CERT_SIGN_KU.get( 8476 c.getSubjectDN())); 8477 numErrors++; 8478 } 8479 else 8480 { 8481 out(); 8482 wrapOut(0, WRAP_COLUMN, 8483 INFO_MANAGE_CERTS_CHECK_USABILITY_ISSUER_GOOD_KU.get( 8484 c.getSubjectDN())); 8485 } 8486 } 8487 } 8488 } 8489 8490 if (i == 0) 8491 { 8492 if (! extendedKeyUsageFound) 8493 { 8494 err(); 8495 wrapErr(0, WRAP_COLUMN, 8496 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_EKU.get( 8497 c.getSubjectDN())); 8498 numWarnings++; 8499 } 8500 } 8501 else 8502 { 8503 if (! basicConstraintsFound) 8504 { 8505 err(); 8506 wrapErr(0, WRAP_COLUMN, 8507 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_BC.get( 8508 c.getSubjectDN())); 8509 numWarnings++; 8510 } 8511 8512 if (! keyUsageFound) 8513 { 8514 err(); 8515 wrapErr(0, WRAP_COLUMN, 8516 WARN_MANAGE_CERTS_CHECK_USABILITY_NO_KU.get( 8517 c.getSubjectDN())); 8518 numWarnings++; 8519 } 8520 } 8521 } 8522 8523 8524 // Make sure that none of the certificates has a signature algorithm that 8525 // uses MD5 or SHA-1. If it uses an unrecognized signature algorithm, then 8526 // that's a warning. 8527 boolean isIssuer = false; 8528 final BooleanArgument ignoreSHA1WarningArg = 8529 subCommandParser.getBooleanArgument( 8530 "allow-sha-1-signature-for-issuer-certificates"); 8531 final boolean ignoreSHA1SignatureWarningForIssuerCertificates = 8532 ((ignoreSHA1WarningArg != null) && ignoreSHA1WarningArg.isPresent()); 8533 for (final X509Certificate c : chain) 8534 { 8535 final OID signatureAlgorithmOID = c.getSignatureAlgorithmOID(); 8536 final SignatureAlgorithmIdentifier id = 8537 SignatureAlgorithmIdentifier.forOID(signatureAlgorithmOID); 8538 if (id == null) 8539 { 8540 err(); 8541 wrapErr(0, WRAP_COLUMN, 8542 WARN_MANAGE_CERTS_CHECK_USABILITY_UNKNOWN_SIG_ALG.get( 8543 c.getSubjectDN(), signatureAlgorithmOID)); 8544 numWarnings++; 8545 } 8546 else 8547 { 8548 switch (id) 8549 { 8550 case MD2_WITH_RSA: 8551 case MD5_WITH_RSA: 8552 err(); 8553 wrapErr(0, WRAP_COLUMN, 8554 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_SIG_ALG.get( 8555 c.getSubjectDN(), id.getUserFriendlyName())); 8556 numErrors++; 8557 break; 8558 8559 case SHA_1_WITH_RSA: 8560 case SHA_1_WITH_DSA: 8561 case SHA_1_WITH_ECDSA: 8562 if (isIssuer && ignoreSHA1SignatureWarningForIssuerCertificates) 8563 { 8564 err(); 8565 wrapErr(0, WRAP_COLUMN, 8566 WARN_MANAGE_CERTS_CHECK_USABILITY_ISSUER_WITH_SHA1_SIG.get( 8567 c.getSubjectDN(), id.getUserFriendlyName(), 8568 ignoreSHA1WarningArg.getIdentifierString())); 8569 } 8570 else 8571 { 8572 err(); 8573 wrapErr(0, WRAP_COLUMN, 8574 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_SIG_ALG.get( 8575 c.getSubjectDN(), id.getUserFriendlyName())); 8576 numErrors++; 8577 } 8578 break; 8579 8580 case SHA_224_WITH_RSA: 8581 case SHA_224_WITH_DSA: 8582 case SHA_224_WITH_ECDSA: 8583 case SHA_256_WITH_RSA: 8584 case SHA_256_WITH_DSA: 8585 case SHA_256_WITH_ECDSA: 8586 case SHA_384_WITH_RSA: 8587 case SHA_384_WITH_ECDSA: 8588 case SHA_512_WITH_RSA: 8589 case SHA_512_WITH_ECDSA: 8590 out(); 8591 wrapOut(0, WRAP_COLUMN, 8592 INFO_MANAGE_CERTS_CHECK_USABILITY_SIG_ALG_OK.get( 8593 c.getSubjectDN(), id.getUserFriendlyName())); 8594 break; 8595 } 8596 } 8597 8598 isIssuer = true; 8599 } 8600 8601 8602 // Make sure that none of the certificates that uses the RSA key algorithm 8603 // has a public modulus size smaller than 2048 bits. 8604 for (final X509Certificate c : chain) 8605 { 8606 if ((c.getDecodedPublicKey() != null) && 8607 (c.getDecodedPublicKey() instanceof RSAPublicKey)) 8608 { 8609 final RSAPublicKey rsaPublicKey = 8610 (RSAPublicKey) c.getDecodedPublicKey(); 8611 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 8612 int modulusSizeBits = modulusBytes.length * 8; 8613 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 8614 { 8615 modulusSizeBits -= 8; 8616 } 8617 8618 if (modulusSizeBits < 2048) 8619 { 8620 err(); 8621 wrapErr(0, WRAP_COLUMN, 8622 ERR_MANAGE_CERTS_CHECK_USABILITY_WEAK_RSA_MODULUS.get( 8623 c.getSubjectDN(), modulusSizeBits)); 8624 numErrors++; 8625 } 8626 else 8627 { 8628 out(); 8629 wrapOut(0, WRAP_COLUMN, 8630 INFO_MANAGE_CERTS_CHECK_USABILITY_RSA_MODULUS_OK.get( 8631 c.getSubjectDN(), modulusSizeBits)); 8632 } 8633 } 8634 } 8635 8636 8637 switch (numErrors) 8638 { 8639 case 0: 8640 break; 8641 case 1: 8642 err(); 8643 wrapErr(0, WRAP_COLUMN, 8644 ERR_MANAGE_CERTS_CHECK_USABILITY_ONE_ERROR.get()); 8645 return ResultCode.PARAM_ERROR; 8646 default: 8647 err(); 8648 wrapErr(0, WRAP_COLUMN, 8649 ERR_MANAGE_CERTS_CHECK_USABILITY_MULTIPLE_ERRORS.get(numErrors)); 8650 return ResultCode.PARAM_ERROR; 8651 } 8652 8653 switch (numWarnings) 8654 { 8655 case 0: 8656 out(); 8657 wrapOut(0, WRAP_COLUMN, 8658 INFO_MANAGE_CERTS_CHECK_USABILITY_NO_ERRORS_OR_WARNINGS.get()); 8659 return ResultCode.SUCCESS; 8660 case 1: 8661 err(); 8662 wrapErr(0, WRAP_COLUMN, 8663 ERR_MANAGE_CERTS_CHECK_USABILITY_ONE_WARNING.get()); 8664 return ResultCode.PARAM_ERROR; 8665 default: 8666 err(); 8667 wrapErr(0, WRAP_COLUMN, 8668 ERR_MANAGE_CERTS_CHECK_USABILITY_MULTIPLE_WARNINGS.get( 8669 numWarnings)); 8670 return ResultCode.PARAM_ERROR; 8671 } 8672 } 8673 8674 8675 8676 /** 8677 * Performs the necessary processing for the display-certificate-file 8678 * subcommand. 8679 * 8680 * @return A result code that indicates whether the processing completed 8681 * successfully. 8682 */ 8683 private ResultCode doDisplayCertificateFile() 8684 { 8685 // Get the values of a number of configured arguments. 8686 final FileArgument certificateFileArgument = 8687 subCommandParser.getFileArgument("certificate-file"); 8688 final File certificateFile = certificateFileArgument.getValue(); 8689 8690 final BooleanArgument verboseArgument = 8691 subCommandParser.getBooleanArgument("verbose"); 8692 final boolean verbose = 8693 ((verboseArgument != null) && verboseArgument.isPresent()); 8694 8695 final BooleanArgument displayKeytoolCommandArgument = 8696 subCommandParser.getBooleanArgument("display-keytool-command"); 8697 if ((displayKeytoolCommandArgument != null) && 8698 displayKeytoolCommandArgument.isPresent()) 8699 { 8700 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 8701 keytoolArgs.add("-printcert"); 8702 keytoolArgs.add("-file"); 8703 keytoolArgs.add(certificateFile.getAbsolutePath()); 8704 8705 if (verbose) 8706 { 8707 keytoolArgs.add("-v"); 8708 } 8709 8710 displayKeytoolCommand(keytoolArgs); 8711 } 8712 8713 8714 // Read the certificates from the specified file. 8715 final List<X509Certificate> certificates; 8716 try 8717 { 8718 certificates = readCertificatesFromFile(certificateFile); 8719 } 8720 catch (final LDAPException le) 8721 { 8722 Debug.debugException(le); 8723 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8724 return le.getResultCode(); 8725 } 8726 8727 8728 // If there aren't any certificates in the file, print that. 8729 if (certificates.isEmpty()) 8730 { 8731 wrapOut(0, WRAP_COLUMN, INFO_MANAGE_CERTS_DISPLAY_CERT_NO_CERTS.get( 8732 certificateFile.getAbsolutePath())); 8733 } 8734 else 8735 { 8736 for (final X509Certificate c : certificates) 8737 { 8738 out(); 8739 printCertificate(c, "", verbose); 8740 } 8741 } 8742 8743 return ResultCode.SUCCESS; 8744 } 8745 8746 8747 8748 /** 8749 * Performs the necessary processing for the 8750 * display-certificate-signing-request-file subcommand. 8751 * 8752 * @return A result code that indicates whether the processing completed 8753 * successfully. 8754 */ 8755 private ResultCode doDisplayCertificateSigningRequestFile() 8756 { 8757 // Get the values of a number of configured arguments. 8758 final FileArgument csrFileArgument = 8759 subCommandParser.getFileArgument("certificate-signing-request-file"); 8760 final File csrFile = csrFileArgument.getValue(); 8761 8762 final BooleanArgument verboseArgument = 8763 subCommandParser.getBooleanArgument("verbose"); 8764 final boolean verbose = 8765 ((verboseArgument != null) && verboseArgument.isPresent()); 8766 8767 final BooleanArgument displayKeytoolCommandArgument = 8768 subCommandParser.getBooleanArgument("display-keytool-command"); 8769 if ((displayKeytoolCommandArgument != null) && 8770 displayKeytoolCommandArgument.isPresent()) 8771 { 8772 final ArrayList<String> keytoolArgs = new ArrayList<>(10); 8773 keytoolArgs.add("-printcertreq"); 8774 keytoolArgs.add("-file"); 8775 keytoolArgs.add(csrFile.getAbsolutePath()); 8776 keytoolArgs.add("-v"); 8777 8778 displayKeytoolCommand(keytoolArgs); 8779 } 8780 8781 8782 // Read the certificate signing request from the specified file. 8783 final PKCS10CertificateSigningRequest csr; 8784 try 8785 { 8786 csr = readCertificateSigningRequestFromFile(csrFile); 8787 } 8788 catch (final LDAPException le) 8789 { 8790 Debug.debugException(le); 8791 wrapErr(0, WRAP_COLUMN, le.getMessage()); 8792 return le.getResultCode(); 8793 } 8794 8795 out(); 8796 printCertificateSigningRequest(csr, verbose, ""); 8797 8798 return ResultCode.SUCCESS; 8799 } 8800 8801 8802 8803 /** 8804 * Prints a string representation of the provided certificate to standard 8805 * output. 8806 * 8807 * @param certificate The certificate to be printed. 8808 * @param indent The string to place at the beginning of each line to 8809 * indent that line. 8810 * @param verbose Indicates whether to display verbose information about 8811 * the certificate. 8812 */ 8813 private void printCertificate(final X509Certificate certificate, 8814 final String indent, final boolean verbose) 8815 { 8816 if (verbose) 8817 { 8818 out(indent + 8819 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VERSION.get( 8820 certificate.getVersion().getName())); 8821 } 8822 8823 out(indent + 8824 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_DN.get( 8825 certificate.getSubjectDN())); 8826 out(indent + 8827 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ISSUER_DN.get( 8828 certificate.getIssuerDN())); 8829 8830 if (verbose) 8831 { 8832 out(indent + 8833 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SERIAL_NUMBER.get( 8834 toColonDelimitedHex( 8835 certificate.getSerialNumber().toByteArray()))); 8836 } 8837 8838 out(indent + 8839 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_START.get( 8840 formatDateAndTime(certificate.getNotBeforeDate()))); 8841 out(indent + 8842 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_END.get( 8843 formatDateAndTime(certificate.getNotAfterDate()))); 8844 8845 final long currentTime = System.currentTimeMillis(); 8846 if (currentTime < certificate.getNotBeforeTime()) 8847 { 8848 out(indent + 8849 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_NOT_YET_VALID. 8850 get()); 8851 } 8852 else if (currentTime > certificate.getNotAfterTime()) 8853 { 8854 out(indent + 8855 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_EXPIRED.get()); 8856 } 8857 else 8858 { 8859 out(indent + 8860 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_VALIDITY_STATE_VALID.get()); 8861 } 8862 8863 out(indent + 8864 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_ALG.get( 8865 certificate.getSignatureAlgorithmNameOrOID())); 8866 if (verbose) 8867 { 8868 String signatureString; 8869 try 8870 { 8871 signatureString = 8872 toColonDelimitedHex(certificate.getSignatureValue().getBytes()); 8873 } 8874 catch (final Exception e) 8875 { 8876 Debug.debugException(e); 8877 signatureString = certificate.getSignatureValue().toString(); 8878 } 8879 out(indent + 8880 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_VALUE.get()); 8881 for (final String line : StaticUtils.wrapLine(signatureString, 78)) 8882 { 8883 out(indent + " " + line); 8884 } 8885 } 8886 8887 final String pkAlg; 8888 final String pkSummary = getPublicKeySummary( 8889 certificate.getPublicKeyAlgorithmOID(), 8890 certificate.getDecodedPublicKey(), 8891 certificate.getPublicKeyAlgorithmParameters()); 8892 if (pkSummary == null) 8893 { 8894 pkAlg = certificate.getPublicKeyAlgorithmNameOrOID(); 8895 } 8896 else 8897 { 8898 pkAlg = certificate.getPublicKeyAlgorithmNameOrOID() + " (" + 8899 pkSummary + ')'; 8900 } 8901 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_PK_ALG.get(pkAlg)); 8902 8903 if (verbose) 8904 { 8905 printPublicKey(certificate.getEncodedPublicKey(), 8906 certificate.getDecodedPublicKey(), 8907 certificate.getPublicKeyAlgorithmParameters(), indent); 8908 8909 if (certificate.getSubjectUniqueID() != null) 8910 { 8911 String subjectUniqueID; 8912 try 8913 { 8914 subjectUniqueID = toColonDelimitedHex( 8915 certificate.getSubjectUniqueID().getBytes()); 8916 } 8917 catch (final Exception e) 8918 { 8919 Debug.debugException(e); 8920 subjectUniqueID = certificate.getSubjectUniqueID().toString(); 8921 } 8922 8923 out(indent + 8924 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_UNIQUE_ID.get()); 8925 for (final String line : StaticUtils.wrapLine(subjectUniqueID, 78)) 8926 { 8927 out(indent + " " + line); 8928 } 8929 } 8930 8931 if (certificate.getIssuerUniqueID() != null) 8932 { 8933 String issuerUniqueID; 8934 try 8935 { 8936 issuerUniqueID = toColonDelimitedHex( 8937 certificate.getIssuerUniqueID().getBytes()); 8938 } 8939 catch (final Exception e) 8940 { 8941 Debug.debugException(e); 8942 issuerUniqueID = certificate.getIssuerUniqueID().toString(); 8943 } 8944 8945 out(indent + 8946 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ISSUER_UNIQUE_ID.get()); 8947 for (final String line : StaticUtils.wrapLine(issuerUniqueID, 78)) 8948 { 8949 out(indent + " " + line); 8950 } 8951 } 8952 8953 printExtensions(certificate.getExtensions(), indent); 8954 } 8955 8956 try 8957 { 8958 out(indent + 8959 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_FINGERPRINT.get("SHA-1", 8960 toColonDelimitedHex(certificate.getSHA1Fingerprint()))); 8961 } 8962 catch (final Exception e) 8963 { 8964 Debug.debugException(e); 8965 } 8966 8967 try 8968 { 8969 out(indent + 8970 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_FINGERPRINT.get("SHA-256", 8971 toColonDelimitedHex(certificate.getSHA256Fingerprint()))); 8972 } 8973 catch (final Exception e) 8974 { 8975 Debug.debugException(e); 8976 } 8977 } 8978 8979 8980 8981 /** 8982 * Prints a string representation of the provided certificate signing request 8983 * to standard output. 8984 * 8985 * @param csr The certificate signing request to be printed. 8986 * @param verbose Indicates whether to display verbose information about 8987 * the contents of the request. 8988 * @param indent The string to place at the beginning of each line to 8989 * indent that line. 8990 */ 8991 private void printCertificateSigningRequest( 8992 final PKCS10CertificateSigningRequest csr, 8993 final boolean verbose, final String indent) 8994 { 8995 out(indent + 8996 INFO_MANAGE_CERTS_PRINT_CSR_LABEL_VERSION.get( 8997 csr.getVersion().getName())); 8998 out(indent + 8999 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SUBJECT_DN.get( 9000 csr.getSubjectDN())); 9001 out(indent + 9002 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_ALG.get( 9003 csr.getSignatureAlgorithmNameOrOID())); 9004 9005 if (verbose) 9006 { 9007 String signatureString; 9008 try 9009 { 9010 signatureString = 9011 toColonDelimitedHex(csr.getSignatureValue().getBytes()); 9012 } 9013 catch (final Exception e) 9014 { 9015 Debug.debugException(e); 9016 signatureString = csr.getSignatureValue().toString(); 9017 } 9018 out(indent + 9019 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_SIG_VALUE.get()); 9020 for (final String line : StaticUtils.wrapLine(signatureString, 78)) 9021 { 9022 out(indent + " " + line); 9023 } 9024 } 9025 9026 final String pkAlg; 9027 final String pkSummary = getPublicKeySummary(csr.getPublicKeyAlgorithmOID(), 9028 csr.getDecodedPublicKey(), csr.getPublicKeyAlgorithmParameters()); 9029 if (pkSummary == null) 9030 { 9031 pkAlg = csr.getPublicKeyAlgorithmNameOrOID(); 9032 } 9033 else 9034 { 9035 pkAlg = csr.getPublicKeyAlgorithmNameOrOID() + " (" + 9036 pkSummary + ')'; 9037 } 9038 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_PK_ALG.get(pkAlg)); 9039 9040 if (verbose) 9041 { 9042 printPublicKey(csr.getEncodedPublicKey(), csr.getDecodedPublicKey(), 9043 csr.getPublicKeyAlgorithmParameters(), indent); 9044 printExtensions(csr.getExtensions(), indent); 9045 } 9046 } 9047 9048 9049 9050 /** 9051 * Prints information about the provided public key. 9052 * 9053 * @param encodedPublicKey The encoded representation of the public key. 9054 * This must not be {@code null}. 9055 * @param decodedPublicKey The decoded representation of the public key, if 9056 * available. 9057 * @param parameters The public key algorithm parameters, if any. 9058 * @param indent The string to place at the beginning of each 9059 * line to indent that line. 9060 */ 9061 private void printPublicKey(final ASN1BitString encodedPublicKey, 9062 final DecodedPublicKey decodedPublicKey, 9063 final ASN1Element parameters, 9064 final String indent) 9065 { 9066 if (decodedPublicKey == null) 9067 { 9068 String pkString; 9069 try 9070 { 9071 pkString = toColonDelimitedHex(encodedPublicKey.getBytes()); 9072 } 9073 catch (final Exception e) 9074 { 9075 Debug.debugException(e); 9076 pkString = encodedPublicKey.toString(); 9077 } 9078 9079 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_ENCODED_PK.get()); 9080 for (final String line : StaticUtils.wrapLine(pkString, 78)) 9081 { 9082 out(indent + " " + line); 9083 } 9084 9085 return; 9086 } 9087 9088 if (decodedPublicKey instanceof RSAPublicKey) 9089 { 9090 final RSAPublicKey rsaPublicKey = (RSAPublicKey) decodedPublicKey; 9091 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 9092 9093 int modulusSizeBits = modulusBytes.length * 8; 9094 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 9095 { 9096 modulusSizeBits -= 8; 9097 } 9098 9099 out(indent + 9100 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_RSA_MODULUS.get( 9101 modulusSizeBits)); 9102 final String modulusHex = toColonDelimitedHex(modulusBytes); 9103 for (final String line : StaticUtils.wrapLine(modulusHex, 78)) 9104 { 9105 out(indent + " " + line); 9106 } 9107 9108 out(indent + 9109 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_RSA_EXPONENT.get( 9110 toColonDelimitedHex( 9111 rsaPublicKey.getPublicExponent().toByteArray()))); 9112 } 9113 else if (decodedPublicKey instanceof EllipticCurvePublicKey) 9114 { 9115 final EllipticCurvePublicKey ecPublicKey = 9116 (EllipticCurvePublicKey) decodedPublicKey; 9117 9118 out(indent + 9119 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_IS_COMPRESSED.get( 9120 String.valueOf(ecPublicKey.usesCompressedForm()))); 9121 out(indent + 9122 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_X.get( 9123 String.valueOf(ecPublicKey.getXCoordinate()))); 9124 if (ecPublicKey.getYCoordinate() == null) 9125 { 9126 out(indent + 9127 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_Y_IS_EVEN.get( 9128 String.valueOf(ecPublicKey.yCoordinateIsEven()))); 9129 } 9130 else 9131 { 9132 out(indent + 9133 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EC_Y.get( 9134 String.valueOf(ecPublicKey.getYCoordinate()))); 9135 } 9136 } 9137 } 9138 9139 9140 9141 /** 9142 * Retrieves a short summary of the provided public key, if available. For 9143 * RSA keys, this will be the modulus size in bits. For elliptic curve keys, 9144 * this will be the named curve, if available. 9145 * 9146 * @param publicKeyAlgorithmOID The OID that identifies the type of public 9147 * key. 9148 * @param publicKey The decoded public key. This may be 9149 * {@code null} if the decoded public key is 9150 * not available. 9151 * @param parameters The encoded public key algorithm parameters. 9152 * This may be {@code null} if no public key 9153 * algorithm parameters are available. 9154 * 9155 * @return A short summary of the provided public key, or {@code null} if 9156 * no summary is available. 9157 */ 9158 private static String getPublicKeySummary(final OID publicKeyAlgorithmOID, 9159 final DecodedPublicKey publicKey, 9160 final ASN1Element parameters) 9161 { 9162 if (publicKey instanceof RSAPublicKey) 9163 { 9164 final RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; 9165 final byte[] modulusBytes = rsaPublicKey.getModulus().toByteArray(); 9166 9167 int modulusSizeBits = modulusBytes.length * 8; 9168 if (((modulusBytes.length % 2) != 0) && (modulusBytes[0] == 0x00)) 9169 { 9170 modulusSizeBits -= 8; 9171 } 9172 9173 return INFO_MANAGE_CERTS_GET_PK_SUMMARY_RSA_MODULUS_SIZE.get( 9174 modulusSizeBits); 9175 } 9176 else if ((parameters != null) && 9177 publicKeyAlgorithmOID.equals(PublicKeyAlgorithmIdentifier.EC.getOID())) 9178 { 9179 try 9180 { 9181 final OID namedCurveOID = 9182 parameters.decodeAsObjectIdentifier().getOID(); 9183 return NamedCurve.getNameOrOID(namedCurveOID); 9184 } 9185 catch (final Exception e) 9186 { 9187 Debug.debugException(e); 9188 } 9189 } 9190 9191 return null; 9192 } 9193 9194 9195 9196 /** 9197 * Prints information about the provided extensions. 9198 * 9199 * @param extensions The list of extensions to be printed. 9200 * @param indent The string to place at the beginning of each line to 9201 * indent that line. 9202 */ 9203 void printExtensions(final List<X509CertificateExtension> extensions, 9204 final String indent) 9205 { 9206 if (extensions.isEmpty()) 9207 { 9208 return; 9209 } 9210 9211 out(indent + INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXTENSIONS.get()); 9212 for (final X509CertificateExtension extension : extensions) 9213 { 9214 if (extension instanceof AuthorityKeyIdentifierExtension) 9215 { 9216 out(indent + " " + 9217 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_EXT.get()); 9218 out(indent + " " + 9219 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9220 extension.getOID().toString())); 9221 out(indent + " " + 9222 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9223 String.valueOf(extension.isCritical()))); 9224 9225 final AuthorityKeyIdentifierExtension e = 9226 (AuthorityKeyIdentifierExtension) extension; 9227 if (e.getKeyIdentifier() != null) 9228 { 9229 out(indent + " " + 9230 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_ID.get()); 9231 final String idHex = 9232 toColonDelimitedHex(e.getKeyIdentifier().getValue()); 9233 for (final String line : StaticUtils.wrapLine(idHex, 78)) 9234 { 9235 out(indent + " " + line); 9236 } 9237 } 9238 9239 if (e.getAuthorityCertIssuer() != null) 9240 { 9241 out(indent + " " + 9242 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_ISSUER. 9243 get()); 9244 printGeneralNames(e.getAuthorityCertIssuer(), 9245 indent + " "); 9246 } 9247 9248 if (e.getAuthorityCertSerialNumber() != null) 9249 { 9250 out(indent + " " + 9251 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_AUTH_KEY_ID_SERIAL.get( 9252 toColonDelimitedHex(e.getAuthorityCertSerialNumber(). 9253 toByteArray()))); 9254 } 9255 } 9256 else if (extension instanceof BasicConstraintsExtension) 9257 { 9258 out(indent + " " + 9259 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_EXT.get()); 9260 out(indent + " " + 9261 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9262 extension.getOID().toString())); 9263 out(indent + " " + 9264 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9265 String.valueOf(extension.isCritical()))); 9266 9267 final BasicConstraintsExtension e = 9268 (BasicConstraintsExtension) extension; 9269 out(indent + " " + 9270 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_IS_CA.get( 9271 String.valueOf(e.isCA()))); 9272 9273 if (e.getPathLengthConstraint() != null) 9274 { 9275 out(indent + " " + 9276 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_BASIC_CONST_LENGTH.get( 9277 e.getPathLengthConstraint())); 9278 } 9279 } 9280 else if (extension instanceof CRLDistributionPointsExtension) 9281 { 9282 out(indent + " " + 9283 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_EXT.get()); 9284 out(indent + " " + 9285 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9286 extension.getOID().toString())); 9287 out(indent + " " + 9288 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9289 String.valueOf(extension.isCritical()))); 9290 9291 final CRLDistributionPointsExtension crlDPE = 9292 (CRLDistributionPointsExtension) extension; 9293 for (final CRLDistributionPoint dp : 9294 crlDPE.getCRLDistributionPoints()) 9295 { 9296 out(indent + " " + 9297 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_HEADER.get()); 9298 if (dp.getFullName() != null) 9299 { 9300 out(indent + " " + 9301 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_FULL_NAME. 9302 get()); 9303 printGeneralNames(dp.getFullName(), 9304 indent + " "); 9305 } 9306 9307 if (dp.getNameRelativeToCRLIssuer() != null) 9308 { 9309 out(indent + " " + 9310 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_REL_NAME.get( 9311 dp.getNameRelativeToCRLIssuer())); 9312 } 9313 9314 if (! dp.getPotentialRevocationReasons().isEmpty()) 9315 { 9316 out(indent + " " + 9317 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_REASON.get()); 9318 for (final CRLDistributionPointRevocationReason r : 9319 dp.getPotentialRevocationReasons()) 9320 { 9321 out(indent + " " + r.getName()); 9322 } 9323 } 9324 9325 if (dp.getCRLIssuer() != null) 9326 { 9327 out(indent + " " + 9328 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_CRL_DP_CRL_ISSUER. 9329 get()); 9330 printGeneralNames(dp.getCRLIssuer(), 9331 indent + " "); 9332 } 9333 } 9334 } 9335 else if (extension instanceof ExtendedKeyUsageExtension) 9336 { 9337 out(indent + " " + 9338 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_EXT.get()); 9339 out(indent + " " + 9340 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9341 extension.getOID().toString())); 9342 out(indent + " " + 9343 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9344 String.valueOf(extension.isCritical()))); 9345 9346 final ExtendedKeyUsageExtension e = 9347 (ExtendedKeyUsageExtension) extension; 9348 for (final OID oid : e.getKeyPurposeIDs()) 9349 { 9350 final ExtendedKeyUsageID id = ExtendedKeyUsageID.forOID(oid); 9351 if (id == null) 9352 { 9353 out(indent + " " + 9354 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_ID.get(oid)); 9355 } 9356 else 9357 { 9358 out(indent + " " + 9359 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_EKU_ID.get( 9360 id.getName())); 9361 } 9362 } 9363 } 9364 else if (extension instanceof IssuerAlternativeNameExtension) 9365 { 9366 out(indent + " " + 9367 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IAN_EXT.get()); 9368 out(indent + " " + 9369 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9370 extension.getOID().toString())); 9371 out(indent + " " + 9372 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9373 String.valueOf(extension.isCritical()))); 9374 9375 final IssuerAlternativeNameExtension e = 9376 (IssuerAlternativeNameExtension) extension; 9377 printGeneralNames(e.getGeneralNames(), indent + " "); 9378 } 9379 else if (extension instanceof KeyUsageExtension) 9380 { 9381 out(indent + " " + 9382 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_EXT.get()); 9383 out(indent + " " + 9384 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9385 extension.getOID().toString())); 9386 out(indent + " " + 9387 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9388 String.valueOf(extension.isCritical()))); 9389 9390 out(indent + " " + 9391 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_USAGES.get()); 9392 final KeyUsageExtension kue = (KeyUsageExtension) extension; 9393 if (kue.isDigitalSignatureBitSet()) 9394 { 9395 out(indent + " " + 9396 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DS.get()); 9397 } 9398 9399 if (kue.isNonRepudiationBitSet()) 9400 { 9401 out(indent + " " + 9402 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_NR.get()); 9403 } 9404 9405 if (kue.isKeyEnciphermentBitSet()) 9406 { 9407 out(indent + " " + 9408 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KE.get()); 9409 } 9410 9411 if (kue.isDataEnciphermentBitSet()) 9412 { 9413 out(indent + " " + 9414 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DE.get()); 9415 } 9416 9417 if (kue.isKeyCertSignBitSet()) 9418 { 9419 out(indent + " " + 9420 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_KCS.get()); 9421 } 9422 9423 if (kue.isCRLSignBitSet()) 9424 { 9425 out(indent + " " + 9426 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_CRL_SIGN.get()); 9427 } 9428 9429 if (kue.isEncipherOnlyBitSet()) 9430 { 9431 out(indent + " " + 9432 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_EO.get()); 9433 } 9434 9435 if (kue.isDecipherOnlyBitSet()) 9436 { 9437 out(indent + " " + 9438 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_KU_DO.get()); 9439 } 9440 } 9441 else if (extension instanceof SubjectAlternativeNameExtension) 9442 { 9443 out(indent + " " + 9444 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SAN_EXT.get()); 9445 out(indent + " " + 9446 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9447 extension.getOID().toString())); 9448 out(indent + " " + 9449 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9450 String.valueOf(extension.isCritical()))); 9451 9452 final SubjectAlternativeNameExtension e = 9453 (SubjectAlternativeNameExtension) extension; 9454 printGeneralNames(e.getGeneralNames(), indent + " "); 9455 } 9456 else if (extension instanceof SubjectKeyIdentifierExtension) 9457 { 9458 out(indent + " " + 9459 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SKI_EXT.get()); 9460 out(indent + " " + 9461 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9462 extension.getOID().toString())); 9463 out(indent + " " + 9464 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9465 String.valueOf(extension.isCritical()))); 9466 9467 final SubjectKeyIdentifierExtension e = 9468 (SubjectKeyIdentifierExtension) extension; 9469 final String idHex = 9470 toColonDelimitedHex(e.getKeyIdentifier().getValue()); 9471 out(indent + " " + 9472 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_SKI_ID.get()); 9473 for (final String line : StaticUtils.wrapLine(idHex, 78)) 9474 { 9475 out(indent + " " + line); 9476 } 9477 } 9478 else 9479 { 9480 out(indent + " " + 9481 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_GENERIC.get()); 9482 out(indent + " " + 9483 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_OID.get( 9484 extension.getOID().toString())); 9485 out(indent + " " + 9486 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_IS_CRITICAL.get( 9487 String.valueOf(extension.isCritical()))); 9488 9489 final String valueHex = toColonDelimitedHex(extension.getValue()); 9490 out(indent + " " + 9491 INFO_MANAGE_CERTS_PRINT_CERT_LABEL_EXT_VALUE.get()); 9492 getOut().print(StaticUtils.toHexPlusASCII(extension.getValue(), 9493 (indent.length() + 15))); 9494 } 9495 } 9496 } 9497 9498 9499 9500 /** 9501 * Prints information about the contents of the provided general names object. 9502 * 9503 * @param generalNames The general names object to print. 9504 * @param indent The string to place at the beginning of each line to 9505 * indent that line. 9506 */ 9507 private void printGeneralNames(final GeneralNames generalNames, 9508 final String indent) 9509 { 9510 for (final String dnsName : generalNames.getDNSNames()) 9511 { 9512 out(indent + INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_DNS.get(dnsName)); 9513 } 9514 9515 for (final InetAddress ipAddress : generalNames.getIPAddresses()) 9516 { 9517 out(indent + 9518 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_IP.get( 9519 ipAddress.getHostAddress())); 9520 } 9521 9522 for (final String name : generalNames.getRFC822Names()) 9523 { 9524 out(indent + 9525 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_RFC_822_NAME.get(name)); 9526 } 9527 9528 for (final DN dn : generalNames.getDirectoryNames()) 9529 { 9530 out(indent + 9531 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_DIRECTORY_NAME.get( 9532 String.valueOf(dn))); 9533 } 9534 9535 for (final String uri : generalNames.getUniformResourceIdentifiers()) 9536 { 9537 out(indent + INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_URI.get(uri)); 9538 } 9539 9540 for (final OID oid : generalNames.getRegisteredIDs()) 9541 { 9542 out(indent + 9543 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_REGISTERED_ID.get( 9544 oid.toString())); 9545 } 9546 9547 if (! generalNames.getOtherNames().isEmpty()) 9548 { 9549 out(indent + 9550 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_OTHER_NAME_COUNT.get( 9551 generalNames.getOtherNames().size())); 9552 } 9553 9554 if (! generalNames.getX400Addresses().isEmpty()) 9555 { 9556 out(indent + 9557 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_X400_ADDR_COUNT.get( 9558 generalNames.getX400Addresses().size())); 9559 } 9560 9561 if (! generalNames.getEDIPartyNames().isEmpty()) 9562 { 9563 out(indent + 9564 INFO_MANAGE_CERTS_GENERAL_NAMES_LABEL_EDI_PARTY_NAME_COUNT.get( 9565 generalNames.getEDIPartyNames().size())); 9566 } 9567 } 9568 9569 9570 9571 /** 9572 * Writes a PEM-encoded representation of the provided encoded certificate to 9573 * the given print stream. 9574 * 9575 * @param printStream The print stream to which the PEM-encoded 9576 * certificate should be written. It must not be 9577 * {@code null}. 9578 * @param encodedCertificate The bytes that comprise the encoded 9579 * certificate. It must not be {@code null}. 9580 */ 9581 private static void writePEMCertificate(final PrintStream printStream, 9582 final byte[] encodedCertificate) 9583 { 9584 final String certBase64 = Base64.encode(encodedCertificate); 9585 printStream.println("-----BEGIN CERTIFICATE-----"); 9586 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 9587 { 9588 printStream.println(line); 9589 } 9590 printStream.println("-----END CERTIFICATE-----"); 9591 } 9592 9593 9594 9595 /** 9596 * Writes a PEM-encoded representation of the provided encoded certificate 9597 * signing request to the given print stream. 9598 * 9599 * @param printStream The print stream to which the PEM-encoded certificate 9600 * signing request should be written. It must not be 9601 * {@code null}. 9602 * @param encodedCSR The bytes that comprise the encoded certificate 9603 * signing request. It must not be {@code null}. 9604 */ 9605 private static void writePEMCertificateSigningRequest( 9606 final PrintStream printStream, 9607 final byte[] encodedCSR) 9608 { 9609 final String certBase64 = Base64.encode(encodedCSR); 9610 printStream.println("-----BEGIN CERTIFICATE REQUEST-----"); 9611 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 9612 { 9613 printStream.println(line); 9614 } 9615 printStream.println("-----END CERTIFICATE REQUEST-----"); 9616 } 9617 9618 9619 9620 /** 9621 * Writes a PEM-encoded representation of the provided encoded private key to 9622 * the given print stream. 9623 * 9624 * @param printStream The print stream to which the PEM-encoded 9625 * private key should be written. It must not be 9626 * {@code null}. 9627 * @param encodedPrivateKey The bytes that comprise the encoded private key. 9628 * It must not be {@code null}. 9629 */ 9630 private static void writePEMPrivateKey(final PrintStream printStream, 9631 final byte[] encodedPrivateKey) 9632 { 9633 final String certBase64 = Base64.encode(encodedPrivateKey); 9634 printStream.println("-----BEGIN PRIVATE KEY-----"); 9635 for (final String line : StaticUtils.wrapLine(certBase64, 64)) 9636 { 9637 printStream.println(line); 9638 } 9639 printStream.println("-----END PRIVATE KEY-----"); 9640 } 9641 9642 9643 9644 /** 9645 * Displays the keytool command that can be invoked to produce approximately 9646 * equivalent functionality. 9647 * 9648 * @param keytoolArgs The arguments to provide to the keytool command. 9649 */ 9650 private void displayKeytoolCommand(final List<String> keytoolArgs) 9651 { 9652 final StringBuilder buffer = new StringBuilder(); 9653 buffer.append("# keytool"); 9654 9655 boolean lastWasArgName = false; 9656 for (final String arg : keytoolArgs) 9657 { 9658 if (arg.startsWith("-")) 9659 { 9660 buffer.append(" \\"); 9661 buffer.append(StaticUtils.EOL); 9662 buffer.append("# "); 9663 buffer.append(arg); 9664 lastWasArgName = true; 9665 } 9666 else if (lastWasArgName) 9667 { 9668 buffer.append(' '); 9669 buffer.append(StaticUtils.cleanExampleCommandLineArgument(arg)); 9670 lastWasArgName = false; 9671 } 9672 else 9673 { 9674 buffer.append(" \\"); 9675 buffer.append(StaticUtils.EOL); 9676 buffer.append("# "); 9677 buffer.append(arg); 9678 lastWasArgName = false; 9679 } 9680 } 9681 9682 out(); 9683 out(INFO_MANAGE_CERTS_APPROXIMATE_KEYTOOL_COMMAND.get()); 9684 out(buffer); 9685 out(); 9686 } 9687 9688 9689 9690 /** 9691 * Retrieves the path to the target keystore file. 9692 * 9693 * @return The path to the target keystore file, or {@code null} if no 9694 * keystore path was configured. 9695 */ 9696 private File getKeystorePath() 9697 { 9698 final FileArgument keystoreArgument = 9699 subCommandParser.getFileArgument("keystore"); 9700 if (keystoreArgument != null) 9701 { 9702 return keystoreArgument.getValue(); 9703 } 9704 9705 return null; 9706 } 9707 9708 9709 9710 /** 9711 * Retrieves the password needed to access the keystore. 9712 * 9713 * @param keystoreFile The path to the keystore file for which to get the 9714 * password. 9715 * 9716 * @return The password needed to access the keystore, or {@code null} if 9717 * no keystore password was configured. 9718 * 9719 * @throws LDAPException If a problem is encountered while trying to get the 9720 * keystore password. 9721 */ 9722 private char[] getKeystorePassword(final File keystoreFile) 9723 throws LDAPException 9724 { 9725 return getKeystorePassword(keystoreFile, null); 9726 } 9727 9728 9729 9730 /** 9731 * Retrieves the password needed to access the keystore. 9732 * 9733 * @param keystoreFile The path to the keystore file for which to get the 9734 * password. 9735 * @param prefix The prefix string to use for the arguments. This may 9736 * be {@code null} if no prefix is needed. 9737 * 9738 * @return The password needed to access the keystore, or {@code null} if 9739 * no keystore password was configured. 9740 * 9741 * @throws LDAPException If a problem is encountered while trying to get the 9742 * keystore password. 9743 */ 9744 private char[] getKeystorePassword(final File keystoreFile, 9745 final String prefix) 9746 throws LDAPException 9747 { 9748 final String prefixDash; 9749 if (prefix == null) 9750 { 9751 prefixDash = ""; 9752 } 9753 else 9754 { 9755 prefixDash = prefix + '-'; 9756 } 9757 9758 final StringArgument keystorePasswordArgument = 9759 subCommandParser.getStringArgument(prefixDash + "keystore-password"); 9760 if ((keystorePasswordArgument != null) && 9761 keystorePasswordArgument.isPresent()) 9762 { 9763 final char[] keystorePWChars = 9764 keystorePasswordArgument.getValue().toCharArray(); 9765 if ((! keystoreFile.exists()) && (keystorePWChars.length < 6)) 9766 { 9767 throw new LDAPException(ResultCode.PARAM_ERROR, 9768 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 9769 } 9770 9771 return keystorePWChars; 9772 } 9773 9774 9775 final FileArgument keystorePasswordFileArgument = 9776 subCommandParser.getFileArgument( 9777 prefixDash + "keystore-password-file"); 9778 if ((keystorePasswordFileArgument != null) && 9779 keystorePasswordFileArgument.isPresent()) 9780 { 9781 final File f = keystorePasswordFileArgument.getValue(); 9782 try (final BufferedReader r = new BufferedReader(new FileReader(f))) 9783 { 9784 final String line = r.readLine(); 9785 if (line == null) 9786 { 9787 throw new LDAPException(ResultCode.PARAM_ERROR, 9788 ERR_MANAGE_CERTS_GET_KS_PW_EMPTY_FILE.get(f.getAbsolutePath())); 9789 } 9790 else if (r.readLine() != null) 9791 { 9792 throw new LDAPException(ResultCode.PARAM_ERROR, 9793 ERR_MANAGE_CERTS_GET_KS_PW_MULTI_LINE_FILE.get( 9794 f.getAbsolutePath())); 9795 } 9796 else if (line.isEmpty()) 9797 { 9798 throw new LDAPException(ResultCode.PARAM_ERROR, 9799 ERR_MANAGE_CERTS_GET_KS_PW_EMPTY_FILE.get(f.getAbsolutePath())); 9800 } 9801 else 9802 { 9803 if ((! keystoreFile.exists()) && (line.length() < 6)) 9804 { 9805 throw new LDAPException(ResultCode.PARAM_ERROR, 9806 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 9807 } 9808 9809 return line.toCharArray(); 9810 } 9811 } 9812 catch(final LDAPException le) 9813 { 9814 Debug.debugException(le); 9815 throw le; 9816 } 9817 catch (final Exception e) 9818 { 9819 Debug.debugException(e); 9820 throw new LDAPException(ResultCode.LOCAL_ERROR, 9821 ERR_MANAGE_CERTS_GET_KS_PW_ERROR_READING_FILE.get( 9822 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 9823 e); 9824 } 9825 } 9826 9827 9828 final BooleanArgument promptArgument = subCommandParser.getBooleanArgument( 9829 "prompt-for-" + prefixDash + "keystore-password"); 9830 if ((promptArgument != null) && promptArgument.isPresent()) 9831 { 9832 out(); 9833 if (keystoreFile.exists() && (! "new".equals(prefix))) 9834 { 9835 // We're only going to prompt once. 9836 if ((prefix != null) && prefix.equals("current")) 9837 { 9838 return promptForPassword( 9839 INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_CURRENT_PROMPT.get( 9840 keystoreFile.getAbsolutePath()), 9841 false); 9842 } 9843 else 9844 { 9845 return promptForPassword( 9846 INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_PROMPT.get( 9847 keystoreFile.getAbsolutePath()), 9848 false); 9849 } 9850 } 9851 else 9852 { 9853 // We're creating a new keystore, so we should prompt for the password 9854 // twice to prevent setting the wrong password because of a typo. 9855 while (true) 9856 { 9857 final String prompt1; 9858 if ("new".equals(prefix)) 9859 { 9860 prompt1 = INFO_MANAGE_CERTS_KEY_KS_PW_EXISTING_NEW_PROMPT.get(); 9861 } 9862 else 9863 { 9864 prompt1 = INFO_MANAGE_CERTS_KEY_KS_PW_NEW_PROMPT_1.get( 9865 keystoreFile.getAbsolutePath()); 9866 } 9867 final char[] pwChars = promptForPassword(prompt1, false); 9868 9869 if (pwChars.length < 6) 9870 { 9871 wrapErr(0, WRAP_COLUMN, 9872 ERR_MANAGE_CERTS_GET_KS_PW_TOO_SHORT.get()); 9873 err(); 9874 continue; 9875 } 9876 9877 final char[] confirmChars = promptForPassword( 9878 INFO_MANAGE_CERTS_KEY_KS_PW_NEW_PROMPT_2.get(), true); 9879 9880 if (Arrays.equals(pwChars, confirmChars)) 9881 { 9882 Arrays.fill(confirmChars, '\u0000'); 9883 return pwChars; 9884 } 9885 else 9886 { 9887 wrapErr(0, WRAP_COLUMN, 9888 ERR_MANAGE_CERTS_KEY_KS_PW_PROMPT_MISMATCH.get()); 9889 err(); 9890 } 9891 } 9892 } 9893 } 9894 9895 9896 return null; 9897 } 9898 9899 9900 9901 /** 9902 * Prompts for a password and retrieves the value that the user entered. 9903 * 9904 * @param prompt The prompt to display to the user. 9905 * @param allowEmpty Indicates whether to allow the password to be empty. 9906 * 9907 * @return The password that was read, or an empty array if the user did not 9908 * type a password before pressing ENTER. 9909 * 9910 * @throws LDAPException If a problem is encountered while reading the 9911 * password. 9912 */ 9913 private char[] promptForPassword(final String prompt, 9914 final boolean allowEmpty) 9915 throws LDAPException 9916 { 9917 final Iterator<String> iterator = 9918 StaticUtils.wrapLine(prompt, WRAP_COLUMN).iterator(); 9919 while (iterator.hasNext()) 9920 { 9921 final String line = iterator.next(); 9922 if (iterator.hasNext()) 9923 { 9924 out(line); 9925 } 9926 else 9927 { 9928 getOut().print(line); 9929 } 9930 } 9931 9932 final char[] passwordChars = PasswordReader.readPasswordChars(); 9933 if ((passwordChars.length == 0) && (! allowEmpty)) 9934 { 9935 wrapErr(0, WRAP_COLUMN, 9936 ERR_MANAGE_CERTS_PROMPT_FOR_PW_EMPTY_PW.get()); 9937 err(); 9938 return promptForPassword(prompt, allowEmpty); 9939 } 9940 9941 return passwordChars; 9942 } 9943 9944 9945 9946 /** 9947 * Prompts the user for a yes or no response. 9948 * 9949 * @param prompt The prompt to display to the end user. 9950 * 9951 * @return {@code true} if the user chooses the "yes" response, or 9952 * {@code false} if the user chooses the "no" throws. 9953 * 9954 * @throws LDAPException If a problem is encountered while reading data from 9955 * the client. 9956 */ 9957 private boolean promptForYesNo(final String prompt) 9958 throws LDAPException 9959 { 9960 while (true) 9961 { 9962 final List<String> lines = 9963 StaticUtils.wrapLine((prompt + ' '), WRAP_COLUMN); 9964 9965 final Iterator<String> lineIterator = lines.iterator(); 9966 while (lineIterator.hasNext()) 9967 { 9968 final String line = lineIterator.next(); 9969 if (lineIterator.hasNext()) 9970 { 9971 out(line); 9972 } 9973 else 9974 { 9975 getOut().print(line); 9976 } 9977 } 9978 9979 try 9980 { 9981 final String response = readLineFromIn(); 9982 if (response.equalsIgnoreCase("yes") || response.equalsIgnoreCase("y")) 9983 { 9984 return true; 9985 } 9986 else if (response.equalsIgnoreCase("no") || 9987 response.equalsIgnoreCase("n")) 9988 { 9989 return false; 9990 } 9991 else 9992 { 9993 err(); 9994 wrapErr(0, WRAP_COLUMN, 9995 ERR_MANAGE_CERTS_PROMPT_FOR_YES_NO_INVALID_RESPONSE.get()); 9996 err(); 9997 } 9998 } 9999 catch (final Exception e) 10000 { 10001 Debug.debugException(e); 10002 throw new LDAPException(ResultCode.LOCAL_ERROR, 10003 ERR_MANAGE_CERTS_PROMPT_FOR_YES_NO_READ_ERROR.get( 10004 StaticUtils.getExceptionMessage(e)), 10005 e); 10006 } 10007 } 10008 } 10009 10010 10011 10012 /** 10013 * Reads a line of input from standard input. 10014 * 10015 * @return The line read from standard input. 10016 * 10017 * @throws IOException If a problem is encountered while reading from 10018 * standard input. 10019 */ 10020 private String readLineFromIn() 10021 throws IOException 10022 { 10023 final ByteStringBuffer buffer = new ByteStringBuffer(); 10024 while (true) 10025 { 10026 final int byteRead = in.read(); 10027 if (byteRead < 0) 10028 { 10029 if (buffer.isEmpty()) 10030 { 10031 return null; 10032 } 10033 else 10034 { 10035 return buffer.toString(); 10036 } 10037 } 10038 10039 if (byteRead == '\n') 10040 { 10041 return buffer.toString(); 10042 } 10043 else if (byteRead == '\r') 10044 { 10045 final int nextByteRead = in.read(); 10046 Validator.ensureTrue(((nextByteRead < 0) || (nextByteRead == '\n')), 10047 "ERROR: Read a carriage return from standard input that was " + 10048 "not followed by a new line."); 10049 return buffer.toString(); 10050 } 10051 else 10052 { 10053 buffer.append((byte) (byteRead & 0xFF)); 10054 } 10055 } 10056 } 10057 10058 10059 10060 /** 10061 * Retrieves the password needed to access the private key. 10062 * 10063 * @param keystore The keystore that contains the target private 10064 * key. This must not be {@code null}. 10065 * @param alias The alias of the target private key. This must 10066 * not be {@code null}. 10067 * @param keystorePassword The keystore password to use if no specific 10068 * private key password was provided. 10069 * 10070 * @return The password needed to access the private key, or the provided 10071 * keystore password if no arguments were provided to specify a 10072 * different private key password. 10073 * 10074 * @throws LDAPException If a problem is encountered while trying to get the 10075 * private key password. 10076 */ 10077 private char[] getPrivateKeyPassword(final KeyStore keystore, 10078 final String alias, 10079 final char[] keystorePassword) 10080 throws LDAPException 10081 { 10082 return getPrivateKeyPassword(keystore, alias, null, keystorePassword); 10083 } 10084 10085 10086 10087 /** 10088 * Retrieves the password needed to access the private key. 10089 * 10090 * @param keystore The keystore that contains the target private 10091 * key. This must not be {@code null}. 10092 * @param alias The alias of the target private key. This must 10093 * not be {@code null}. 10094 * @param prefix The prefix string to use for the arguments. This 10095 * may be {@code null} if no prefix is needed. 10096 * @param keystorePassword The keystore password to use if no specific 10097 * private key password was provided. 10098 * 10099 * @return The password needed to access the private key, or the provided 10100 * keystore password if no arguments were provided to specify a 10101 * different private key password. 10102 * 10103 * @throws LDAPException If a problem is encountered while trying to get the 10104 * private key password. 10105 */ 10106 private char[] getPrivateKeyPassword(final KeyStore keystore, 10107 final String alias, final String prefix, 10108 final char[] keystorePassword) 10109 throws LDAPException 10110 { 10111 final String prefixDash; 10112 if (prefix == null) 10113 { 10114 prefixDash = ""; 10115 } 10116 else 10117 { 10118 prefixDash = prefix + '-'; 10119 } 10120 10121 final StringArgument privateKeyPasswordArgument = 10122 subCommandParser.getStringArgument( 10123 prefixDash + "private-key-password"); 10124 if ((privateKeyPasswordArgument != null) && 10125 privateKeyPasswordArgument.isPresent()) 10126 { 10127 final char[] pkPasswordChars = 10128 privateKeyPasswordArgument.getValue().toCharArray(); 10129 if ((pkPasswordChars.length < 6) && 10130 (! (hasCertificateAlias(keystore, alias) || 10131 hasKeyAlias(keystore, alias)))) 10132 { 10133 throw new LDAPException(ResultCode.PARAM_ERROR, 10134 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 10135 } 10136 10137 return pkPasswordChars; 10138 } 10139 10140 10141 final FileArgument privateKeyPasswordFileArgument = 10142 subCommandParser.getFileArgument( 10143 prefixDash + "private-key-password-file"); 10144 if ((privateKeyPasswordFileArgument != null) && 10145 privateKeyPasswordFileArgument.isPresent()) 10146 { 10147 final File f = privateKeyPasswordFileArgument.getValue(); 10148 try (final BufferedReader r = new BufferedReader(new FileReader(f))) 10149 { 10150 final String line = r.readLine(); 10151 if (line == null) 10152 { 10153 throw new LDAPException(ResultCode.PARAM_ERROR, 10154 ERR_MANAGE_CERTS_GET_PK_PW_EMPTY_FILE.get(f.getAbsolutePath())); 10155 } 10156 else if (r.readLine() != null) 10157 { 10158 throw new LDAPException(ResultCode.PARAM_ERROR, 10159 ERR_MANAGE_CERTS_GET_PK_PW_MULTI_LINE_FILE.get( 10160 f.getAbsolutePath())); 10161 } 10162 else if (line.isEmpty()) 10163 { 10164 throw new LDAPException(ResultCode.PARAM_ERROR, 10165 ERR_MANAGE_CERTS_GET_PK_PW_EMPTY_FILE.get(f.getAbsolutePath())); 10166 } 10167 else 10168 { 10169 if ((line.length() < 6) && 10170 (! (hasCertificateAlias(keystore, alias) || 10171 hasKeyAlias(keystore, alias)))) 10172 { 10173 throw new LDAPException(ResultCode.PARAM_ERROR, 10174 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 10175 } 10176 10177 return line.toCharArray(); 10178 } 10179 } 10180 catch(final LDAPException le) 10181 { 10182 Debug.debugException(le); 10183 throw le; 10184 } 10185 catch (final Exception e) 10186 { 10187 Debug.debugException(e); 10188 throw new LDAPException(ResultCode.LOCAL_ERROR, 10189 ERR_MANAGE_CERTS_GET_PK_PW_ERROR_READING_FILE.get( 10190 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 10191 e); 10192 } 10193 } 10194 10195 10196 final BooleanArgument promptArgument = 10197 subCommandParser.getBooleanArgument( 10198 "prompt-for-" + prefixDash + "private-key-password"); 10199 if ((promptArgument != null) && promptArgument.isPresent()) 10200 { 10201 out(); 10202 10203 try 10204 { 10205 if ((hasKeyAlias(keystore, alias) || 10206 hasCertificateAlias(keystore, alias)) && 10207 (! "new".equals(prefix))) 10208 { 10209 // This means that the private key already exists, so we just need to 10210 // prompt once. 10211 final String prompt; 10212 if ("current".equals(prefix)) 10213 { 10214 prompt = 10215 INFO_MANAGE_CERTS_GET_PK_PW_CURRENT_PROMPT.get(alias); 10216 } 10217 else 10218 { 10219 prompt = 10220 INFO_MANAGE_CERTS_GET_PK_PW_EXISTING_PROMPT.get(alias); 10221 } 10222 10223 return promptForPassword(prompt, false); 10224 } 10225 else 10226 { 10227 // This means that we'll be creating a new private key, so we need to 10228 // prompt twice. 10229 while (true) 10230 { 10231 final String prompt; 10232 if ("new".equals(prefix)) 10233 { 10234 prompt = INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT.get(); 10235 } 10236 else 10237 { 10238 prompt = INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT_1.get(alias); 10239 } 10240 10241 final char[] pwChars = promptForPassword(prompt, false); 10242 if (pwChars.length < 6) 10243 { 10244 wrapErr(0, WRAP_COLUMN, 10245 ERR_MANAGE_CERTS_GET_PK_PW_TOO_SHORT.get()); 10246 err(); 10247 continue; 10248 } 10249 10250 final char[] confirmChars = promptForPassword( 10251 INFO_MANAGE_CERTS_GET_PK_PW_NEW_PROMPT_2.get(), true); 10252 10253 if (Arrays.equals(pwChars, confirmChars)) 10254 { 10255 Arrays.fill(confirmChars, '\u0000'); 10256 return pwChars; 10257 } 10258 else 10259 { 10260 wrapErr(0, WRAP_COLUMN, 10261 ERR_MANAGE_CERTS_GET_PK_PW_PROMPT_MISMATCH.get()); 10262 err(); 10263 } 10264 } 10265 } 10266 } 10267 catch (final LDAPException le) 10268 { 10269 Debug.debugException(le); 10270 throw le; 10271 } 10272 catch (final Exception e) 10273 { 10274 Debug.debugException(e); 10275 throw new LDAPException(ResultCode.LOCAL_ERROR, 10276 ERR_MANAGE_CERTS_GET_PK_PW_PROMPT_ERROR.get(alias, 10277 StaticUtils.getExceptionMessage(e)), 10278 e); 10279 } 10280 } 10281 10282 10283 return keystorePassword; 10284 } 10285 10286 10287 10288 /** 10289 * Infers the keystore type from the provided keystore file. 10290 * 10291 * @param keystorePath The path to the file to examine. 10292 * 10293 * @return The keystore type inferred from the provided keystore file, or 10294 * {@code null} if the specified file does not exist. 10295 * 10296 * @throws LDAPException If a problem is encountered while trying to infer 10297 * the keystore type. 10298 */ 10299 private String inferKeystoreType(final File keystorePath) 10300 throws LDAPException 10301 { 10302 if (! keystorePath.exists()) 10303 { 10304 final StringArgument keystoreTypeArgument = 10305 subCommandParser.getStringArgument("keystore-type"); 10306 if ((keystoreTypeArgument != null) && keystoreTypeArgument.isPresent()) 10307 { 10308 final String ktaValue = keystoreTypeArgument.getValue(); 10309 if (ktaValue.equalsIgnoreCase("PKCS12") || 10310 ktaValue.equalsIgnoreCase("PKCS 12") || 10311 ktaValue.equalsIgnoreCase("PKCS#12") || 10312 ktaValue.equalsIgnoreCase("PKCS #12")) 10313 { 10314 return "PKCS12"; 10315 } 10316 else 10317 { 10318 return "JKS"; 10319 } 10320 } 10321 10322 return DEFAULT_KEYSTORE_TYPE; 10323 } 10324 10325 10326 try (final FileInputStream inputStream = new FileInputStream(keystorePath)) 10327 { 10328 final int firstByte = inputStream.read(); 10329 if (firstByte < 0) 10330 { 10331 throw new LDAPException(ResultCode.PARAM_ERROR, 10332 ERR_MANAGE_CERTS_INFER_KS_TYPE_EMPTY_FILE.get( 10333 keystorePath.getAbsolutePath())); 10334 } 10335 10336 if (firstByte == 0x30) 10337 { 10338 // This is the correct first byte of a DER sequence, and a PKCS #12 10339 // file is encoded as a DER sequence. 10340 return "PKCS12"; 10341 } 10342 else if (firstByte == 0xFE) 10343 { 10344 // This is the correct first byte of a Java JKS keystore, which starts 10345 // with bytes 0xFEEDFEED. 10346 return "JKS"; 10347 } 10348 else 10349 { 10350 throw new LDAPException(ResultCode.PARAM_ERROR, 10351 ERR_MANAGE_CERTS_INFER_KS_TYPE_UNEXPECTED_FIRST_BYTE.get( 10352 keystorePath.getAbsolutePath(), 10353 StaticUtils.toHex((byte) (firstByte & 0xFF)))); 10354 } 10355 } 10356 catch (final LDAPException e) 10357 { 10358 Debug.debugException(e); 10359 throw e; 10360 } 10361 catch (final Exception e) 10362 { 10363 Debug.debugException(e); 10364 throw new LDAPException(ResultCode.LOCAL_ERROR, 10365 ERR_MANAGE_CERTS_INFER_KS_TYPE_ERROR_READING_FILE.get( 10366 keystorePath.getAbsolutePath(), 10367 StaticUtils.getExceptionMessage(e)), 10368 e); 10369 } 10370 } 10371 10372 10373 10374 /** 10375 * Retrieves a user-friendly representation of the provided keystore type. 10376 * 10377 * @param keystoreType The keystore type for which to get the user-friendly 10378 * name. 10379 * 10380 * @return "JKS" if the provided keystore type is for a JKS keystore, 10381 * "PKCS #12" if the provided keystore type is for a PKCS #12 10382 * keystore, or the provided string if it is for some other keystore 10383 * type. 10384 */ 10385 static String getUserFriendlyKeystoreType(final String keystoreType) 10386 { 10387 if (keystoreType.equalsIgnoreCase("JKS")) 10388 { 10389 return "JKS"; 10390 } 10391 else if (keystoreType.equalsIgnoreCase("PKCS12") || 10392 keystoreType.equalsIgnoreCase("PKCS 12") || 10393 keystoreType.equalsIgnoreCase("PKCS#12") || 10394 keystoreType.equalsIgnoreCase("PKCS #12")) 10395 { 10396 return "PKCS #12"; 10397 } 10398 else 10399 { 10400 return keystoreType; 10401 } 10402 } 10403 10404 10405 10406 /** 10407 * Gets access to a keystore based on information included in command-line 10408 * arguments. 10409 * 10410 * @param keystoreType The keystore type for the keystore to access. 10411 * @param keystorePath The path to the keystore file. 10412 * @param keystorePassword The password to use to access the keystore. 10413 * 10414 * @return The configured keystore instance. 10415 * 10416 * @throws LDAPException If it is not possible to access the keystore. 10417 */ 10418 static KeyStore getKeystore(final String keystoreType, 10419 final File keystorePath, 10420 final char[] keystorePassword) 10421 throws LDAPException 10422 { 10423 // Instantiate a keystore instance of the desired keystore type. 10424 final KeyStore keystore; 10425 try 10426 { 10427 keystore = KeyStore.getInstance(keystoreType); 10428 } 10429 catch (final Exception e) 10430 { 10431 Debug.debugException(e); 10432 throw new LDAPException(ResultCode.LOCAL_ERROR, 10433 ERR_MANAGE_CERTS_CANNOT_INSTANTIATE_KS_TYPE.get(keystoreType, 10434 StaticUtils.getExceptionMessage(e)), 10435 e); 10436 } 10437 10438 10439 // Get an input stream that may be used to access the keystore. 10440 final InputStream inputStream; 10441 try 10442 { 10443 if (keystorePath.exists()) 10444 { 10445 inputStream = new FileInputStream(keystorePath); 10446 } 10447 else 10448 { 10449 inputStream = null; 10450 } 10451 } 10452 catch (final Exception e) 10453 { 10454 Debug.debugException(e); 10455 throw new LDAPException(ResultCode.LOCAL_ERROR, 10456 ERR_MANAGE_CERTS_CANNOT_OPEN_KS_FILE_FOR_READING.get( 10457 keystorePath.getAbsolutePath(), 10458 StaticUtils.getExceptionMessage(e)), 10459 e); 10460 } 10461 10462 try 10463 { 10464 keystore.load(inputStream, keystorePassword); 10465 } 10466 catch (final Exception e) 10467 { 10468 Debug.debugException(e); 10469 final Throwable cause = e.getCause(); 10470 if ((e instanceof IOException) && (cause != null) && 10471 (cause instanceof UnrecoverableKeyException) && 10472 (keystorePassword != null)) 10473 { 10474 throw new LDAPException(ResultCode.PARAM_ERROR, 10475 ERR_MANAGE_CERTS_CANNOT_LOAD_KS_WRONG_PW.get( 10476 keystorePath.getAbsolutePath()), 10477 e); 10478 } 10479 else 10480 { 10481 throw new LDAPException(ResultCode.PARAM_ERROR, 10482 ERR_MANAGE_CERTS_ERROR_CANNOT_LOAD_KS.get( 10483 keystorePath.getAbsolutePath(), 10484 StaticUtils.getExceptionMessage(e)), 10485 e); 10486 } 10487 } 10488 finally 10489 { 10490 try 10491 { 10492 if (inputStream != null) 10493 { 10494 inputStream.close(); 10495 } 10496 } 10497 catch (final Exception e) 10498 { 10499 Debug.debugException(e); 10500 } 10501 } 10502 10503 return keystore; 10504 } 10505 10506 10507 10508 /** 10509 * Reads all of the certificates contained in the specified file. The file 10510 * must exist and may contain zero or more certificates that are either all in 10511 * PEM format or all in DER format. 10512 * 10513 * @param f The path to the certificate file to read. It must not be 10514 * {@code null}. 10515 * 10516 * @return A list of the certificates read from the specified file. 10517 * 10518 * @throws LDAPException If a problem is encountered while reading 10519 * certificates from the specified file. 10520 */ 10521 static List<X509Certificate> readCertificatesFromFile(final File f) 10522 throws LDAPException 10523 { 10524 // Read the first byte of the file to see if it contains DER-formatted data, 10525 // which we can determine by seeing if the first byte is 0x30. 10526 try (final BufferedInputStream inputStream = 10527 new BufferedInputStream(new FileInputStream(f))) 10528 { 10529 inputStream.mark(1); 10530 final int firstByte = inputStream.read(); 10531 10532 if (firstByte < 0) 10533 { 10534 // This means that the file is empty. 10535 return Collections.emptyList(); 10536 } 10537 else 10538 { 10539 inputStream.reset(); 10540 } 10541 10542 final ArrayList<X509Certificate> certList = new ArrayList<>(5); 10543 if ((firstByte & 0xFF) == 0x30) 10544 { 10545 // It is a DER-encoded file. Read ASN.1 elements and decode them as 10546 // X.509 certificates. 10547 while (true) 10548 { 10549 final ASN1Element certElement; 10550 try 10551 { 10552 certElement = ASN1Element.readFrom(inputStream); 10553 } 10554 catch (final Exception e) 10555 { 10556 Debug.debugException(e); 10557 throw new LDAPException(ResultCode.LOCAL_ERROR, 10558 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DER_NOT_VALID_ASN1.get( 10559 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 10560 e); 10561 } 10562 10563 if (certElement == null) 10564 { 10565 // We've reached the end of the input stream. 10566 return certList; 10567 } 10568 10569 try 10570 { 10571 certList.add(new X509Certificate(certElement.encode())); 10572 } 10573 catch (final CertException e) 10574 { 10575 Debug.debugException(e); 10576 throw new LDAPException(ResultCode.PARAM_ERROR, 10577 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DER_NOT_VALID_CERT.get( 10578 f.getAbsolutePath(), e.getMessage()), 10579 e); 10580 } 10581 } 10582 } 10583 else 10584 { 10585 try (final BufferedReader reader = 10586 new BufferedReader(new InputStreamReader(inputStream))) 10587 { 10588 boolean inCert = false; 10589 final StringBuilder buffer = new StringBuilder(); 10590 while (true) 10591 { 10592 String line = reader.readLine(); 10593 if (line == null) 10594 { 10595 if (inCert) 10596 { 10597 throw new LDAPException(ResultCode.PARAM_ERROR, 10598 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_EOF_WITHOUT_END.get( 10599 f.getAbsolutePath())); 10600 } 10601 10602 return certList; 10603 } 10604 10605 line = line.trim(); 10606 if (line.isEmpty() || line.startsWith("#")) 10607 { 10608 continue; 10609 } 10610 10611 if (line.equals("-----BEGIN CERTIFICATE-----")) 10612 { 10613 if (inCert) 10614 { 10615 throw new LDAPException(ResultCode.PARAM_ERROR, 10616 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_MULTIPLE_BEGIN.get( 10617 f.getAbsolutePath())); 10618 } 10619 else 10620 { 10621 inCert = true; 10622 } 10623 } 10624 else if (line.equals("-----END CERTIFICATE-----")) 10625 { 10626 if (! inCert) 10627 { 10628 throw new LDAPException(ResultCode.PARAM_ERROR, 10629 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_END_WITHOUT_BEGIN. 10630 get(f.getAbsolutePath())); 10631 } 10632 10633 inCert = false; 10634 final byte[] certBytes; 10635 try 10636 { 10637 certBytes = Base64.decode(buffer.toString()); 10638 } 10639 catch (final Exception e) 10640 { 10641 Debug.debugException(e); 10642 throw new LDAPException(ResultCode.PARAM_ERROR, 10643 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_PEM_CERT_NOT_BASE64. 10644 get(f.getAbsolutePath(), 10645 StaticUtils.getExceptionMessage(e)), 10646 e); 10647 } 10648 10649 try 10650 { 10651 certList.add(new X509Certificate(certBytes)); 10652 } 10653 catch (final CertException e) 10654 { 10655 Debug.debugException(e); 10656 throw new LDAPException(ResultCode.PARAM_ERROR, 10657 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_PEM_CERT_NOT_CERT. 10658 get(f.getAbsolutePath(), e.getMessage()), 10659 e); 10660 } 10661 10662 buffer.setLength(0); 10663 } 10664 else if (inCert) 10665 { 10666 buffer.append(line); 10667 } 10668 else 10669 { 10670 throw new LDAPException(ResultCode.PARAM_ERROR, 10671 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_DATA_WITHOUT_BEGIN.get( 10672 f.getAbsolutePath())); 10673 } 10674 } 10675 } 10676 } 10677 } 10678 catch (final LDAPException le) 10679 { 10680 Debug.debugException(le); 10681 throw le; 10682 } 10683 catch (final Exception e) 10684 { 10685 Debug.debugException(e); 10686 throw new LDAPException(ResultCode.LOCAL_ERROR, 10687 ERR_MANAGE_CERTS_READ_CERTS_FROM_FILE_READ_ERROR.get( 10688 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 10689 e); 10690 } 10691 } 10692 10693 10694 10695 /** 10696 * Reads a private key from the specified file. The file must exist and must 10697 * contain exactly one PEM-encoded or DER-encoded PKCS #8 private key. 10698 * 10699 * @param f The path to the private key file to read. It must not be 10700 * {@code null}. 10701 * 10702 * @return The private key read from the file. 10703 * 10704 * @throws LDAPException If a problem is encountered while reading the 10705 * private key. 10706 */ 10707 static PKCS8PrivateKey readPrivateKeyFromFile(final File f) 10708 throws LDAPException 10709 { 10710 // Read the first byte of the file to see if it contains DER-formatted data, 10711 // which we can determine by seeing if the first byte is 0x30. 10712 try (final BufferedInputStream inputStream = 10713 new BufferedInputStream(new FileInputStream(f))) 10714 { 10715 inputStream.mark(1); 10716 final int firstByte = inputStream.read(); 10717 10718 if (firstByte < 0) 10719 { 10720 // This means that the file is empty. 10721 throw new LDAPException(ResultCode.PARAM_ERROR, 10722 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 10723 f.getAbsolutePath())); 10724 } 10725 else 10726 { 10727 inputStream.reset(); 10728 } 10729 10730 PKCS8PrivateKey privateKey = null; 10731 if ((firstByte & 0xFF) == 0x30) 10732 { 10733 // It is a DER-encoded file. Read an ASN.1 element and decode it as a 10734 // certificate. 10735 while (true) 10736 { 10737 final ASN1Element pkElement; 10738 try 10739 { 10740 pkElement = ASN1Element.readFrom(inputStream); 10741 } 10742 catch (final Exception e) 10743 { 10744 Debug.debugException(e); 10745 throw new LDAPException(ResultCode.LOCAL_ERROR, 10746 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DER_NOT_VALID_ASN1.get( 10747 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 10748 e); 10749 } 10750 10751 if (pkElement == null) 10752 { 10753 // We've reached the end of the input stream. 10754 if (privateKey == null) 10755 { 10756 throw new LDAPException(ResultCode.PARAM_ERROR, 10757 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 10758 f.getAbsolutePath())); 10759 } 10760 else 10761 { 10762 return privateKey; 10763 } 10764 } 10765 else if (privateKey == null) 10766 { 10767 try 10768 { 10769 privateKey = new PKCS8PrivateKey(pkElement.encode()); 10770 } 10771 catch (final Exception e) 10772 { 10773 Debug.debugException(e); 10774 throw new LDAPException(ResultCode.PARAM_ERROR, 10775 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DER_NOT_VALID_PK.get( 10776 f.getAbsolutePath(), e.getMessage()), 10777 e); 10778 } 10779 } 10780 else 10781 { 10782 throw new LDAPException(ResultCode.PARAM_ERROR, 10783 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_KEYS.get( 10784 f.getAbsolutePath())); 10785 } 10786 } 10787 } 10788 else 10789 { 10790 try (final BufferedReader reader = 10791 new BufferedReader(new InputStreamReader(inputStream))) 10792 { 10793 boolean inKey = false; 10794 boolean isRSAKey = false; 10795 final StringBuilder buffer = new StringBuilder(); 10796 while (true) 10797 { 10798 String line = reader.readLine(); 10799 if (line == null) 10800 { 10801 if (inKey) 10802 { 10803 throw new LDAPException(ResultCode.PARAM_ERROR, 10804 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EOF_WITHOUT_END.get( 10805 f.getAbsolutePath())); 10806 } 10807 10808 if (privateKey == null) 10809 { 10810 throw new LDAPException(ResultCode.PARAM_ERROR, 10811 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_EMPTY_FILE.get( 10812 f.getAbsolutePath())); 10813 } 10814 else 10815 { 10816 return privateKey; 10817 } 10818 } 10819 10820 line = line.trim(); 10821 if (line.isEmpty() || line.startsWith("#")) 10822 { 10823 continue; 10824 } 10825 10826 if (line.equals("-----BEGIN PRIVATE KEY-----") || 10827 line.equals("-----BEGIN RSA PRIVATE KEY-----")) 10828 { 10829 if (inKey) 10830 { 10831 throw new LDAPException(ResultCode.PARAM_ERROR, 10832 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_BEGIN.get( 10833 f.getAbsolutePath())); 10834 } 10835 else if (privateKey != null) 10836 { 10837 throw new LDAPException(ResultCode.PARAM_ERROR, 10838 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_MULTIPLE_KEYS.get( 10839 f.getAbsolutePath())); 10840 } 10841 else 10842 { 10843 inKey = true; 10844 if (line.equals("-----BEGIN RSA PRIVATE KEY-----")) 10845 { 10846 isRSAKey = true; 10847 } 10848 } 10849 } 10850 else if (line.equals("-----END PRIVATE KEY-----") || 10851 line.equals("-----END RSA PRIVATE KEY-----")) 10852 { 10853 if (! inKey) 10854 { 10855 throw new LDAPException(ResultCode.PARAM_ERROR, 10856 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_END_WITHOUT_BEGIN.get( 10857 f.getAbsolutePath())); 10858 } 10859 10860 inKey = false; 10861 byte[] pkBytes; 10862 try 10863 { 10864 pkBytes = Base64.decode(buffer.toString()); 10865 } 10866 catch (final Exception e) 10867 { 10868 Debug.debugException(e); 10869 throw new LDAPException(ResultCode.PARAM_ERROR, 10870 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PEM_PK_NOT_BASE64.get( 10871 f.getAbsolutePath(), 10872 StaticUtils.getExceptionMessage(e)), 10873 e); 10874 } 10875 10876 if (isRSAKey) 10877 { 10878 pkBytes = PKCS8PrivateKey.wrapRSAPrivateKey(pkBytes); 10879 } 10880 10881 try 10882 { 10883 privateKey = new PKCS8PrivateKey(pkBytes); 10884 } 10885 catch (final CertException e) 10886 { 10887 Debug.debugException(e); 10888 throw new LDAPException(ResultCode.PARAM_ERROR, 10889 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_PEM_PK_NOT_PK.get( 10890 f.getAbsolutePath(), e.getMessage()), 10891 e); 10892 } 10893 10894 buffer.setLength(0); 10895 } 10896 else if (inKey) 10897 { 10898 buffer.append(line); 10899 } 10900 else 10901 { 10902 throw new LDAPException(ResultCode.PARAM_ERROR, 10903 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_DATA_WITHOUT_BEGIN.get( 10904 f.getAbsolutePath())); 10905 } 10906 } 10907 } 10908 } 10909 } 10910 catch (final LDAPException le) 10911 { 10912 Debug.debugException(le); 10913 throw le; 10914 } 10915 catch (final Exception e) 10916 { 10917 Debug.debugException(e); 10918 throw new LDAPException(ResultCode.LOCAL_ERROR, 10919 ERR_MANAGE_CERTS_READ_PK_FROM_FILE_READ_ERROR.get( 10920 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 10921 e); 10922 } 10923 } 10924 10925 10926 10927 /** 10928 * Reads a certificate signing request from the specified file. The file must 10929 * exist and must contain exactly one PEM-encoded or DER-encoded PKCS #10 10930 * certificate signing request. 10931 * 10932 * @param f The path to the private key file to read. It must not be 10933 * {@code null}. 10934 * 10935 * @return The certificate signing request read from the file. 10936 * 10937 * @throws LDAPException If a problem is encountered while reading the 10938 * certificate signing request. 10939 */ 10940 static PKCS10CertificateSigningRequest 10941 readCertificateSigningRequestFromFile(final File f) 10942 throws LDAPException 10943 { 10944 // Read the first byte of the file to see if it contains DER-formatted data, 10945 // which we can determine by seeing if the first byte is 0x30. 10946 try (final BufferedInputStream inputStream = 10947 new BufferedInputStream(new FileInputStream(f))) 10948 { 10949 inputStream.mark(1); 10950 final int firstByte = inputStream.read(); 10951 10952 if (firstByte < 0) 10953 { 10954 // This means that the file is empty. 10955 throw new LDAPException(ResultCode.PARAM_ERROR, 10956 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 10957 f.getAbsolutePath())); 10958 } 10959 else 10960 { 10961 inputStream.reset(); 10962 } 10963 10964 PKCS10CertificateSigningRequest csr = null; 10965 if ((firstByte & 0xFF) == 0x30) 10966 { 10967 // It is a DER-encoded file. Read an ASN.1 element and decode it as a 10968 // certificate. 10969 while (true) 10970 { 10971 final ASN1Element csrElement; 10972 try 10973 { 10974 csrElement = ASN1Element.readFrom(inputStream); 10975 } 10976 catch (final Exception e) 10977 { 10978 Debug.debugException(e); 10979 throw new LDAPException(ResultCode.LOCAL_ERROR, 10980 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DER_NOT_VALID_ASN1.get( 10981 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 10982 e); 10983 } 10984 10985 if (csrElement == null) 10986 { 10987 // We've reached the end of the input stream. 10988 if (csr == null) 10989 { 10990 throw new LDAPException(ResultCode.PARAM_ERROR, 10991 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 10992 f.getAbsolutePath())); 10993 } 10994 else 10995 { 10996 return csr; 10997 } 10998 } 10999 else if (csr == null) 11000 { 11001 try 11002 { 11003 csr = new PKCS10CertificateSigningRequest(csrElement.encode()); 11004 } 11005 catch (final Exception e) 11006 { 11007 Debug.debugException(e); 11008 throw new LDAPException(ResultCode.PARAM_ERROR, 11009 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DER_NOT_VALID_CSR.get( 11010 f.getAbsolutePath(), e.getMessage()), 11011 e); 11012 } 11013 } 11014 else 11015 { 11016 throw new LDAPException(ResultCode.PARAM_ERROR, 11017 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_CSRS.get( 11018 f.getAbsolutePath())); 11019 } 11020 } 11021 } 11022 else 11023 { 11024 try (final BufferedReader reader = 11025 new BufferedReader(new InputStreamReader(inputStream))) 11026 { 11027 boolean inCSR = false; 11028 final StringBuilder buffer = new StringBuilder(); 11029 while (true) 11030 { 11031 String line = reader.readLine(); 11032 if (line == null) 11033 { 11034 if (inCSR) 11035 { 11036 throw new LDAPException(ResultCode.PARAM_ERROR, 11037 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EOF_WITHOUT_END.get( 11038 f.getAbsolutePath())); 11039 } 11040 11041 if (csr == null) 11042 { 11043 throw new LDAPException(ResultCode.PARAM_ERROR, 11044 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_EMPTY_FILE.get( 11045 f.getAbsolutePath())); 11046 } 11047 else 11048 { 11049 return csr; 11050 } 11051 } 11052 11053 line = line.trim(); 11054 if (line.isEmpty() || line.startsWith("#")) 11055 { 11056 continue; 11057 } 11058 11059 if (line.equals("-----BEGIN CERTIFICATE REQUEST-----") || 11060 line.equals("-----BEGIN NEW CERTIFICATE REQUEST-----")) 11061 { 11062 if (inCSR) 11063 { 11064 throw new LDAPException(ResultCode.PARAM_ERROR, 11065 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_BEGIN.get( 11066 f.getAbsolutePath())); 11067 } 11068 else if (csr != null) 11069 { 11070 throw new LDAPException(ResultCode.PARAM_ERROR, 11071 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_MULTIPLE_CSRS.get( 11072 f.getAbsolutePath())); 11073 } 11074 else 11075 { 11076 inCSR = true; 11077 } 11078 } 11079 else if (line.equals("-----END CERTIFICATE REQUEST-----") || 11080 line.equals("-----END NEW CERTIFICATE REQUEST-----")) 11081 { 11082 if (! inCSR) 11083 { 11084 throw new LDAPException(ResultCode.PARAM_ERROR, 11085 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_END_WITHOUT_BEGIN.get( 11086 f.getAbsolutePath())); 11087 } 11088 11089 inCSR = false; 11090 final byte[] csrBytes; 11091 try 11092 { 11093 csrBytes = Base64.decode(buffer.toString()); 11094 } 11095 catch (final Exception e) 11096 { 11097 Debug.debugException(e); 11098 throw new LDAPException(ResultCode.PARAM_ERROR, 11099 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_PEM_CSR_NOT_BASE64.get( 11100 f.getAbsolutePath(), 11101 StaticUtils.getExceptionMessage(e)), 11102 e); 11103 } 11104 11105 try 11106 { 11107 csr = new PKCS10CertificateSigningRequest(csrBytes); 11108 } 11109 catch (final CertException e) 11110 { 11111 Debug.debugException(e); 11112 throw new LDAPException(ResultCode.PARAM_ERROR, 11113 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_PEM_CSR_NOT_CSR.get( 11114 f.getAbsolutePath(), e.getMessage()), 11115 e); 11116 } 11117 11118 buffer.setLength(0); 11119 } 11120 else if (inCSR) 11121 { 11122 buffer.append(line); 11123 } 11124 else 11125 { 11126 throw new LDAPException(ResultCode.PARAM_ERROR, 11127 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_DATA_WITHOUT_BEGIN.get( 11128 f.getAbsolutePath())); 11129 } 11130 } 11131 } 11132 } 11133 } 11134 catch (final LDAPException le) 11135 { 11136 Debug.debugException(le); 11137 throw le; 11138 } 11139 catch (final Exception e) 11140 { 11141 Debug.debugException(e); 11142 throw new LDAPException(ResultCode.LOCAL_ERROR, 11143 ERR_MANAGE_CERTS_READ_CSR_FROM_FILE_READ_ERROR.get( 11144 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 11145 e); 11146 } 11147 } 11148 11149 11150 11151 /** 11152 * Retrieves a colon-delimited hexadecimal representation of the contents of 11153 * the provided byte array. 11154 * 11155 * @param bytes The byte array for which to get the hexadecimal 11156 * representation. It must not be {@code null}. 11157 * 11158 * @return A colon-delimited hexadecimal representation of the contents of 11159 * the provided byte array. 11160 */ 11161 private static String toColonDelimitedHex(final byte... bytes) 11162 { 11163 final StringBuilder buffer = new StringBuilder(bytes.length * 3); 11164 StaticUtils.toHex(bytes, ":", buffer); 11165 return buffer.toString(); 11166 } 11167 11168 11169 11170 /** 11171 * Retrieves a formatted representation of the provided date in a 11172 * human-readable format that includes an offset from the current time. 11173 * 11174 * @param d The date to format. It must not be {@code null}. 11175 * 11176 * @return A formatted representation of the provided date. 11177 */ 11178 private static String formatDateAndTime(final Date d) 11179 { 11180 // Example: Sunday, January 1, 2017 11181 final String dateFormatString = "EEEE, MMMM d, yyyy"; 11182 final String formattedDate = 11183 new SimpleDateFormat(dateFormatString).format(d); 11184 11185 // Example: 12:34:56 AM CDT 11186 final String timeFormatString = "hh:mm:ss aa z"; 11187 final String formattedTime = 11188 new SimpleDateFormat(timeFormatString).format(d); 11189 11190 final long providedTime = d.getTime(); 11191 final long currentTime = System.currentTimeMillis(); 11192 if (providedTime > currentTime) 11193 { 11194 final long secondsInFuture = ((providedTime - currentTime) / 1000L); 11195 final String durationInFuture = 11196 StaticUtils.secondsToHumanReadableDuration(secondsInFuture); 11197 return INFO_MANAGE_CERTS_FORMAT_DATE_AND_TIME_IN_FUTURE.get(formattedDate, 11198 formattedTime, durationInFuture); 11199 } 11200 else 11201 { 11202 final long secondsInPast = ((currentTime - providedTime) / 1000L); 11203 final String durationInPast = 11204 StaticUtils.secondsToHumanReadableDuration(secondsInPast); 11205 return INFO_MANAGE_CERTS_FORMAT_DATE_AND_TIME_IN_PAST.get(formattedDate, 11206 formattedTime, durationInPast); 11207 } 11208 } 11209 11210 11211 11212 /** 11213 * Retrieves a formatted representation of the provided date in a format 11214 * suitable for use as the validity start time value provided to the keytool 11215 * command. 11216 * 11217 * @param d The date to format. It must not be {@code null}. 11218 * 11219 * @return A formatted representation of the provided date. 11220 */ 11221 private static String formatValidityStartTime(final Date d) 11222 { 11223 // Example: 2017/01/01 01:23:45 11224 final String dateFormatString = "yyyy'/'MM'/'dd HH':'mm':'ss"; 11225 return new SimpleDateFormat(dateFormatString).format(d); 11226 } 11227 11228 11229 11230 /** 11231 * Retrieves the certificate chain for the specified certificate from the 11232 * given keystore. If any issuer certificate is not in the provided keystore, 11233 * then the JVM-default trust store will be checked to see if it can be found 11234 * there. 11235 * 11236 * @param alias The alias of the certificate for which to get the 11237 * certificate chain. This must not be 11238 * {@code null}. 11239 * @param keystore The keystore from which to get the certificate 11240 * chain. This must not be {@code null}. 11241 * @param missingIssuerRef A reference that will be updated with the DN of a 11242 * missing issuer certificate, if any certificate in 11243 * the chain cannot be located. This must not be 11244 * {@code null}. 11245 * 11246 * @return The certificate chain for the specified certificate, or an empty 11247 * array if no certificate exists with the specified alias. 11248 * 11249 * @throws LDAPException If a problem is encountered while getting the 11250 * certificate chain. 11251 */ 11252 private static X509Certificate[] getCertificateChain(final String alias, 11253 final KeyStore keystore, 11254 final AtomicReference<DN> missingIssuerRef) 11255 throws LDAPException 11256 { 11257 try 11258 { 11259 // First, see if the keystore will give us the certificate chain. This 11260 // will only happen if the alias references an entry that includes the 11261 // private key, but it will save us a lot of work. 11262 final Certificate[] chain = keystore.getCertificateChain(alias); 11263 if ((chain != null) && (chain.length > 0)) 11264 { 11265 final X509Certificate[] x509Chain = new X509Certificate[chain.length]; 11266 for (int i=0; i < chain.length; i++) 11267 { 11268 x509Chain[i] = new X509Certificate(chain[i].getEncoded()); 11269 } 11270 return x509Chain; 11271 } 11272 11273 11274 // We couldn't get the keystore to give us the chain, but see if we can 11275 // get a certificate with the specified alias. 11276 final Certificate endCert = keystore.getCertificate(alias); 11277 if (endCert == null) 11278 { 11279 // This means there isn't any certificate with the specified alias. 11280 // Return an empty chain. 11281 return new X509Certificate[0]; 11282 } 11283 11284 final ArrayList<X509Certificate> chainList = new ArrayList<>(5); 11285 X509Certificate certificate = new X509Certificate(endCert.getEncoded()); 11286 chainList.add(certificate); 11287 11288 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef = 11289 new AtomicReference<>(); 11290 while (true) 11291 { 11292 final X509Certificate issuerCertificate = 11293 getIssuerCertificate(certificate, keystore, 11294 jvmDefaultTrustStoreRef, missingIssuerRef); 11295 if (issuerCertificate == null) 11296 { 11297 break; 11298 } 11299 11300 chainList.add(issuerCertificate); 11301 certificate = issuerCertificate; 11302 } 11303 11304 final X509Certificate[] x509Chain = new X509Certificate[chainList.size()]; 11305 return chainList.toArray(x509Chain); 11306 } 11307 catch (final Exception e) 11308 { 11309 Debug.debugException(e); 11310 throw new LDAPException(ResultCode.LOCAL_ERROR, 11311 ERR_MANAGE_CERTS_GET_CHAIN_ERROR.get(alias, 11312 StaticUtils.getExceptionMessage(e)), 11313 e); 11314 } 11315 } 11316 11317 11318 11319 /** 11320 * Attempts to retrieve the issuer certificate for the provided certificate 11321 * from the given keystore or the JVM-default trust store. 11322 * 11323 * @param certificate The certificate for which to retrieve the 11324 * issuer certificate. 11325 * @param keystore The keystore in which to look for the 11326 * issuer certificate. 11327 * @param jvmDefaultTrustStoreRef A reference that will be used to hold the 11328 * JVM-default trust store if it is obtained 11329 * in the process of retrieving the issuer 11330 * certificate. 11331 * @param missingIssuerRef A reference that will be updated with the 11332 * DN of a missing issuer certificate, if any 11333 * certificate in the chain cannot be 11334 * located. This must not be {@code null}. 11335 * 11336 * @return The issuer certificate for the provided certificate, or 11337 * {@code null} if the issuer certificate could not be retrieved. 11338 * 11339 * @throws Exception If a problem is encountered while trying to retrieve 11340 * the issuer certificate. 11341 */ 11342 private static X509Certificate getIssuerCertificate( 11343 final X509Certificate certificate, 11344 final KeyStore keystore, 11345 final AtomicReference<KeyStore> jvmDefaultTrustStoreRef, 11346 final AtomicReference<DN> missingIssuerRef) 11347 throws Exception 11348 { 11349 final DN subjectDN = certificate.getSubjectDN(); 11350 final DN issuerDN = certificate.getIssuerDN(); 11351 if (subjectDN.equals(issuerDN)) 11352 { 11353 // This means that the certificate is self-signed, so there is no issuer. 11354 return null; 11355 } 11356 11357 11358 // See if we can find the issuer certificate in the provided keystore. 11359 X509Certificate issuerCertificate = getIssuerCertificate(certificate, 11360 keystore); 11361 if (issuerCertificate != null) 11362 { 11363 return issuerCertificate; 11364 } 11365 11366 11367 // See if we can get the JVM-default trust store. 11368 KeyStore jvmDefaultTrustStore = jvmDefaultTrustStoreRef.get(); 11369 if (jvmDefaultTrustStore == null) 11370 { 11371 if (JVM_DEFAULT_CACERTS_FILE == null) 11372 { 11373 missingIssuerRef.set(issuerDN); 11374 return null; 11375 } 11376 11377 for (final String keystoreType : new String[] { "JKS", "PKCS12" }) 11378 { 11379 final KeyStore ks = KeyStore.getInstance(keystoreType); 11380 try (final FileInputStream inputStream = 11381 new FileInputStream(JVM_DEFAULT_CACERTS_FILE)) 11382 { 11383 ks.load(inputStream, null); 11384 jvmDefaultTrustStore = ks; 11385 jvmDefaultTrustStoreRef.set(jvmDefaultTrustStore); 11386 break; 11387 } 11388 catch (final Exception e) 11389 { 11390 Debug.debugException(e); 11391 } 11392 } 11393 } 11394 11395 if (jvmDefaultTrustStore != null) 11396 { 11397 issuerCertificate = getIssuerCertificate(certificate, 11398 jvmDefaultTrustStore); 11399 } 11400 11401 if (issuerCertificate == null) 11402 { 11403 missingIssuerRef.set(issuerDN); 11404 } 11405 11406 return issuerCertificate; 11407 } 11408 11409 11410 11411 /** 11412 * Attempts to retrieve the issuer certificate for the provided certificate 11413 * from the given keystore. 11414 * 11415 * @param certificate The certificate for which to retrieve the issuer 11416 * certificate. 11417 * @param keystore The keystore in which to look for the issuer 11418 * certificate. 11419 * 11420 * @return The issuer certificate for the provided certificate, or 11421 * {@code null} if the issuer certificate could not be retrieved. 11422 * 11423 * @throws Exception If a problem is encountered while trying to retrieve 11424 * the issuer certificate. 11425 */ 11426 private static X509Certificate getIssuerCertificate( 11427 final X509Certificate certificate, 11428 final KeyStore keystore) 11429 throws Exception 11430 { 11431 final Enumeration<String> aliases = keystore.aliases(); 11432 while (aliases.hasMoreElements()) 11433 { 11434 final String alias = aliases.nextElement(); 11435 11436 Certificate[] certs = null; 11437 if (hasCertificateAlias(keystore, alias)) 11438 { 11439 final Certificate c = keystore.getCertificate(alias); 11440 if (c == null) 11441 { 11442 continue; 11443 } 11444 11445 certs = new Certificate[] { c }; 11446 } 11447 else if (hasKeyAlias(keystore, alias)) 11448 { 11449 certs = keystore.getCertificateChain(alias); 11450 } 11451 11452 if (certs != null) 11453 { 11454 for (final Certificate c : certs) 11455 { 11456 final X509Certificate xc = new X509Certificate(c.getEncoded()); 11457 if (xc.isIssuerFor(certificate)) 11458 { 11459 return xc; 11460 } 11461 } 11462 } 11463 } 11464 11465 return null; 11466 } 11467 11468 11469 11470 /** 11471 * Retrieves the authority key identifier value for the provided certificate, 11472 * if present. 11473 * 11474 * @param c The certificate for which to retrieve the authority key 11475 * identifier. 11476 * 11477 * @return The authority key identifier value for the provided certificate, 11478 * or {@code null} if the certificate does not have an authority 11479 * key identifier. 11480 */ 11481 private static byte[] getAuthorityKeyIdentifier(final X509Certificate c) 11482 { 11483 for (final X509CertificateExtension extension : c.getExtensions()) 11484 { 11485 if (extension instanceof AuthorityKeyIdentifierExtension) 11486 { 11487 final AuthorityKeyIdentifierExtension e = 11488 (AuthorityKeyIdentifierExtension) extension; 11489 if (e.getKeyIdentifier() != null) 11490 { 11491 return e.getKeyIdentifier().getValue(); 11492 } 11493 } 11494 } 11495 11496 return null; 11497 } 11498 11499 11500 11501 /** 11502 * Writes the provided keystore to the specified file. If the keystore file 11503 * already exists, a new temporary file will be created, the old file renamed 11504 * out of the way, the new file renamed into place, and the old file deleted. 11505 * If the keystore file does not exist, then it will simply be created in the 11506 * correct place. 11507 * 11508 * @param keystore The keystore to be written. 11509 * @param keystorePath The path to the keystore file to be written. 11510 * @param keystorePassword The password to use for the keystore. 11511 * 11512 * @throws LDAPException If a problem is encountered while writing the 11513 * keystore. 11514 */ 11515 static void writeKeystore(final KeyStore keystore, final File keystorePath, 11516 final char[] keystorePassword) 11517 throws LDAPException 11518 { 11519 File copyOfExistingKeystore = null; 11520 final String timestamp = 11521 StaticUtils.encodeGeneralizedTime(System.currentTimeMillis()); 11522 if (keystorePath.exists()) 11523 { 11524 copyOfExistingKeystore = new File(keystorePath.getAbsolutePath() + 11525 ".backup-" + timestamp); 11526 try 11527 { 11528 Files.copy(keystorePath.toPath(), copyOfExistingKeystore.toPath()); 11529 } 11530 catch (final Exception e) 11531 { 11532 Debug.debugException(e); 11533 throw new LDAPException(ResultCode.LOCAL_ERROR, 11534 ERR_MANAGE_CERTS_WRITE_KS_ERROR_COPYING_EXISTING_KS.get( 11535 keystorePath.getAbsolutePath(), 11536 copyOfExistingKeystore.getAbsolutePath(), 11537 StaticUtils.getExceptionMessage(e)), 11538 e); 11539 } 11540 } 11541 11542 try (final FileOutputStream outputStream = 11543 new FileOutputStream(keystorePath)) 11544 { 11545 keystore.store(outputStream, keystorePassword); 11546 } 11547 catch (final Exception e) 11548 { 11549 Debug.debugException(e); 11550 if (copyOfExistingKeystore == null) 11551 { 11552 throw new LDAPException(ResultCode.LOCAL_ERROR, 11553 ERR_MANAGE_CERTS_WRITE_KS_ERROR_WRITING_NEW_KS.get( 11554 keystorePath.getAbsolutePath(), 11555 StaticUtils.getExceptionMessage(e)), 11556 e); 11557 } 11558 else 11559 { 11560 throw new LDAPException(ResultCode.LOCAL_ERROR, 11561 ERR_MANAGE_CERTS_WRITE_KS_ERROR_OVERWRITING_KS.get( 11562 keystorePath.getAbsolutePath(), 11563 StaticUtils.getExceptionMessage(e), 11564 copyOfExistingKeystore.getAbsolutePath()), 11565 e); 11566 } 11567 } 11568 11569 if (copyOfExistingKeystore != null) 11570 { 11571 try 11572 { 11573 Files.delete(copyOfExistingKeystore.toPath()); 11574 } 11575 catch (final Exception e) 11576 { 11577 Debug.debugException(e); 11578 throw new LDAPException(ResultCode.LOCAL_ERROR, 11579 ERR_MANAGE_CERTS_WRITE_KS_ERROR_DELETING_KS_BACKUP.get( 11580 copyOfExistingKeystore.getAbsolutePath(), 11581 keystorePath.getAbsolutePath(), 11582 StaticUtils.getExceptionMessage(e)), 11583 e); 11584 } 11585 } 11586 } 11587 11588 11589 11590 /** 11591 * Indicates whether the provided keystore has a certificate entry with the 11592 * specified alias. 11593 * 11594 * @param keystore The keystore to examine. 11595 * @param alias The alias for which to make the determination. 11596 * 11597 * @return {@code true} if the keystore has a certificate entry with the 11598 * specified alias, or {@code false} if the alias doesn't exist or 11599 * is associated with some other type of entry (like a key). 11600 */ 11601 private static boolean hasCertificateAlias(final KeyStore keystore, 11602 final String alias) 11603 { 11604 try 11605 { 11606 return keystore.isCertificateEntry(alias); 11607 } 11608 catch (final Exception e) 11609 { 11610 // This should never happen. If it does, then we'll assume the alias 11611 // doesn't exist or isn't associated with a certificate. 11612 Debug.debugException(e); 11613 return false; 11614 } 11615 } 11616 11617 11618 11619 /** 11620 * Indicates whether the provided keystore has a key entry with the specified 11621 * alias. 11622 * 11623 * @param keystore The keystore to examine. 11624 * @param alias The alias for which to make the determination. 11625 * 11626 * @return {@code true} if the keystore has a key entry with the specified 11627 * alias, or {@code false} if the alias doesn't exist or is 11628 * associated with some other type of entry (like a certificate). 11629 */ 11630 private static boolean hasKeyAlias(final KeyStore keystore, 11631 final String alias) 11632 { 11633 try 11634 { 11635 return keystore.isKeyEntry(alias); 11636 } 11637 catch (final Exception e) 11638 { 11639 // This should never happen. If it does, then we'll assume the alias 11640 // doesn't exist or isn't associated with a key. 11641 Debug.debugException(e); 11642 return false; 11643 } 11644 } 11645 11646 11647 11648 /** 11649 * Adds arguments for each of the provided extensions to the given list. 11650 * 11651 * @param keytoolArguments The list to which the extension arguments should 11652 * be added. 11653 * @param basicConstraints The basic constraints extension to include. It 11654 * may be {@code null} if this extension should not 11655 * be included. 11656 * @param keyUsage The key usage extension to include. It may be 11657 * {@code null} if this extension should not be 11658 * included. 11659 * @param extendedKeyUsage The extended key usage extension to include. It 11660 * may be {@code null} if this extension should not 11661 * be included. 11662 * @param sanValues The list of subject alternative name values to 11663 * include. It must not be {@code null} but may be 11664 * empty. 11665 * @param ianValues The list of issuer alternative name values to 11666 * include. It must not be {@code null} but may be 11667 * empty. 11668 * @param genericExtensions The list of generic extensions to include. It 11669 * must not be {@code null} but may be empty. 11670 */ 11671 private static void addExtensionArguments(final List<String> keytoolArguments, 11672 final BasicConstraintsExtension basicConstraints, 11673 final KeyUsageExtension keyUsage, 11674 final ExtendedKeyUsageExtension extendedKeyUsage, 11675 final Set<String> sanValues, 11676 final Set<String> ianValues, 11677 final List<X509CertificateExtension> genericExtensions) 11678 { 11679 if (basicConstraints != null) 11680 { 11681 final StringBuilder basicConstraintsValue = new StringBuilder(); 11682 basicConstraintsValue.append("ca:"); 11683 basicConstraintsValue.append(basicConstraints.isCA()); 11684 11685 if (basicConstraints.getPathLengthConstraint() != null) 11686 { 11687 basicConstraintsValue.append(",pathlen:"); 11688 basicConstraintsValue.append( 11689 basicConstraints.getPathLengthConstraint()); 11690 } 11691 11692 keytoolArguments.add("-ext"); 11693 keytoolArguments.add("BasicConstraints=" + basicConstraintsValue); 11694 } 11695 11696 if (keyUsage != null) 11697 { 11698 final StringBuilder keyUsageValue = new StringBuilder(); 11699 if (keyUsage.isDigitalSignatureBitSet()) 11700 { 11701 commaAppend(keyUsageValue, "digitalSignature"); 11702 } 11703 11704 if (keyUsage.isNonRepudiationBitSet()) 11705 { 11706 commaAppend(keyUsageValue, "nonRepudiation"); 11707 } 11708 11709 if (keyUsage.isKeyEnciphermentBitSet()) 11710 { 11711 commaAppend(keyUsageValue, "keyEncipherment"); 11712 } 11713 11714 if (keyUsage.isDataEnciphermentBitSet()) 11715 { 11716 commaAppend(keyUsageValue, "dataEncipherment"); 11717 } 11718 11719 if (keyUsage.isKeyAgreementBitSet()) 11720 { 11721 commaAppend(keyUsageValue, "keyAgreement"); 11722 } 11723 11724 if (keyUsage.isKeyCertSignBitSet()) 11725 { 11726 commaAppend(keyUsageValue, "keyCertSign"); 11727 } 11728 11729 if (keyUsage.isCRLSignBitSet()) 11730 { 11731 commaAppend(keyUsageValue, "cRLSign"); 11732 } 11733 11734 if (keyUsage.isEncipherOnlyBitSet()) 11735 { 11736 commaAppend(keyUsageValue, "encipherOnly"); 11737 } 11738 11739 if (keyUsage.isEncipherOnlyBitSet()) 11740 { 11741 commaAppend(keyUsageValue, "decipherOnly"); 11742 } 11743 11744 keytoolArguments.add("-ext"); 11745 keytoolArguments.add("KeyUsage=" + keyUsageValue); 11746 } 11747 11748 if (extendedKeyUsage != null) 11749 { 11750 final StringBuilder extendedKeyUsageValue = new StringBuilder(); 11751 for (final OID oid : extendedKeyUsage.getKeyPurposeIDs()) 11752 { 11753 final ExtendedKeyUsageID id = ExtendedKeyUsageID.forOID(oid); 11754 if (id == null) 11755 { 11756 commaAppend(extendedKeyUsageValue, oid.toString()); 11757 } 11758 else 11759 { 11760 switch (id) 11761 { 11762 case TLS_SERVER_AUTHENTICATION: 11763 commaAppend(extendedKeyUsageValue, "serverAuth"); 11764 break; 11765 case TLS_CLIENT_AUTHENTICATION: 11766 commaAppend(extendedKeyUsageValue, "clientAuth"); 11767 break; 11768 case CODE_SIGNING: 11769 commaAppend(extendedKeyUsageValue, "codeSigning"); 11770 break; 11771 case EMAIL_PROTECTION: 11772 commaAppend(extendedKeyUsageValue, "emailProtection"); 11773 break; 11774 case TIME_STAMPING: 11775 commaAppend(extendedKeyUsageValue, "timeStamping"); 11776 break; 11777 case OCSP_SIGNING: 11778 commaAppend(extendedKeyUsageValue, "OCSPSigning"); 11779 break; 11780 default: 11781 // This should never happen. 11782 commaAppend(extendedKeyUsageValue, id.getOID().toString()); 11783 break; 11784 } 11785 } 11786 } 11787 11788 keytoolArguments.add("-ext"); 11789 keytoolArguments.add("ExtendedKeyUsage=" + extendedKeyUsageValue); 11790 } 11791 11792 if (! sanValues.isEmpty()) 11793 { 11794 final StringBuilder subjectAltNameValue = new StringBuilder(); 11795 for (final String sanValue : sanValues) 11796 { 11797 commaAppend(subjectAltNameValue, sanValue); 11798 } 11799 11800 keytoolArguments.add("-ext"); 11801 keytoolArguments.add("SAN=" + subjectAltNameValue); 11802 } 11803 11804 if (! ianValues.isEmpty()) 11805 { 11806 final StringBuilder issuerAltNameValue = new StringBuilder(); 11807 for (final String ianValue : ianValues) 11808 { 11809 commaAppend(issuerAltNameValue, ianValue); 11810 } 11811 11812 keytoolArguments.add("-ext"); 11813 keytoolArguments.add("IAN=" + issuerAltNameValue); 11814 } 11815 11816 for (final X509CertificateExtension e : genericExtensions) 11817 { 11818 keytoolArguments.add("-ext"); 11819 if (e.isCritical()) 11820 { 11821 keytoolArguments.add(e.getOID().toString() + ":critical=" + 11822 toColonDelimitedHex(e.getValue())); 11823 } 11824 else 11825 { 11826 keytoolArguments.add(e.getOID().toString() + '=' + 11827 toColonDelimitedHex(e.getValue())); 11828 } 11829 } 11830 } 11831 11832 11833 11834 /** 11835 * Appends the provided value to the given buffer. If the buffer is not 11836 * empty, the new value will be preceded by a comma. There will not be any 11837 * spaces on either side of the comma. 11838 * 11839 * @param buffer The buffer to which the value should be appended. 11840 * @param value The value to append to the buffer. 11841 */ 11842 private static void commaAppend(final StringBuilder buffer, 11843 final String value) 11844 { 11845 if (buffer.length() > 0) 11846 { 11847 buffer.append(','); 11848 } 11849 11850 buffer.append(value); 11851 } 11852 11853 11854 11855 /** 11856 * Retrieves a set of information that may be used to generate example usage 11857 * information. Each element in the returned map should consist of a map 11858 * between an example set of arguments and a string that describes the 11859 * behavior of the tool when invoked with that set of arguments. 11860 * 11861 * @return A set of information that may be used to generate example usage 11862 * information. It may be {@code null} or empty if no example usage 11863 * information is available. 11864 */ 11865 @Override() 11866 public LinkedHashMap<String[],String> getExampleUsages() 11867 { 11868 final String keystorePath = getPlatformSpecificPath("config", "keystore"); 11869 final String keystorePWPath = 11870 getPlatformSpecificPath("config", "keystore.pin"); 11871 final String privateKeyPWPath = 11872 getPlatformSpecificPath("config", "server-cert-private-key.pin"); 11873 final String exportCertOutputFile = 11874 getPlatformSpecificPath("server-cert.crt"); 11875 final String exportKeyOutputFile = 11876 getPlatformSpecificPath("server-cert.private-key"); 11877 final String genCSROutputFile = getPlatformSpecificPath("server-cert.csr"); 11878 final String truststorePath = 11879 getPlatformSpecificPath("config", "truststore"); 11880 final String truststorePWPath = 11881 getPlatformSpecificPath("config", "truststore.pin"); 11882 11883 final LinkedHashMap<String[],String> examples = 11884 new LinkedHashMap<>(StaticUtils.computeMapCapacity(20)); 11885 11886 examples.put( 11887 new String[] 11888 { 11889 "list-certificates", 11890 "--keystore", keystorePath, 11891 "--keystore-password-file", keystorePWPath, 11892 "--verbose", 11893 "--display-keytool-command" 11894 }, 11895 INFO_MANAGE_CERTS_EXAMPLE_LIST_1.get(keystorePath)); 11896 11897 examples.put( 11898 new String[] 11899 { 11900 "export-certificate", 11901 "--keystore", keystorePath, 11902 "--keystore-password-file", keystorePWPath, 11903 "--alias", "server-cert", 11904 "--output-file", exportCertOutputFile, 11905 "--output-format", "PEM", 11906 "--verbose", 11907 "--display-keytool-command" 11908 }, 11909 INFO_MANAGE_CERTS_EXAMPLE_EXPORT_CERT_1.get(keystorePath, 11910 exportCertOutputFile)); 11911 11912 examples.put( 11913 new String[] 11914 { 11915 "export-private-key", 11916 "--keystore", keystorePath, 11917 "--keystore-password-file", keystorePWPath, 11918 "--private-key-password-file", privateKeyPWPath, 11919 "--alias", "server-cert", 11920 "--output-file", exportKeyOutputFile, 11921 "--output-format", "PEM", 11922 "--verbose", 11923 "--display-keytool-command" 11924 }, 11925 INFO_MANAGE_CERTS_EXAMPLE_EXPORT_KEY_1.get(keystorePath, 11926 exportKeyOutputFile)); 11927 11928 examples.put( 11929 new String[] 11930 { 11931 "import-certificate", 11932 "--keystore", keystorePath, 11933 "--keystore-type", "JKS", 11934 "--keystore-password-file", keystorePWPath, 11935 "--alias", "server-cert", 11936 "--certificate-file", exportCertOutputFile, 11937 "--private-key-file", exportKeyOutputFile, 11938 "--display-keytool-command" 11939 }, 11940 INFO_MANAGE_CERTS_EXAMPLE_IMPORT_1.get(exportCertOutputFile, 11941 exportKeyOutputFile, keystorePath)); 11942 11943 examples.put( 11944 new String[] 11945 { 11946 "delete-certificate", 11947 "--keystore", keystorePath, 11948 "--keystore-password-file", keystorePWPath, 11949 "--alias", "server-cert" 11950 }, 11951 INFO_MANAGE_CERTS_EXAMPLE_DELETE_1.get(keystorePath)); 11952 11953 examples.put( 11954 new String[] 11955 { 11956 "generate-self-signed-certificate", 11957 "--keystore", keystorePath, 11958 "--keystore-type", "PKCS12", 11959 "--keystore-password-file", keystorePWPath, 11960 "--alias", "ca-cert", 11961 "--subject-dn", "CN=Example Authority,O=Example Corporation,C=US", 11962 "--days-valid", "7300", 11963 "--validity-start-time", "20170101000000", 11964 "--key-algorithm", "RSA", 11965 "--key-size-bits", "4096", 11966 "--signature-algorithm", "SHA256withRSA", 11967 "--basic-constraints-is-ca", "true", 11968 "--key-usage", "key-cert-sign", 11969 "--key-usage", "crl-sign", 11970 "--display-keytool-command" 11971 }, 11972 INFO_MANAGE_CERTS_EXAMPLE_GEN_CERT_1.get(keystorePath)); 11973 11974 examples.put( 11975 new String[] 11976 { 11977 "generate-certificate-signing-request", 11978 "--keystore", keystorePath, 11979 "--keystore-type", "PKCS12", 11980 "--keystore-password-file", keystorePWPath, 11981 "--output-file", genCSROutputFile, 11982 "--alias", "server-cert", 11983 "--subject-dn", "CN=ldap.example.com,O=Example Corporation,C=US", 11984 "--key-algorithm", "EC", 11985 "--key-size-bits", "256", 11986 "--signature-algorithm", "SHA256withECDSA", 11987 "--subject-alternative-name-dns", "ldap1.example.com", 11988 "--subject-alternative-name-dns", "ldap2.example.com", 11989 "--extended-key-usage", "server-auth", 11990 "--extended-key-usage", "client-auth", 11991 "--display-keytool-command" 11992 }, 11993 INFO_MANAGE_CERTS_EXAMPLE_GEN_CSR_1.get(keystorePath, 11994 genCSROutputFile)); 11995 11996 examples.put( 11997 new String[] 11998 { 11999 "generate-certificate-signing-request", 12000 "--keystore", keystorePath, 12001 "--keystore-password-file", keystorePWPath, 12002 "--alias", "server-cert", 12003 "--use-existing-key-pair", 12004 "--inherit-extensions", 12005 "--display-keytool-command" 12006 }, 12007 INFO_MANAGE_CERTS_EXAMPLE_GEN_CSR_2.get(keystorePath)); 12008 12009 examples.put( 12010 new String[] 12011 { 12012 "sign-certificate-signing-request", 12013 "--keystore", keystorePath, 12014 "--keystore-password-file", keystorePWPath, 12015 "--request-input-file", genCSROutputFile, 12016 "--certificate-output-file", exportCertOutputFile, 12017 "--alias", "ca-cert", 12018 "--days-valid", "730", 12019 "--include-requested-extensions", 12020 "--display-keytool-command" 12021 }, 12022 INFO_MANAGE_CERTS_EXAMPLE_SIGN_CERT_1.get(keystorePath, 12023 genCSROutputFile, exportCertOutputFile)); 12024 12025 examples.put( 12026 new String[] 12027 { 12028 "change-certificate-alias", 12029 "--keystore", keystorePath, 12030 "--keystore-password-file", keystorePWPath, 12031 "--current-alias", "server-cert", 12032 "--new-alias", "server-certificate", 12033 "--display-keytool-command" 12034 }, 12035 INFO_MANAGE_CERTS_EXAMPLE_CHANGE_ALIAS_1.get(keystorePath, 12036 genCSROutputFile, exportCertOutputFile)); 12037 12038 examples.put( 12039 new String[] 12040 { 12041 "change-keystore-password", 12042 "--keystore", getPlatformSpecificPath("config", "keystore"), 12043 "--current-keystore-password-file", 12044 getPlatformSpecificPath("config", "current.pin"), 12045 "--new-keystore-password-file", 12046 getPlatformSpecificPath("config", "new.pin"), 12047 "--display-keytool-command" 12048 }, 12049 INFO_MANAGE_CERTS_SC_CHANGE_KS_PW_EXAMPLE_1.get( 12050 getPlatformSpecificPath("config", "keystore"), 12051 getPlatformSpecificPath("config", "current.pin"), 12052 getPlatformSpecificPath("config", "new.pin"))); 12053 12054 examples.put( 12055 new String[] 12056 { 12057 "trust-server-certificate", 12058 "--hostname", "ldap.example.com", 12059 "--port", "636", 12060 "--keystore", truststorePath, 12061 "--keystore-password-file", truststorePWPath, 12062 "--alias", "ldap.example.com:636" 12063 }, 12064 INFO_MANAGE_CERTS_EXAMPLE_TRUST_SERVER_1.get(truststorePath)); 12065 12066 examples.put( 12067 new String[] 12068 { 12069 "check-certificate-usability", 12070 "--keystore", keystorePath, 12071 "--keystore-password-file", keystorePWPath, 12072 "--alias", "server-cert" 12073 }, 12074 INFO_MANAGE_CERTS_EXAMPLE_CHECK_USABILITY_1.get(keystorePath)); 12075 12076 examples.put( 12077 new String[] 12078 { 12079 "display-certificate-file", 12080 "--certificate-file", exportCertOutputFile, 12081 "--verbose", 12082 "--display-keytool-command" 12083 }, 12084 INFO_MANAGE_CERTS_EXAMPLE_DISPLAY_CERT_1.get(keystorePath)); 12085 12086 examples.put( 12087 new String[] 12088 { 12089 "display-certificate-signing-request-file", 12090 "--certificate-signing-request-file", genCSROutputFile, 12091 "--display-keytool-command" 12092 }, 12093 INFO_MANAGE_CERTS_EXAMPLE_DISPLAY_CSR_1.get(keystorePath)); 12094 12095 examples.put( 12096 new String[] 12097 { 12098 "--help-subcommands" 12099 }, 12100 INFO_MANAGE_CERTS_EXAMPLE_HELP_SUBCOMMANDS_1.get(keystorePath)); 12101 12102 return examples; 12103 } 12104}