001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2012-2015 ForgeRock AS. 026 */ 027package org.opends.server.tools; 028 029import static org.opends.messages.ConfigMessages.*; 030import static org.opends.messages.ExtensionMessages.*; 031import static org.opends.messages.ProtocolMessages.*; 032import static org.opends.messages.ToolMessages.*; 033import static org.opends.server.config.ConfigConstants.*; 034import static org.opends.server.util.ServerConstants.*; 035import static org.opends.server.util.StaticUtils.*; 036 037import static com.forgerock.opendj.cli.ArgumentConstants.*; 038import static com.forgerock.opendj.cli.Utils.*; 039 040import java.io.File; 041import java.io.OutputStream; 042import java.io.PrintStream; 043import java.io.StringReader; 044import java.net.InetAddress; 045import java.security.GeneralSecurityException; 046import java.util.Collection; 047import java.util.HashSet; 048import java.util.LinkedList; 049import java.util.List; 050import java.util.Set; 051 052import javax.crypto.Cipher; 053 054import org.forgerock.i18n.LocalizableMessage; 055import org.forgerock.opendj.config.ManagedObjectDefinition; 056import org.forgerock.opendj.server.config.client.BackendCfgClient; 057import org.forgerock.opendj.server.config.server.BackendCfg; 058import org.opends.quicksetup.installer.Installer; 059import org.opends.server.admin.DefaultBehaviorProvider; 060import org.opends.server.admin.DefinedDefaultBehaviorProvider; 061import org.opends.server.admin.StringPropertyDefinition; 062import org.opends.server.admin.std.meta.CryptoManagerCfgDefn; 063import org.opends.server.api.ConfigHandler; 064import org.opends.server.config.BooleanConfigAttribute; 065import org.opends.server.config.ConfigEntry; 066import org.opends.server.config.DNConfigAttribute; 067import org.opends.server.config.IntegerConfigAttribute; 068import org.opends.server.config.StringConfigAttribute; 069import org.opends.server.core.DirectoryServer; 070import org.opends.server.core.LockFileManager; 071import org.opends.server.extensions.ConfigFileHandler; 072import org.opends.server.extensions.SaltedSHA512PasswordStorageScheme; 073import org.opends.server.protocols.ldap.LDAPResultCode; 074import org.opends.server.types.DN; 075import org.opends.server.types.DirectoryEnvironmentConfig; 076import org.opends.server.types.DirectoryException; 077import org.opends.server.types.Entry; 078import org.opends.server.types.InitializationException; 079import org.opends.server.types.LDIFImportConfig; 080import org.opends.server.types.NullOutputStream; 081import org.opends.server.util.LDIFReader; 082 083import com.forgerock.opendj.cli.Argument; 084import com.forgerock.opendj.cli.ArgumentException; 085import com.forgerock.opendj.cli.ArgumentParser; 086import com.forgerock.opendj.cli.BooleanArgument; 087import com.forgerock.opendj.cli.CliConstants; 088import com.forgerock.opendj.cli.CommonArguments; 089import com.forgerock.opendj.cli.FileBasedArgument; 090import com.forgerock.opendj.cli.IntegerArgument; 091import com.forgerock.opendj.cli.StringArgument; 092 093/** 094 * This class provides a very basic tool that can be used to configure some of 095 * the most important settings in the Directory Server. This configuration is 096 * performed by editing the server's configuration files and therefore the 097 * Directory Server must be offline. This utility will be used during the 098 * Directory Server installation process. 099 * <BR><BR> 100 * The options that this tool can currently set include: 101 * <BR> 102 * <UL> 103 * <LI>The port on which the server will listen for LDAP communication</LI> 104 * <LI>The DN and password for the initial root user. 105 * <LI>The set of base DNs for user data</LI> 106 * </UL> 107 */ 108public class ConfigureDS 109{ 110 private static final boolean WRONG_USAGE = true; 111 112 /** Private exception class to handle error message printing. */ 113 @SuppressWarnings("serial") 114 private class ConfigureDSException extends Exception 115 { 116 private final int returnedErrorCode; 117 private final LocalizableMessage errorMessage; 118 private final boolean wrongUsage; 119 120 ConfigureDSException(final LocalizableMessage errorMessage) 121 { 122 this(new Exception("An error occured in ConfigureDS: " + errorMessage), errorMessage, false); 123 } 124 125 ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage) 126 { 127 this(parentException, errorMessage, false); 128 } 129 130 ConfigureDSException(final LocalizableMessage errorMessage, final boolean showUsage) 131 { 132 this(new Exception("An error occured in ConfigureDS: " + errorMessage), errorMessage, showUsage); 133 } 134 135 ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage, 136 final boolean showUsage) 137 { 138 this(parentException, errorMessage, showUsage, ERROR); 139 } 140 141 ConfigureDSException(final Exception parentException, final LocalizableMessage errorMessage, 142 final boolean wrongUsage, final int retCode) 143 { 144 super(parentException); 145 this.errorMessage = errorMessage; 146 this.wrongUsage = wrongUsage; 147 returnedErrorCode = retCode; 148 } 149 150 private LocalizableMessage getErrorMessage() 151 { 152 return errorMessage; 153 } 154 155 private boolean isWrongUsage() 156 { 157 return wrongUsage; 158 } 159 160 private int getErrorCode() 161 { 162 return returnedErrorCode; 163 } 164 } 165 166 //FIXME: Find a better way to do to prevent hardcoded ldif entries. 167 private static final String NEW_LINE = System.getProperty("line.separator"); 168 169 private static final String JCKES_KEY_MANAGER_DN = "cn=JCEKS,cn=Key Manager Providers,cn=config"; 170 private static final String JCKES_KEY_MANAGER_LDIF_ENTRY = 171 "dn: " + JCKES_KEY_MANAGER_DN + NEW_LINE 172 + "objectClass: top" + NEW_LINE 173 + "objectClass: ds-cfg-key-manager-provider" + NEW_LINE 174 + "objectClass: ds-cfg-file-based-key-manager-provider" + NEW_LINE 175 + "cn: JCEKS" + NEW_LINE 176 + "ds-cfg-java-class: org.opends.server.extensions.FileBasedKeyManagerProvider" + NEW_LINE 177 + "ds-cfg-enabled: true" + NEW_LINE 178 + "ds-cfg-key-store-type: JCEKS" + NEW_LINE 179 + "ds-cfg-key-store-file: config/keystore.jceks" + NEW_LINE 180 + "ds-cfg-key-store-pin-file: config/keystore.pin" + NEW_LINE; 181 182 private static final String JCKES_TRUST_MANAGER_DN = "cn=JCEKS,cn=Trust Manager Providers,cn=config"; 183 private static final String JCKES_TRUST_MANAGER_LDIF_ENTRY = 184 "dn: " + JCKES_TRUST_MANAGER_DN + NEW_LINE 185 + "objectClass: top" + NEW_LINE 186 + "objectClass: ds-cfg-trust-manager-provider" + NEW_LINE 187 + "objectClass: ds-cfg-file-based-trust-manager-provider" + NEW_LINE 188 + "cn: JCEKS" + NEW_LINE 189 + "ds-cfg-java-class: org.opends.server.extensions.FileBasedTrustManagerProvider" + NEW_LINE 190 + "ds-cfg-enabled: false" + NEW_LINE 191 + "ds-cfg-trust-store-type: JCEKS" + NEW_LINE 192 + "ds-cfg-trust-store-file: config/truststore" + NEW_LINE; 193 194 /** The fully-qualified name of this class. */ 195 private static final String CLASS_NAME = "org.opends.server.tools.ConfigureDS"; 196 197 /** The DN of the configuration entry defining the LDAP connection handler. */ 198 public static final String DN_LDAP_CONNECTION_HANDLER = "cn=LDAP Connection Handler," + DN_CONNHANDLER_BASE; 199 200 /** The DN of the configuration entry defining the Administration connector. */ 201 public static final String DN_ADMIN_CONNECTOR = "cn=Administration Connector," + DN_CONFIG_ROOT; 202 203 /** The DN of the configuration entry defining the LDAPS connection handler. */ 204 private static final String DN_LDAPS_CONNECTION_HANDLER = "cn=LDAPS Connection Handler," + DN_CONNHANDLER_BASE; 205 206 /** The DN of the configuration entry defining the JMX connection handler. */ 207 private static final String DN_JMX_CONNECTION_HANDLER = "cn=JMX Connection Handler," + DN_CONNHANDLER_BASE; 208 209 /** The DN of the configuration entry defining the initial root user. */ 210 public static final String DN_ROOT_USER = "cn=Directory Manager," + DN_ROOT_DN_CONFIG_BASE; 211 212 /** The DN of the Crypto Manager. */ 213 public static final String DN_CRYPTO_MANAGER = "cn=Crypto Manager,cn=config"; 214 215 /** The DN of the DIGEST-MD5 SASL mechanism handler. */ 216 public static final String DN_DIGEST_MD5_SASL_MECHANISM = "cn=DIGEST-MD5,cn=SASL Mechanisms,cn=config"; 217 218 private static int SUCCESS = 0; 219 private static int ERROR = 1; 220 221 /** 222 * Provides the command-line arguments to the <CODE>configMain</CODE> method 223 * for processing. 224 * 225 * @param args The set of command-line arguments provided to this program. 226 */ 227 public static void main(String[] args) 228 { 229 final int exitCode = configMain(args, System.out, System.err); 230 if (exitCode != SUCCESS) 231 { 232 System.exit(filterExitCode(exitCode)); 233 } 234 } 235 236 /** 237 * Parses the provided command-line arguments and makes the appropriate 238 * changes to the Directory Server configuration. 239 * 240 * @param args The command-line arguments provided to this program. 241 * 242 * @param outStream Output stream. 243 * @param errStream Error stream. 244 * @return The exit code from the configuration processing. A nonzero value 245 * indicates that there was some kind of problem during the 246 * configuration processing. 247 */ 248 public static int configMain(final String[] args, final OutputStream outStream, final OutputStream errStream) 249 { 250 final ConfigureDS tool = new ConfigureDS(args, outStream, errStream); 251 return tool.run(); 252 } 253 254 private final String[] arguments; 255 private final PrintStream out; 256 private final PrintStream err; 257 258 private final ArgumentParser argParser; 259 260 private BooleanArgument showUsage; 261 private BooleanArgument enableStartTLS; 262 private FileBasedArgument rootPasswordFile; 263 private StringArgument hostName; 264 private IntegerArgument ldapPort; 265 private IntegerArgument adminConnectorPort; 266 private IntegerArgument ldapsPort; 267 private IntegerArgument jmxPort; 268 private StringArgument baseDNString; 269 private StringArgument configClass; 270 private StringArgument configFile; 271 private StringArgument rootDNString; 272 private StringArgument rootPassword; 273 private StringArgument keyManagerProviderDN; 274 private StringArgument trustManagerProviderDN; 275 private StringArgument certNickName; 276 private StringArgument keyManagerPath; 277 private StringArgument serverRoot; 278 private StringArgument backendType; 279 280 private final String serverLockFileName = LockFileManager.getServerLockFileName(); 281 private final StringBuilder failureReason = new StringBuilder(); 282 private ConfigHandler<?> configHandler; 283 284 private ConfigureDS(final String[] args, final OutputStream outStream, final OutputStream errStream) 285 { 286 arguments = args; 287 out = NullOutputStream.wrapOrNullStream(outStream); 288 err = NullOutputStream.wrapOrNullStream(errStream); 289 argParser = new ArgumentParser(CLASS_NAME, INFO_CONFIGDS_TOOL_DESCRIPTION.get(), false); 290 } 291 292 private int run() 293 { 294 try 295 { 296 initializeArguments(); 297 parseArguments(); 298 if (argParser.usageOrVersionDisplayed()) 299 { 300 return SUCCESS; 301 } 302 303 checkArgumentsConsistency(); 304 checkPortArguments(); 305 306 tryAcquireExclusiveLocks(); 307 updateBaseDNs(parseProvidedBaseDNs()); 308 309 initializeDirectoryServer(); 310 311 final DN rootDN = parseRootDN(); 312 final String rootPW = parseRootDNPassword(); 313 314 // Get the Directory Server configuration handler and use it to make the 315 // appropriate configuration changes. 316 configHandler = DirectoryServer.getConfigHandler(); 317 318 checkManagerProvider(keyManagerProviderDN, JCKES_KEY_MANAGER_DN, JCKES_KEY_MANAGER_LDIF_ENTRY, true); 319 checkManagerProvider(trustManagerProviderDN, JCKES_TRUST_MANAGER_DN, JCKES_TRUST_MANAGER_LDIF_ENTRY, false); 320 // Check that the keystore path values are valid. 321 if (keyManagerPath.isPresent() && !keyManagerProviderDN.isPresent()) 322 { 323 final LocalizableMessage message = ERR_CONFIGDS_KEYMANAGER_PROVIDER_DN_REQUIRED.get( 324 keyManagerProviderDN.getLongIdentifier(), keyManagerPath.getLongIdentifier()); 325 throw new ConfigureDSException(message); 326 } 327 328 updateLdapPort(); 329 updateAdminConnectorPort(); 330 updateLdapSecurePort(); 331 updateJMXport(); 332 updateStartTLS(); 333 updateKeyManager(); 334 updateTrustManager(); 335 updateRootUser(rootDN, rootPW); 336 addFQDNDigestMD5(); 337 updateCryptoCipher(); 338 writeUpdatedConfiguration(); 339 340 return SUCCESS; 341 } 342 catch (final ConfigureDSException e) 343 { 344 if (e.isWrongUsage()) 345 { 346 argParser.displayMessageAndUsageReference(err, e.getErrorMessage()); 347 } 348 else 349 { 350 printWrappedText(err, e.getErrorMessage()); 351 } 352 return e.getErrorCode(); 353 } 354 finally 355 { 356 LockFileManager.releaseLock(serverLockFileName, failureReason); 357 } 358 } 359 360 private void initializeArguments() throws ConfigureDSException 361 { 362 try 363 { 364 configFile = new StringArgument( 365 "configfile", 'c', "configFile", 366 true, false, true, INFO_CONFIGFILE_PLACEHOLDER.get(), 367 null, null, INFO_DESCRIPTION_CONFIG_FILE.get()); 368 configFile.setHidden(true); 369 argParser.addArgument(configFile); 370 371 configClass = new StringArgument( 372 "configclass", OPTION_SHORT_CONFIG_CLASS, OPTION_LONG_CONFIG_CLASS, 373 false, false, true, INFO_CONFIGCLASS_PLACEHOLDER.get(), 374 ConfigFileHandler.class.getName(), null, INFO_DESCRIPTION_CONFIG_CLASS.get()); 375 configClass.setHidden(true); 376 argParser.addArgument(configClass); 377 378 String defaultHostName; 379 try 380 { 381 defaultHostName = InetAddress.getLocalHost().getHostName(); 382 } 383 catch (final Exception e) 384 { 385 // Not much we can do here. 386 defaultHostName = "localhost"; 387 } 388 389 hostName = new StringArgument( 390 OPTION_LONG_HOST.toLowerCase(), OPTION_SHORT_HOST, OPTION_LONG_HOST, 391 false, false, true, INFO_HOST_PLACEHOLDER.get(), 392 defaultHostName, null, INFO_INSTALLDS_DESCRIPTION_HOST_NAME.get()); 393 argParser.addArgument(hostName); 394 395 ldapPort = new IntegerArgument( 396 "ldapport", OPTION_SHORT_PORT, "ldapPort", 397 false, false, true, INFO_LDAPPORT_PLACEHOLDER.get(), 398 389, null, true, 1, true, 65535, INFO_CONFIGDS_DESCRIPTION_LDAP_PORT.get()); 399 argParser.addArgument(ldapPort); 400 401 adminConnectorPort = new IntegerArgument( 402 "adminConnectorPort".toLowerCase(), null, "adminConnectorPort", 403 false, false, true, INFO_PORT_PLACEHOLDER.get(), 404 4444, "adminConnectorPort", true, 1, true, 65535, INFO_INSTALLDS_DESCRIPTION_ADMINCONNECTORPORT.get()); 405 argParser.addArgument(adminConnectorPort); 406 407 ldapsPort = new IntegerArgument( 408 "ldapsPort", 'P', "ldapsPort", 409 false, false, true, INFO_LDAPPORT_PLACEHOLDER.get(), 410 636, null, true, 1, true, 65535, INFO_CONFIGDS_DESCRIPTION_LDAPS_PORT.get()); 411 argParser.addArgument(ldapsPort); 412 413 enableStartTLS = new BooleanArgument( 414 "enableStartTLS", OPTION_SHORT_START_TLS, "enableStartTLS", 415 INFO_CONFIGDS_DESCRIPTION_ENABLE_START_TLS.get()); 416 argParser.addArgument(enableStartTLS); 417 418 jmxPort = new IntegerArgument( 419 "jmxport", 'x', "jmxPort", 420 false, false, true, INFO_JMXPORT_PLACEHOLDER.get(), 421 CliConstants.DEFAULT_JMX_PORT, null, true, 1, true, 65535, INFO_CONFIGDS_DESCRIPTION_JMX_PORT.get()); 422 argParser.addArgument(jmxPort); 423 424 keyManagerProviderDN = new StringArgument( 425 "keymanagerproviderdn", 'k', "keyManagerProviderDN", 426 false, false, true, INFO_KEY_MANAGER_PROVIDER_DN_PLACEHOLDER.get(), 427 null, null, INFO_CONFIGDS_DESCRIPTION_KEYMANAGER_PROVIDER_DN.get()); 428 argParser.addArgument(keyManagerProviderDN); 429 430 trustManagerProviderDN = new StringArgument( 431 "trustmanagerproviderdn", 't', "trustManagerProviderDN", 432 false, false, true, INFO_TRUST_MANAGER_PROVIDER_DN_PLACEHOLDER.get(), 433 null, null, INFO_CONFIGDS_DESCRIPTION_TRUSTMANAGER_PROVIDER_DN.get()); 434 argParser.addArgument(trustManagerProviderDN); 435 436 keyManagerPath = new StringArgument( 437 "keymanagerpath", 'm', "keyManagerPath", 438 false, false, true, INFO_KEY_MANAGER_PATH_PLACEHOLDER.get(), 439 null, null, INFO_CONFIGDS_DESCRIPTION_KEYMANAGER_PATH.get()); 440 argParser.addArgument(keyManagerPath); 441 442 certNickName = new StringArgument( 443 "certnickname", 'a', "certNickName", 444 false, false, true, INFO_NICKNAME_PLACEHOLDER.get(), 445 null, null, INFO_CONFIGDS_DESCRIPTION_CERTNICKNAME.get()); 446 argParser.addArgument(certNickName); 447 448 baseDNString = new StringArgument( 449 "basedn", OPTION_SHORT_BASEDN, OPTION_LONG_BASEDN, 450 false, true, true, INFO_BASEDN_PLACEHOLDER.get(), 451 "dc=example,dc=com", null, INFO_CONFIGDS_DESCRIPTION_BASE_DN.get()); 452 argParser.addArgument(baseDNString); 453 454 rootDNString = new StringArgument( 455 "rootdn", OPTION_SHORT_ROOT_USER_DN, OPTION_LONG_ROOT_USER_DN, 456 false, false, true, INFO_ROOT_USER_DN_PLACEHOLDER.get(), 457 "cn=Directory Manager", null, INFO_CONFIGDS_DESCRIPTION_ROOT_DN.get()); 458 argParser.addArgument(rootDNString); 459 460 rootPassword = new StringArgument( 461 "rootpw", OPTION_SHORT_BINDPWD, "rootPassword", 462 false, false, true, INFO_ROOT_USER_PWD_PLACEHOLDER.get(), 463 null, null, INFO_CONFIGDS_DESCRIPTION_ROOT_PW.get()); 464 argParser.addArgument(rootPassword); 465 466 rootPasswordFile = new FileBasedArgument( 467 "rootpwfile", OPTION_SHORT_BINDPWD_FILE, "rootPasswordFile", 468 false, false, INFO_FILE_PLACEHOLDER.get(), 469 null, null, INFO_CONFIGDS_DESCRIPTION_ROOT_PW_FILE.get()); 470 argParser.addArgument(rootPasswordFile); 471 472 showUsage = CommonArguments.getShowUsage(); 473 argParser.addArgument(showUsage); 474 argParser.setUsageArgument(showUsage); 475 476 serverRoot = new StringArgument( 477 "serverRoot", OPTION_SHORT_SERVER_ROOT, OPTION_LONG_SERVER_ROOT, 478 false, false, true, INFO_SERVER_ROOT_DIR_PLACEHOLDER.get(), 479 null, null, null); 480 serverRoot.setHidden(true); 481 argParser.addArgument(serverRoot); 482 483 backendType = new StringArgument( 484 OPTION_LONG_BACKEND_TYPE.toLowerCase(), null, OPTION_LONG_BACKEND_TYPE, 485 false, false, true, INFO_INSTALLDS_BACKEND_TYPE_PLACEHOLDER.get(), 486 null, OPTION_LONG_BACKEND_TYPE, INFO_INSTALLDS_DESCRIPTION_BACKEND_TYPE.get() 487 ); 488 argParser.addArgument(backendType); 489 } 490 catch (final ArgumentException ae) 491 { 492 throw new ConfigureDSException(ae, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage())); 493 } 494 } 495 496 private int parseArguments() throws ConfigureDSException 497 { 498 try 499 { 500 argParser.parseArguments(arguments); 501 return SUCCESS; 502 } 503 catch (final ArgumentException ae) 504 { 505 throw new ConfigureDSException(ae, ERR_ERROR_PARSING_ARGS.get(ae.getMessage()), 506 WRONG_USAGE, LDAPResultCode.CLIENT_SIDE_PARAM_ERROR); 507 } 508 } 509 510 /** Make sure that the user actually tried to configure something. */ 511 private void checkArgumentsConsistency() throws ConfigureDSException 512 { 513 if (!baseDNString.isPresent() 514 && !ldapPort.isPresent() 515 && !jmxPort.isPresent() 516 && !rootDNString.isPresent()) 517 { 518 throw new ConfigureDSException(ERR_CONFIGDS_NO_CONFIG_CHANGES.get(), WRONG_USAGE); 519 } 520 } 521 522 private void checkPortArguments() throws ConfigureDSException 523 { 524 try 525 { 526 final IntegerArgument[] portArgs = {ldapPort, adminConnectorPort, ldapsPort, jmxPort}; 527 final Set<Integer> portsAdded = new HashSet<>(); 528 529 for (final IntegerArgument portArg : portArgs) 530 { 531 if (portArg.isPresent()) 532 { 533 final int portNumber = portArg.getIntValue(); 534 if (portsAdded.contains(portNumber)) 535 { 536 throw new ConfigureDSException(ERR_CONFIGDS_PORT_ALREADY_SPECIFIED.get(portArg.getIntValue()), WRONG_USAGE); 537 } 538 portsAdded.add(portNumber); 539 } 540 } 541 } 542 catch (final ArgumentException ae) 543 { 544 throw new ConfigureDSException(ae, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage())); 545 } 546 } 547 548 private void initializeDirectoryServer() throws ConfigureDSException 549 { 550 if (serverRoot.isPresent()) { 551 final DirectoryEnvironmentConfig env = DirectoryServer.getEnvironmentConfig(); 552 final String root = serverRoot.getValue(); 553 try { 554 env.setServerRoot(new File(serverRoot.getValue())); 555 } catch (final InitializationException e) { 556 ERR_INITIALIZE_SERVER_ROOT.get(root, e.getMessageObject()); 557 } 558 } 559 560 // Initialize the Directory Server configuration handler using the 561 // information that was provided. 562 final DirectoryServer directoryServer = DirectoryServer.getInstance(); 563 DirectoryServer.bootstrapClient(); 564 565 try 566 { 567 DirectoryServer.initializeJMX(); 568 } 569 catch (final Exception e) 570 { 571 final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_JMX.get(configFile.getValue(), e.getMessage()); 572 throw new ConfigureDSException(e, msg); 573 } 574 575 try 576 { 577 directoryServer.initializeConfiguration(configClass.getValue(), configFile.getValue()); 578 } 579 catch (final Exception e) 580 { 581 final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_CONFIG.get(configFile.getValue(), e.getMessage()); 582 throw new ConfigureDSException(e, msg); 583 } 584 585 try 586 { 587 directoryServer.initializeSchema(); 588 } 589 catch (final Exception e) 590 { 591 final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_INITIALIZE_SCHEMA.get(configFile.getValue(), e.getMessage()); 592 throw new ConfigureDSException(e, msg); 593 } 594 } 595 596 /** 597 * Make sure that we can get an exclusive lock for the Directory Server, so 598 * that no other operation will be allowed while this is in progress. 599 * 600 * @throws ConfigureDSException 601 */ 602 private void tryAcquireExclusiveLocks() throws ConfigureDSException 603 { 604 if (! LockFileManager.acquireExclusiveLock(serverLockFileName, failureReason)) 605 { 606 throw new ConfigureDSException(ERR_CONFIGDS_CANNOT_ACQUIRE_SERVER_LOCK.get(serverLockFileName, failureReason)); 607 } 608 } 609 610 private LinkedList<org.forgerock.opendj.ldap.DN> parseProvidedBaseDNs() throws ConfigureDSException 611 { 612 LinkedList<org.forgerock.opendj.ldap.DN> baseDNs = new LinkedList<>(); 613 if (baseDNString.isPresent()) 614 { 615 for (final String dnString : baseDNString.getValues()) 616 { 617 try 618 { 619 baseDNs.add(org.forgerock.opendj.ldap.DN.valueOf(dnString)); 620 } 621 catch (final Exception e) 622 { 623 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_PARSE_BASE_DN.get(dnString, e.getMessage())); 624 } 625 } 626 } 627 628 return baseDNs; 629 } 630 631 private DN parseRootDN() throws ConfigureDSException 632 { 633 DN rootDN = null; 634 if (rootDNString.isPresent()) 635 { 636 try 637 { 638 rootDN = DN.valueOf(rootDNString.getValue()); 639 } 640 catch (final DirectoryException de) 641 { 642 final LocalizableMessage msg = ERR_CONFIGDS_CANNOT_PARSE_ROOT_DN.get( 643 rootDNString.getValue(), de.getMessageObject()); 644 throw new ConfigureDSException(de, msg); 645 } 646 } 647 return rootDN; 648 } 649 650 private String parseRootDNPassword() throws ConfigureDSException 651 { 652 String rootPW = null; 653 if (rootDNString.isPresent()) 654 { 655 if (rootPassword.isPresent()) 656 { 657 rootPW = rootPassword.getValue(); 658 } 659 else if (rootPasswordFile.isPresent()) 660 { 661 rootPW = rootPasswordFile.getValue(); 662 } 663 else 664 { 665 throw new ConfigureDSException(ERR_CONFIGDS_NO_ROOT_PW.get()); 666 } 667 } 668 return rootPW; 669 } 670 671 private void checkManagerProvider(final Argument arg, final String jckesDN, final String ldifEntry, 672 final boolean isKeyManager) throws ConfigureDSException 673 { 674 if (arg.isPresent()) 675 { 676 DN dn = null; 677 DN JCEKSManagerDN = null; 678 try 679 { 680 dn = DN.valueOf(trustManagerProviderDN.getValue()); 681 JCEKSManagerDN = DN.valueOf(jckesDN); 682 } 683 catch (final DirectoryException de) 684 { 685 final String value = trustManagerProviderDN.getValue(); 686 final LocalizableMessage errorMessage = de.getMessageObject(); 687 final LocalizableMessage message = 688 isKeyManager ? ERR_CONFIGDS_CANNOT_PARSE_KEYMANAGER_PROVIDER_DN.get(value, errorMessage) 689 : ERR_CONFIGDS_CANNOT_PARSE_TRUSTMANAGER_PROVIDER_DN.get(value, errorMessage); 690 throw new ConfigureDSException(de, message); 691 } 692 693 if (dn.equals(JCEKSManagerDN)) 694 { 695 LDIFReader reader = null; 696 try 697 { 698 699 final String ldif = ldifEntry; 700 final LDIFImportConfig ldifImportConfig = new LDIFImportConfig(new StringReader(ldif)); 701 reader = new LDIFReader(ldifImportConfig); 702 Entry mangerConfigEntry; 703 while ((mangerConfigEntry = reader.readEntry()) != null) 704 { 705 configHandler.addEntry(mangerConfigEntry, null); 706 } 707 } 708 catch (final Exception e) 709 { 710 final LocalizableMessage message = isKeyManager ? ERR_CONFIG_KEYMANAGER_CANNOT_CREATE_JCEKS_PROVIDER.get(e) 711 : ERR_CONFIG_KEYMANAGER_CANNOT_GET_BASE.get(e); 712 throw new ConfigureDSException(e, message); 713 } 714 finally 715 { 716 close(reader); 717 } 718 } 719 else 720 { 721 try 722 { 723 configHandler.getConfigEntry(dn); 724 } 725 catch (final Exception e) 726 { 727 final LocalizableMessage message = isKeyManager ? ERR_CONFIG_KEYMANAGER_CANNOT_GET_BASE.get(e) 728 : ERR_CONFIG_TRUSTMANAGER_CANNOT_GET_BASE.get(e); 729 throw new ConfigureDSException(e, message); 730 } 731 } 732 } 733 } 734 735 @SuppressWarnings("unchecked") 736 private void updateBaseDNs(final List<org.forgerock.opendj.ldap.DN> baseDNs) throws ConfigureDSException 737 { 738 if (!baseDNs.isEmpty()) 739 { 740 final String backendTypeName = backendType.getValue(); 741 final BackendTypeHelper backendTypeHelper = new BackendTypeHelper(); 742 final ManagedObjectDefinition<?, ?> backend = backendTypeHelper.retrieveBackendTypeFromName(backendTypeName); 743 if (backend == null) 744 { 745 throw new ConfigureDSException( 746 ERR_CONFIGDS_BACKEND_TYPE_UNKNOWN.get(backendTypeName, backendTypeHelper.getPrintableBackendTypeNames())); 747 } 748 749 try 750 { 751 BackendCreationHelper.createBackendOffline(Installer.ROOT_BACKEND_NAME, baseDNs, 752 (ManagedObjectDefinition<? extends BackendCfgClient, ? extends BackendCfg>) backend); 753 } 754 catch (Exception e) 755 { 756 throw new ConfigureDSException(ERR_CONFIGDS_SET_BACKEND_TYPE.get(backendTypeName, e.getMessage())); 757 } 758 } 759 } 760 761 private void updateLdapPort() throws ConfigureDSException 762 { 763 if (ldapPort.isPresent()) 764 { 765 try 766 { 767 final IntegerConfigAttribute portAttr = new IntegerConfigAttribute( 768 ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(), 769 true, false, true, true, 1, true, 65535, ldapPort.getIntValue()); 770 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAP_CONNECTION_HANDLER)); 771 configEntry.putConfigAttribute(portAttr); 772 } 773 catch (final Exception e) 774 { 775 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_LDAP_PORT.get(e)); 776 } 777 } 778 } 779 780 private void updateAdminConnectorPort() throws ConfigureDSException 781 { 782 if (adminConnectorPort.isPresent()) 783 { 784 try 785 { 786 final IntegerConfigAttribute portAttr = new IntegerConfigAttribute( 787 ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(), 788 true, false, true, true, 1, true, 65535, adminConnectorPort.getIntValue()); 789 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_ADMIN_CONNECTOR)); 790 configEntry.putConfigAttribute(portAttr); 791 } 792 catch (final Exception e) 793 { 794 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_ADMIN_CONNECTOR_PORT.get(e)); 795 } 796 } 797 } 798 799 private void updateLdapSecurePort() throws ConfigureDSException 800 { 801 if (ldapsPort.isPresent()) 802 { 803 try 804 { 805 final IntegerConfigAttribute portAttr = new IntegerConfigAttribute( 806 ATTR_LISTEN_PORT, INFO_LDAP_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(), 807 true, false, true, true, 1, true, 65535, ldapsPort.getIntValue()); 808 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAPS_CONNECTION_HANDLER)); 809 configEntry.putConfigAttribute(portAttr); 810 811 final BooleanConfigAttribute enablePortAttr = new BooleanConfigAttribute( 812 ATTR_CONNECTION_HANDLER_ENABLED, INFO_LDAPS_CONNHANDLER_DESCRIPTION_ENABLE.get(), true, true); 813 configEntry.putConfigAttribute(enablePortAttr); 814 } 815 catch (final Exception e) 816 { 817 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_LDAPS_PORT.get(e)); 818 } 819 } 820 } 821 822 private void updateJMXport() throws ConfigureDSException 823 { 824 if (jmxPort.isPresent()) 825 { 826 try 827 { 828 829 final IntegerConfigAttribute portAttr = new IntegerConfigAttribute( 830 ATTR_LISTEN_PORT, INFO_JMX_CONNHANDLER_DESCRIPTION_LISTEN_PORT.get(), 831 true, false, true, true, 1, true, 65535, jmxPort.getIntValue()); 832 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_JMX_CONNECTION_HANDLER)); 833 configEntry.putConfigAttribute(portAttr); 834 835 final BooleanConfigAttribute enablePortAttr = new BooleanConfigAttribute( 836 ATTR_CONNECTION_HANDLER_ENABLED, INFO_JMX_CONNHANDLER_DESCRIPTION_ENABLE.get(), true, true); 837 configEntry.putConfigAttribute(enablePortAttr); 838 } 839 catch (final Exception e) 840 { 841 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_JMX_PORT.get(e)); 842 } 843 } 844 } 845 846 private void updateStartTLS() throws ConfigureDSException 847 { 848 if (enableStartTLS.isPresent()) 849 { 850 try 851 { 852 final BooleanConfigAttribute startTLS = new BooleanConfigAttribute( 853 ATTR_ALLOW_STARTTLS, INFO_LDAP_CONNHANDLER_DESCRIPTION_ALLOW_STARTTLS.get(), true, true); 854 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_LDAP_CONNECTION_HANDLER)); 855 configEntry.putConfigAttribute(startTLS); 856 } 857 catch (final Exception e) 858 { 859 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_STARTTLS.get(e)); 860 } 861 } 862 } 863 864 private void updateKeyManager() throws ConfigureDSException 865 { 866 if (keyManagerProviderDN.isPresent()) 867 { 868 if (enableStartTLS.isPresent() || ldapsPort.isPresent()) 869 { 870 try 871 { 872 // Enable the key manager 873 final BooleanConfigAttribute enableAttr = new BooleanConfigAttribute( 874 ATTR_KEYMANAGER_ENABLED, INFO_CONFIG_KEYMANAGER_DESCRIPTION_ENABLED.get(), true, true); 875 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(keyManagerProviderDN.getValue())); 876 configEntry.putConfigAttribute(enableAttr); 877 } 878 catch (final Exception e) 879 { 880 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_KEYMANAGER.get(e)); 881 } 882 } 883 884 putKeyManagerConfigAttribute(enableStartTLS, DN_LDAP_CONNECTION_HANDLER); 885 putKeyManagerConfigAttribute(ldapsPort, DN_LDAPS_CONNECTION_HANDLER); 886 887 if (keyManagerPath.isPresent()) 888 { 889 try 890 { 891 final StringConfigAttribute pathAttr = new StringConfigAttribute( 892 ATTR_KEYSTORE_FILE, INFO_FILE_KEYMANAGER_DESCRIPTION_FILE.get(), 893 true, true, true, keyManagerPath.getValue()); 894 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(keyManagerProviderDN.getValue())); 895 configEntry.putConfigAttribute(pathAttr); 896 } 897 catch (final Exception e) 898 { 899 throw new ConfigureDSException(e, LocalizableMessage.raw(e.toString())); 900 } 901 } 902 } 903 } 904 905 private void putKeyManagerConfigAttribute(final Argument arg, final String attributeDN) 906 throws ConfigureDSException 907 { 908 if (arg.isPresent()) 909 { 910 try 911 { 912 final StringConfigAttribute keyManagerProviderAttr = new StringConfigAttribute( 913 ATTR_KEYMANAGER_DN, INFO_LDAP_CONNHANDLER_DESCRIPTION_KEYMANAGER_DN.get(), 914 false, false, true, keyManagerProviderDN.getValue()); 915 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN)); 916 configEntry.putConfigAttribute(keyManagerProviderAttr); 917 } 918 catch (final Exception e) 919 { 920 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_KEYMANAGER_REFERENCE.get(e)); 921 } 922 } 923 } 924 925 private void updateTrustManager() throws ConfigureDSException 926 { 927 if (trustManagerProviderDN.isPresent()) 928 { 929 if (enableStartTLS.isPresent() || ldapsPort.isPresent()) 930 { 931 try 932 { 933 final BooleanConfigAttribute enableAttr = new BooleanConfigAttribute( 934 ATTR_TRUSTMANAGER_ENABLED, ERR_CONFIG_TRUSTMANAGER_DESCRIPTION_ENABLED.get(), true, true); 935 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(trustManagerProviderDN.getValue())); 936 configEntry.putConfigAttribute(enableAttr); 937 } 938 catch (final Exception e) 939 { 940 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_ENABLE_TRUSTMANAGER.get(e)); 941 } 942 } 943 putTrustManagerAttribute(enableStartTLS, DN_LDAP_CONNECTION_HANDLER); 944 putTrustManagerAttribute(ldapsPort, DN_LDAPS_CONNECTION_HANDLER); 945 } 946 947 if (certNickName.isPresent()) 948 { 949 final StringConfigAttribute certNickNameAttr = new StringConfigAttribute( 950 ATTR_SSL_CERT_NICKNAME, INFO_LDAP_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME.get(), 951 false, false, true, certNickName.getValue()); 952 updateCertNicknameEntry(ldapPort, DN_LDAP_CONNECTION_HANDLER, certNickNameAttr); 953 updateCertNicknameEntry(ldapsPort, DN_LDAPS_CONNECTION_HANDLER, certNickNameAttr); 954 955 final StringConfigAttribute certNickNameJmxAttr = new StringConfigAttribute( 956 ATTR_SSL_CERT_NICKNAME, INFO_JMX_CONNHANDLER_DESCRIPTION_SSL_CERT_NICKNAME.get(), 957 false, false, true, certNickName.getValue()); 958 updateCertNicknameEntry(jmxPort, DN_JMX_CONNECTION_HANDLER, certNickNameJmxAttr); 959 } 960 else 961 { 962 // Use the key manager specified for connection handlers 963 removeSSLCertNicknameAttribute(DN_LDAP_CONNECTION_HANDLER); 964 removeSSLCertNicknameAttribute(DN_LDAPS_CONNECTION_HANDLER); 965 removeSSLCertNicknameAttribute(DN_JMX_CONNECTION_HANDLER); 966 } 967 } 968 969 private void putTrustManagerAttribute(final Argument arg, final String attributeDN) throws ConfigureDSException 970 { 971 if (arg.isPresent()) 972 { 973 try 974 { 975 final StringConfigAttribute trustManagerProviderAttr = new StringConfigAttribute( 976 ATTR_TRUSTMANAGER_DN, INFO_LDAP_CONNHANDLER_DESCRIPTION_TRUSTMANAGER_DN.get(), 977 false, false, true, trustManagerProviderDN.getValue()); 978 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN)); 979 configEntry.putConfigAttribute(trustManagerProviderAttr); 980 } 981 catch (final Exception e) 982 { 983 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_TRUSTMANAGER_REFERENCE.get(e)); 984 } 985 } 986 } 987 988 private void updateCertNicknameEntry(final Argument arg, final String attributeDN, 989 final StringConfigAttribute configAttr) throws ConfigureDSException 990 { 991 try 992 { 993 ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN)); 994 if (arg.isPresent()) 995 { 996 configEntry.putConfigAttribute(configAttr); 997 } 998 else 999 { 1000 configEntry.removeConfigAttribute(ATTR_SSL_CERT_NICKNAME); 1001 } 1002 } 1003 catch (final Exception e) 1004 { 1005 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CERT_NICKNAME.get(e)); 1006 } 1007 } 1008 1009 private void removeSSLCertNicknameAttribute(final String attributeDN) throws ConfigureDSException 1010 { 1011 try 1012 { 1013 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(attributeDN)); 1014 configEntry.removeConfigAttribute(ATTR_SSL_CERT_NICKNAME.toLowerCase()); 1015 } 1016 catch (final Exception e) 1017 { 1018 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CERT_NICKNAME.get(e)); 1019 } 1020 } 1021 1022 private void updateRootUser(final DN rootDN, final String rootPW) throws ConfigureDSException 1023 { 1024 if (rootDN != null) 1025 { 1026 try 1027 { 1028 final DNConfigAttribute bindDNAttr = new DNConfigAttribute( 1029 ATTR_ROOTDN_ALTERNATE_BIND_DN, INFO_CONFIG_ROOTDN_DESCRIPTION_ALTERNATE_BIND_DN.get(), 1030 false, true, false, rootDN); 1031 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_ROOT_USER)); 1032 configEntry.putConfigAttribute(bindDNAttr); 1033 1034 final String encodedPassword = SaltedSHA512PasswordStorageScheme.encodeOffline(getBytes(rootPW)); 1035 final StringConfigAttribute bindPWAttr = new StringConfigAttribute( 1036 ATTR_USER_PASSWORD, LocalizableMessage.EMPTY, false, false, false, encodedPassword); 1037 configEntry.putConfigAttribute(bindPWAttr); 1038 } 1039 catch (final Exception e) 1040 { 1041 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_ROOT_USER.get(e)); 1042 } 1043 } 1044 } 1045 1046 /** Set the FQDN for the DIGEST-MD5 SASL mechanism. */ 1047 private void addFQDNDigestMD5() throws ConfigureDSException 1048 { 1049 try 1050 { 1051 final StringConfigAttribute fqdnAttr = new StringConfigAttribute( 1052 "ds-cfg-server-fqdn", LocalizableMessage.EMPTY, false, false, false, hostName.getValue()); 1053 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_DIGEST_MD5_SASL_MECHANISM)); 1054 configEntry.putConfigAttribute(fqdnAttr); 1055 } 1056 catch (final Exception e) 1057 { 1058 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_DIGEST_MD5_FQDN.get(e)); 1059 } 1060 } 1061 1062 /** 1063 * Check that the cipher specified is supported. This is intended to fix 1064 * issues with JVM that do not support the default cipher (see issue 3075 for 1065 * instance). 1066 * 1067 * @throws ConfigureDSException 1068 */ 1069 private void updateCryptoCipher() throws ConfigureDSException 1070 { 1071 final CryptoManagerCfgDefn cryptoManager = CryptoManagerCfgDefn.getInstance(); 1072 final StringPropertyDefinition prop = cryptoManager.getKeyWrappingTransformationPropertyDefinition(); 1073 String defaultCipher = null; 1074 1075 final DefaultBehaviorProvider<?> p = prop.getDefaultBehaviorProvider(); 1076 if (p instanceof DefinedDefaultBehaviorProvider) 1077 { 1078 final Collection<?> defaultValues = ((DefinedDefaultBehaviorProvider<?>) p).getDefaultValues(); 1079 if (!defaultValues.isEmpty()) 1080 { 1081 defaultCipher = defaultValues.iterator().next().toString(); 1082 } 1083 } 1084 1085 if (defaultCipher != null) 1086 { 1087 // Check that the default cipher is supported by the JVM. 1088 try 1089 { 1090 Cipher.getInstance(defaultCipher); 1091 } 1092 catch (final GeneralSecurityException ex) 1093 { 1094 // The cipher is not supported: try to find an alternative one. 1095 final String alternativeCipher = getAlternativeCipher(); 1096 if (alternativeCipher != null) 1097 { 1098 try 1099 { 1100 final StringConfigAttribute keyWrappingTransformation = new StringConfigAttribute( 1101 ATTR_CRYPTO_CIPHER_KEY_WRAPPING_TRANSFORMATION, LocalizableMessage.EMPTY, 1102 false, false, true, alternativeCipher); 1103 final ConfigEntry configEntry = configHandler.getConfigEntry(DN.valueOf(DN_CRYPTO_MANAGER)); 1104 configEntry.putConfigAttribute(keyWrappingTransformation); 1105 } 1106 catch (final Exception e) 1107 { 1108 throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_CRYPTO_MANAGER.get(e)); 1109 } 1110 } 1111 } 1112 } 1113 } 1114 1115 private void writeUpdatedConfiguration() throws ConfigureDSException 1116 { 1117 try 1118 { 1119 configHandler.writeUpdatedConfig(); 1120 printWrappedText(out, INFO_CONFIGDS_WROTE_UPDATED_CONFIG.get()); 1121 } 1122 catch (final DirectoryException de) 1123 { 1124 throw new ConfigureDSException(de, ERR_CONFIGDS_CANNOT_WRITE_UPDATED_CONFIG.get(de.getMessageObject())); 1125 } 1126 } 1127 1128 /** 1129 * Returns a cipher that is supported by the JVM we are running at. 1130 * Returns <CODE>null</CODE> if no alternative cipher could be found. 1131 * @return a cipher that is supported by the JVM we are running at. 1132 */ 1133 public static String getAlternativeCipher() 1134 { 1135 final String[] preferredAlternativeCiphers = 1136 { 1137 "RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING", 1138 "RSA/ECB/PKCS1Padding" 1139 }; 1140 String alternativeCipher = null; 1141 for (final String cipher : preferredAlternativeCiphers) 1142 { 1143 try 1144 { 1145 Cipher.getInstance(cipher); 1146 alternativeCipher = cipher; 1147 break; 1148 } 1149 catch (final Throwable t) 1150 { 1151 } 1152 } 1153 return alternativeCipher; 1154 } 1155} 1156