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