001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2011-2016 ForgeRock AS. 016 */ 017package org.opends.server.tools; 018 019import static com.forgerock.opendj.cli.ArgumentConstants.*; 020import static com.forgerock.opendj.cli.CliMessages.INFO_FILE_PLACEHOLDER; 021import static com.forgerock.opendj.cli.Utils.*; 022import static com.forgerock.opendj.cli.CommonArguments.*; 023 024import static org.opends.messages.ConfigMessages.*; 025import static org.opends.messages.ToolMessages.*; 026import static org.opends.server.protocols.ldap.LDAPResultCode.*; 027import static org.opends.server.util.StaticUtils.*; 028 029import java.io.Console; 030import java.io.IOException; 031import java.io.OutputStream; 032import java.io.PrintStream; 033import java.util.ArrayList; 034import java.util.Collections; 035import java.util.concurrent.ConcurrentHashMap; 036 037import org.forgerock.i18n.LocalizableMessage; 038import org.forgerock.opendj.config.server.ConfigException; 039import org.forgerock.opendj.ldap.ByteString; 040import org.forgerock.opendj.ldap.DN; 041import org.opends.server.admin.server.ServerManagementContext; 042import org.opends.server.admin.std.server.BackendCfg; 043import org.opends.server.admin.std.server.LDIFBackendCfg; 044import org.opends.server.admin.std.server.RootCfg; 045import org.opends.server.admin.std.server.TrustStoreBackendCfg; 046import org.opends.server.api.Backend; 047import org.opends.server.api.PasswordStorageScheme; 048import org.opends.server.config.ConfigConstants; 049import org.opends.server.config.ConfigEntry; 050import org.opends.server.core.CoreConfigManager; 051import org.opends.server.core.DirectoryServer; 052import org.opends.server.core.DirectoryServer.DirectoryServerVersionHandler; 053import org.opends.server.core.PasswordStorageSchemeConfigManager; 054import org.opends.server.crypto.CryptoManagerSync; 055import org.opends.server.extensions.ConfigFileHandler; 056import org.opends.server.loggers.JDKLogging; 057import org.opends.server.schema.AuthPasswordSyntax; 058import org.opends.server.schema.UserPasswordSyntax; 059import org.opends.server.types.*; 060import org.opends.server.util.BuildVersion; 061 062import com.forgerock.opendj.cli.ArgumentException; 063import com.forgerock.opendj.cli.ArgumentParser; 064import com.forgerock.opendj.cli.BooleanArgument; 065import com.forgerock.opendj.cli.FileBasedArgument; 066import com.forgerock.opendj.cli.StringArgument; 067 068/** 069 * This program provides a utility that may be used to interact with the 070 * password storage schemes defined in the Directory Server. In particular, 071 * it can encode a clear-text password using a specified scheme, and it can also 072 * determine whether a given encoded password is the encoded representation of a 073 * given clear-text password. Alternately, it can be used to obtain a list of 074 * the available password storage scheme names. 075 */ 076public class EncodePassword 077{ 078 /** 079 * Processes the command-line arguments and performs the requested action. 080 * 081 * @param args The command-line arguments provided to this program. 082 */ 083 public static void main(String[] args) 084 { 085 int returnCode = encodePassword(args, true, System.out, System.err); 086 if (returnCode != 0) 087 { 088 System.exit(filterExitCode(returnCode)); 089 } 090 } 091 092 093 094 /** 095 * Processes the command-line arguments and performs the requested action. 096 * 097 * @param args The command-line arguments provided to this program. 098 * 099 * @return An integer value that indicates whether processing was successful. 100 */ 101 public static int encodePassword(String[] args) 102 { 103 return encodePassword(args, true, System.out, System.err); 104 } 105 106 107 108 /** 109 * Processes the command-line arguments and performs the requested action. 110 * 111 * @param args The command-line arguments provided to this 112 * program. 113 * @param initializeServer Indicates whether to initialize the server. 114 * @param outStream The output stream to use for standard output, or 115 * <CODE>null</CODE> if standard output is not 116 * needed. 117 * @param errStream The output stream to use for standard error, or 118 * <CODE>null</CODE> if standard error is not 119 * needed. 120 * 121 * @return An integer value that indicates whether processing was successful. 122 */ 123 public static int encodePassword(String[] args, boolean initializeServer, 124 OutputStream outStream, 125 OutputStream errStream) 126 { 127 PrintStream out = NullOutputStream.wrapOrNullStream(outStream); 128 PrintStream err = NullOutputStream.wrapOrNullStream(errStream); 129 JDKLogging.disableLogging(); 130 131 // Define the command-line arguments that may be used with this program. 132 BooleanArgument authPasswordSyntax = null; 133 BooleanArgument useCompareResultCode = null; 134 BooleanArgument listSchemes = null; 135 BooleanArgument showUsage = null; 136 BooleanArgument interactivePassword = null; 137 StringArgument clearPassword = null; 138 FileBasedArgument clearPasswordFile = null; 139 StringArgument encodedPassword = null; 140 FileBasedArgument encodedPasswordFile = null; 141 StringArgument configClass = null; 142 StringArgument configFile = null; 143 StringArgument schemeName = null; 144 145 146 // Create the command-line argument parser for use with this program. 147 LocalizableMessage toolDescription = INFO_ENCPW_TOOL_DESCRIPTION.get(); 148 ArgumentParser argParser = 149 new ArgumentParser("org.opends.server.tools.EncodePassword", 150 toolDescription, false); 151 argParser.setShortToolDescription(REF_SHORT_DESC_ENCODE_PASSWORD.get()); 152 argParser.setVersionHandler(new DirectoryServerVersionHandler()); 153 154 // Initialize all the command-line argument types and register them with the parser. 155 try 156 { 157 listSchemes = 158 BooleanArgument.builder("listSchemes") 159 .shortIdentifier('l') 160 .description(INFO_ENCPW_DESCRIPTION_LISTSCHEMES.get()) 161 .buildAndAddToParser(argParser); 162 interactivePassword = 163 BooleanArgument.builder("interactivePassword") 164 .shortIdentifier('i') 165 .description(INFO_ENCPW_DESCRIPTION_INPUT_PW.get()) 166 .buildAndAddToParser(argParser); 167 clearPassword = 168 StringArgument.builder("clearPassword") 169 .shortIdentifier('c') 170 .description(INFO_ENCPW_DESCRIPTION_CLEAR_PW.get()) 171 .valuePlaceholder(INFO_CLEAR_PWD.get()) 172 .buildAndAddToParser(argParser); 173 clearPasswordFile = 174 FileBasedArgument.builder("clearPasswordFile") 175 .shortIdentifier('f') 176 .description(INFO_ENCPW_DESCRIPTION_CLEAR_PW_FILE.get()) 177 .valuePlaceholder(INFO_FILE_PLACEHOLDER.get()) 178 .buildAndAddToParser(argParser); 179 encodedPassword = 180 StringArgument.builder("encodedPassword") 181 .shortIdentifier('e') 182 .description(INFO_ENCPW_DESCRIPTION_ENCODED_PW.get()) 183 .valuePlaceholder(INFO_ENCODED_PWD_PLACEHOLDER.get()) 184 .buildAndAddToParser(argParser); 185 encodedPasswordFile = 186 FileBasedArgument.builder("encodedPasswordFile") 187 .shortIdentifier('E') 188 .description(INFO_ENCPW_DESCRIPTION_ENCODED_PW_FILE.get()) 189 .valuePlaceholder(INFO_FILE_PLACEHOLDER.get()) 190 .buildAndAddToParser(argParser); 191 configClass = 192 StringArgument.builder(OPTION_LONG_CONFIG_CLASS) 193 .shortIdentifier(OPTION_SHORT_CONFIG_CLASS) 194 .description(INFO_DESCRIPTION_CONFIG_CLASS.get()) 195 .hidden() 196 .required() 197 .defaultValue(ConfigFileHandler.class.getName()) 198 .valuePlaceholder(INFO_CONFIGCLASS_PLACEHOLDER.get()) 199 .buildAndAddToParser(argParser); 200 configFile = 201 StringArgument.builder("configFile") 202 .shortIdentifier('F') 203 .description(INFO_DESCRIPTION_CONFIG_FILE.get()) 204 .hidden() 205 .required() 206 .valuePlaceholder(INFO_CONFIGFILE_PLACEHOLDER.get()) 207 .buildAndAddToParser(argParser); 208 schemeName = 209 StringArgument.builder("storageScheme") 210 .shortIdentifier('s') 211 .description(INFO_ENCPW_DESCRIPTION_SCHEME.get()) 212 .valuePlaceholder(INFO_STORAGE_SCHEME_PLACEHOLDER.get()) 213 .buildAndAddToParser(argParser); 214 authPasswordSyntax = 215 BooleanArgument.builder("authPasswordSyntax") 216 .shortIdentifier('a') 217 .description(INFO_ENCPW_DESCRIPTION_AUTHPW.get()) 218 .buildAndAddToParser(argParser); 219 useCompareResultCode = 220 BooleanArgument.builder("useCompareResultCode") 221 .shortIdentifier('r') 222 .description(INFO_ENCPW_DESCRIPTION_USE_COMPARE_RESULT.get()) 223 .buildAndAddToParser(argParser); 224 225 showUsage = showUsageArgument(); 226 argParser.addArgument(showUsage); 227 argParser.setUsageArgument(showUsage, out); 228 } 229 catch (ArgumentException ae) 230 { 231 printWrappedText(err, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage())); 232 return OPERATIONS_ERROR; 233 } 234 235 236 // Parse the command-line arguments provided to this program. 237 try 238 { 239 argParser.parseArguments(args); 240 } 241 catch (ArgumentException ae) 242 { 243 argParser.displayMessageAndUsageReference(err, ERR_ERROR_PARSING_ARGS.get(ae.getMessage())); 244 return OPERATIONS_ERROR; 245 } 246 247 248 // If we should just display usage or version information, 249 // then we've already done it so just return without doing anything else. 250 if (argParser.usageOrVersionDisplayed()) 251 { 252 return SUCCESS; 253 } 254 255 // Checks the version - if upgrade required, the tool is unusable 256 try 257 { 258 BuildVersion.checkVersionMismatch(); 259 } 260 catch (InitializationException e) 261 { 262 printWrappedText(err, e.getMessage()); 263 return 1; 264 } 265 266 // Check for conflicting arguments. 267 try 268 { 269 throwIfArgumentsConflict(clearPassword, clearPasswordFile); 270 throwIfArgumentsConflict(clearPassword, interactivePassword); 271 throwIfArgumentsConflict(clearPasswordFile, interactivePassword); 272 throwIfArgumentsConflict(encodedPassword, encodedPasswordFile); 273 } 274 catch (final ArgumentException conflict) 275 { 276 printWrappedText(err, conflict.getMessageObject()); 277 return OPERATIONS_ERROR; 278 } 279 280 // If we are not going to just list the storage schemes, then the clear-text 281 // password must have been provided. If we're going to encode a password, 282 // then the scheme must have also been provided. 283 if (!listSchemes.isPresent() 284 && !encodedPassword.isPresent() 285 && !encodedPasswordFile.isPresent() 286 && !schemeName.isPresent()) 287 { 288 argParser.displayMessageAndUsageReference(err, ERR_ENCPW_NO_SCHEME.get(schemeName.getLongIdentifier())); 289 return OPERATIONS_ERROR; 290 } 291 292 293 // Determine whether we're encoding the clear-text password or comparing it 294 // against an already-encoded password. 295 boolean compareMode; 296 ByteString encodedPW = null; 297 if (encodedPassword.hasValue()) 298 { 299 compareMode = true; 300 encodedPW = ByteString.valueOfUtf8(encodedPassword.getValue()); 301 } 302 else if (encodedPasswordFile.hasValue()) 303 { 304 compareMode = true; 305 encodedPW = ByteString.valueOfUtf8(encodedPasswordFile.getValue()); 306 } 307 else 308 { 309 compareMode = false; 310 } 311 312 313 // Perform the initial bootstrap of the Directory Server and process the 314 // configuration. 315 DirectoryServer directoryServer = DirectoryServer.getInstance(); 316 317 if (initializeServer) 318 { 319 try 320 { 321 DirectoryServer.bootstrapClient(); 322 DirectoryServer.initializeJMX(); 323 } 324 catch (Exception e) 325 { 326 printWrappedText(err, ERR_SERVER_BOOTSTRAP_ERROR.get(getExceptionMessage(e))); 327 return OPERATIONS_ERROR; 328 } 329 330 try 331 { 332 directoryServer.initializeConfiguration(configClass.getValue(), 333 configFile.getValue()); 334 } 335 catch (InitializationException ie) 336 { 337 printWrappedText(err, ERR_CANNOT_LOAD_CONFIG.get(ie.getMessage())); 338 return OPERATIONS_ERROR; 339 } 340 catch (Exception e) 341 { 342 printWrappedText(err, ERR_CANNOT_LOAD_CONFIG.get(getExceptionMessage(e))); 343 return OPERATIONS_ERROR; 344 } 345 346 347 348 // Initialize the Directory Server schema elements. 349 try 350 { 351 directoryServer.initializeSchema(); 352 } 353 catch (ConfigException | InitializationException e) 354 { 355 printWrappedText(err, ERR_CANNOT_LOAD_SCHEMA.get(e.getMessage())); 356 return OPERATIONS_ERROR; 357 } 358 catch (Exception e) 359 { 360 printWrappedText(err, ERR_CANNOT_LOAD_SCHEMA.get(getExceptionMessage(e))); 361 return OPERATIONS_ERROR; 362 } 363 364 365 // Initialize the Directory Server core configuration. 366 try 367 { 368 CoreConfigManager coreConfigManager = new CoreConfigManager(directoryServer.getServerContext()); 369 coreConfigManager.initializeCoreConfig(); 370 } 371 catch (ConfigException | InitializationException e) 372 { 373 printWrappedText(err, ERR_CANNOT_INITIALIZE_CORE_CONFIG.get(e.getMessage())); 374 return OPERATIONS_ERROR; 375 } 376 catch (Exception e) 377 { 378 printWrappedText(err, ERR_CANNOT_INITIALIZE_CORE_CONFIG.get(getExceptionMessage(e))); 379 return OPERATIONS_ERROR; 380 } 381 382 383 if(!initializeServerComponents(directoryServer, err)) 384 { 385 return -1; 386 } 387 388 // Initialize the password storage schemes. 389 try 390 { 391 PasswordStorageSchemeConfigManager storageSchemeConfigManager = 392 new PasswordStorageSchemeConfigManager(directoryServer.getServerContext()); 393 storageSchemeConfigManager.initializePasswordStorageSchemes(); 394 } 395 catch (ConfigException | InitializationException e) 396 { 397 printWrappedText(err, ERR_ENCPW_CANNOT_INITIALIZE_STORAGE_SCHEMES.get(e.getMessage())); 398 return OPERATIONS_ERROR; 399 } 400 catch (Exception e) 401 { 402 printWrappedText(err, ERR_ENCPW_CANNOT_INITIALIZE_STORAGE_SCHEMES.get(getExceptionMessage(e))); 403 return OPERATIONS_ERROR; 404 } 405 } 406 407 408 // If we are only trying to list the available schemes, then do so and exit. 409 if (listSchemes.isPresent()) 410 { 411 if (authPasswordSyntax.isPresent()) 412 { 413 listPasswordStorageSchemes(out, err, DirectoryServer.getAuthPasswordStorageSchemes(), true); 414 } 415 else 416 { 417 listPasswordStorageSchemes(out, err, DirectoryServer.getPasswordStorageSchemes(), false); 418 } 419 return SUCCESS; 420 } 421 422 423 // Either encode the clear-text password using the provided scheme, or 424 // compare the clear-text password against the encoded password. 425 ByteString clearPW = null; 426 if (compareMode) 427 { 428 // Check to see if the provided password value was encoded. If so, then 429 // break it down into its component parts and use that to perform the 430 // comparison. Otherwise, the user must have provided the storage scheme. 431 if (authPasswordSyntax.isPresent()) 432 { 433 String[] authPWElements; 434 try 435 { 436 authPWElements = AuthPasswordSyntax.decodeAuthPassword(encodedPW.toString()); 437 } 438 catch (DirectoryException de) 439 { 440 printWrappedText(err, ERR_ENCPW_INVALID_ENCODED_AUTHPW.get(de.getMessageObject())); 441 return OPERATIONS_ERROR; 442 } 443 catch (Exception e) 444 { 445 printWrappedText(err, ERR_ENCPW_INVALID_ENCODED_AUTHPW.get(e)); 446 return OPERATIONS_ERROR; 447 } 448 449 String scheme = authPWElements[0]; 450 String authInfo = authPWElements[1]; 451 String authValue = authPWElements[2]; 452 453 PasswordStorageScheme storageScheme = 454 DirectoryServer.getAuthPasswordStorageScheme(scheme); 455 if (storageScheme == null) 456 { 457 printWrappedText(err, ERR_ENCPW_NO_SUCH_AUTH_SCHEME.get(scheme)); 458 return OPERATIONS_ERROR; 459 } 460 461 if (clearPW == null) 462 { 463 clearPW = getClearPW(out, err, argParser, clearPassword, 464 clearPasswordFile, interactivePassword); 465 if (clearPW == null) 466 { 467 return OPERATIONS_ERROR; 468 } 469 } 470 final boolean authPasswordMatches = 471 storageScheme.authPasswordMatches(clearPW, authInfo, authValue); 472 out.println(getOutputMessage(authPasswordMatches)); 473 if (useCompareResultCode.isPresent()) 474 { 475 return authPasswordMatches ? COMPARE_TRUE : COMPARE_FALSE; 476 } 477 return SUCCESS; 478 } 479 else 480 { 481 PasswordStorageScheme storageScheme; 482 String encodedPWString; 483 484 if (UserPasswordSyntax.isEncoded(encodedPW)) 485 { 486 try 487 { 488 String[] userPWElements = 489 UserPasswordSyntax.decodeUserPassword(encodedPW.toString()); 490 encodedPWString = userPWElements[1]; 491 492 storageScheme = 493 DirectoryServer.getPasswordStorageScheme(userPWElements[0]); 494 if (storageScheme == null) 495 { 496 printWrappedText(err, ERR_ENCPW_NO_SUCH_SCHEME.get(userPWElements[0])); 497 return OPERATIONS_ERROR; 498 } 499 } 500 catch (DirectoryException de) 501 { 502 printWrappedText(err, ERR_ENCPW_INVALID_ENCODED_USERPW.get(de.getMessageObject())); 503 return OPERATIONS_ERROR; 504 } 505 catch (Exception e) 506 { 507 printWrappedText(err, ERR_ENCPW_INVALID_ENCODED_USERPW.get(e)); 508 return OPERATIONS_ERROR; 509 } 510 } 511 else 512 { 513 if (! schemeName.isPresent()) 514 { 515 printWrappedText(err, ERR_ENCPW_NO_SCHEME.get(schemeName.getLongIdentifier())); 516 return OPERATIONS_ERROR; 517 } 518 519 encodedPWString = encodedPW.toString(); 520 521 String scheme = toLowerCase(schemeName.getValue()); 522 storageScheme = DirectoryServer.getPasswordStorageScheme(scheme); 523 if (storageScheme == null) 524 { 525 printWrappedText(err, ERR_ENCPW_NO_SUCH_SCHEME.get(scheme)); 526 return OPERATIONS_ERROR; 527 } 528 } 529 530 if (clearPW == null) 531 { 532 clearPW = getClearPW(out, err, argParser, clearPassword, 533 clearPasswordFile, interactivePassword); 534 if (clearPW == null) 535 { 536 return OPERATIONS_ERROR; 537 } 538 } 539 boolean passwordMatches = 540 storageScheme.passwordMatches(clearPW, ByteString 541 .valueOfUtf8(encodedPWString)); 542 out.println(getOutputMessage(passwordMatches)); 543 if (useCompareResultCode.isPresent()) 544 { 545 return passwordMatches ? COMPARE_TRUE : COMPARE_FALSE; 546 } 547 return SUCCESS; 548 } 549 } 550 else 551 { 552 // Try to get a reference to the requested password storage scheme. 553 PasswordStorageScheme storageScheme; 554 if (authPasswordSyntax.isPresent()) 555 { 556 String scheme = schemeName.getValue(); 557 storageScheme = DirectoryServer.getAuthPasswordStorageScheme(scheme); 558 if (storageScheme == null) 559 { 560 printWrappedText(err, ERR_ENCPW_NO_SUCH_AUTH_SCHEME.get(scheme)); 561 return OPERATIONS_ERROR; 562 } 563 } 564 else 565 { 566 String scheme = toLowerCase(schemeName.getValue()); 567 storageScheme = DirectoryServer.getPasswordStorageScheme(scheme); 568 if (storageScheme == null) 569 { 570 printWrappedText(err, ERR_ENCPW_NO_SUCH_SCHEME.get(scheme)); 571 return OPERATIONS_ERROR; 572 } 573 } 574 575 if (authPasswordSyntax.isPresent()) 576 { 577 try 578 { 579 if (clearPW == null) 580 { 581 clearPW = getClearPW(out, err, argParser, clearPassword, 582 clearPasswordFile, interactivePassword); 583 if (clearPW == null) 584 { 585 return OPERATIONS_ERROR; 586 } 587 } 588 encodedPW = storageScheme.encodeAuthPassword(clearPW); 589 590 LocalizableMessage message = ERR_ENCPW_ENCODED_PASSWORD.get(encodedPW); 591 out.println(message); 592 } 593 catch (DirectoryException de) 594 { 595 printWrappedText(err, ERR_ENCPW_CANNOT_ENCODE.get(de.getMessageObject())); 596 return OPERATIONS_ERROR; 597 } 598 catch (Exception e) 599 { 600 printWrappedText(err, ERR_ENCPW_CANNOT_ENCODE.get(getExceptionMessage(e))); 601 return OPERATIONS_ERROR; 602 } 603 } 604 else 605 { 606 try 607 { 608 if (clearPW == null) 609 { 610 clearPW = getClearPW(out, err, argParser, clearPassword, 611 clearPasswordFile, interactivePassword); 612 if (clearPW == null) 613 { 614 return OPERATIONS_ERROR; 615 } 616 } 617 encodedPW = storageScheme.encodePasswordWithScheme(clearPW); 618 619 out.println(ERR_ENCPW_ENCODED_PASSWORD.get(encodedPW)); 620 } 621 catch (DirectoryException de) 622 { 623 printWrappedText(err, ERR_ENCPW_CANNOT_ENCODE.get(de.getMessageObject())); 624 return OPERATIONS_ERROR; 625 } 626 catch (Exception e) 627 { 628 printWrappedText(err, ERR_ENCPW_CANNOT_ENCODE.get(getExceptionMessage(e))); 629 return OPERATIONS_ERROR; 630 } 631 } 632 } 633 634 // If we've gotten here, then all processing completed successfully. 635 return SUCCESS; 636 } 637 638 private static void listPasswordStorageSchemes(PrintStream out, PrintStream err, 639 ConcurrentHashMap<String, PasswordStorageScheme> storageSchemes, boolean authPasswordSchemeName) 640 { 641 if (storageSchemes.isEmpty()) 642 { 643 printWrappedText(err, ERR_ENCPW_NO_STORAGE_SCHEMES.get()); 644 } 645 else 646 { 647 ArrayList<String> nameList = new ArrayList<>(storageSchemes.size()); 648 for (PasswordStorageScheme<?> s : storageSchemes.values()) 649 { 650 if (authPasswordSchemeName) 651 { 652 nameList.add(s.getAuthPasswordSchemeName()); 653 } 654 else 655 { 656 nameList.add(s.getStorageSchemeName()); 657 } 658 } 659 Collections.sort(nameList); 660 661 for (String storageSchemeName : nameList) 662 { 663 out.println(storageSchemeName); 664 } 665 } 666 } 667 668 private static LocalizableMessage getOutputMessage(boolean passwordMatches) 669 { 670 if (passwordMatches) 671 { 672 return INFO_ENCPW_PASSWORDS_MATCH.get(); 673 } 674 return INFO_ENCPW_PASSWORDS_DO_NOT_MATCH.get(); 675 } 676 677 678 679 private static boolean initializeServerComponents(DirectoryServer directoryServer, PrintStream err) 680 { 681 // Initialize the Directory Server crypto manager. 682 try 683 { 684 directoryServer.initializeCryptoManager(); 685 } 686 catch (ConfigException | InitializationException e) 687 { 688 printWrappedText(err, ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(e.getMessage())); 689 return false; 690 } 691 catch (Exception e) 692 { 693 printWrappedText(err, ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(getExceptionMessage(e))); 694 return false; 695 } 696 //Attempt to bring up enough of the server to process schemes requiring 697 //secret keys from the trust store backend (3DES, BLOWFISH, AES, RC4) via 698 //the crypto-manager. 699 try { 700 directoryServer.initializeRootDNConfigManager(); 701 directoryServer.initializePlugins(Collections.EMPTY_SET); 702 initializeServerBackends(directoryServer, err); 703 directoryServer.initializeSubentryManager(); 704 directoryServer.initializeAuthenticationPolicyComponents(); 705 directoryServer.initializeAuthenticatedUsers(); 706 new CryptoManagerSync(); 707 } catch (InitializationException | ConfigException e) { 708 printWrappedText(err, ERR_ENCPW_CANNOT_INITIALIZE_SERVER_COMPONENTS.get(getExceptionMessage(e))); 709 return false; 710 } 711 return true; 712 } 713 714 private static void initializeServerBackends(DirectoryServer directoryServer, PrintStream err) 715 throws InitializationException, ConfigException { 716 directoryServer.initializeRootDSE(); 717 ServerManagementContext context = ServerManagementContext.getInstance(); 718 RootCfg root = context.getRootConfiguration(); 719 ConfigEntry backendRoot; 720 try { 721 DN configEntryDN = DN.valueOf(ConfigConstants.DN_BACKEND_BASE); 722 backendRoot = DirectoryServer.getConfigEntry(configEntryDN); 723 } catch (Exception e) { 724 LocalizableMessage message = ERR_CONFIG_BACKEND_CANNOT_GET_CONFIG_BASE.get( 725 getExceptionMessage(e)); 726 throw new ConfigException(message, e); 727 } 728 if (backendRoot == null) { 729 LocalizableMessage message = ERR_CONFIG_BACKEND_BASE_DOES_NOT_EXIST.get(); 730 throw new ConfigException(message); 731 } 732 for (String name : root.listBackends()) { 733 BackendCfg backendCfg = root.getBackend(name); 734 String backendID = backendCfg.getBackendId(); 735 if((backendCfg instanceof TrustStoreBackendCfg 736 || backendCfg instanceof LDIFBackendCfg) 737 && backendCfg.isEnabled()) 738 { 739 String className = backendCfg.getJavaClass(); 740 Class<?> backendClass; 741 Backend<BackendCfg> backend; 742 try { 743 backendClass = DirectoryServer.loadClass(className); 744 backend = (Backend<BackendCfg>) backendClass.newInstance(); 745 } catch (Exception e) { 746 printWrappedText(err, 747 ERR_CONFIG_BACKEND_CANNOT_INSTANTIATE.get(className, backendCfg.dn(), stackTraceToSingleLineString(e))); 748 continue; 749 } 750 backend.setBackendID(backendID); 751 backend.setWritabilityMode(WritabilityMode.INTERNAL_ONLY); 752 try { 753 backend.configureBackend(backendCfg, directoryServer.getServerContext()); 754 backend.openBackend(); 755 } catch (Exception e) { 756 printWrappedText(err, 757 ERR_CONFIG_BACKEND_CANNOT_INITIALIZE.get(className, backendCfg.dn(), stackTraceToSingleLineString(e))); 758 } 759 try { 760 DirectoryServer.registerBackend(backend); 761 } catch (Exception e) 762 { 763 printWrappedText( 764 err, WARN_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND.get(backendCfg.getBackendId(), getExceptionMessage(e))); 765 } 766 } 767 } 768 } 769 770 /** 771 * Get the clear password. 772 * @param out The output to ask password. 773 * @param err The error output. 774 * @param argParser The argument parser. 775 * @param clearPassword the clear password 776 * @param clearPasswordFile the file in which the password in stored 777 * @param interactivePassword indicate if the password should be asked 778 * interactively. 779 * @return the password or null if an error occurs. 780 */ 781 private static ByteString getClearPW(PrintStream out, PrintStream err, 782 ArgumentParser argParser, StringArgument clearPassword, 783 FileBasedArgument clearPasswordFile, BooleanArgument interactivePassword) 784 { 785 if (clearPassword.hasValue()) 786 { 787 return ByteString.valueOfUtf8(clearPassword.getValue()); 788 } 789 else if (clearPasswordFile.hasValue()) 790 { 791 return ByteString.valueOfUtf8(clearPasswordFile.getValue()); 792 } 793 else if (interactivePassword.isPresent()) 794 { 795 try 796 { 797 EncodePassword encodePassword = new EncodePassword(); 798 String pwd1 = encodePassword.getPassword(INFO_ENCPW_INPUT_PWD_1.get().toString()); 799 String pwd2 = encodePassword.getPassword(INFO_ENCPW_INPUT_PWD_2.get().toString()); 800 if (pwd1.equals(pwd2)) 801 { 802 return ByteString.valueOfUtf8(pwd1); 803 } 804 else 805 { 806 printWrappedText(err, ERR_ENCPW_NOT_SAME_PW.get()); 807 return null; 808 } 809 } 810 catch (IOException e) 811 { 812 printWrappedText(err, ERR_ENCPW_CANNOT_READ_PW.get(e.getMessage())); 813 return null; 814 } 815 } 816 else 817 { 818 argParser.displayMessageAndUsageReference(err, ERR_ENCPW_NO_CLEAR_PW.get(clearPassword.getLongIdentifier(), 819 clearPasswordFile.getLongIdentifier(), interactivePassword.getLongIdentifier())); 820 return null; 821 } 822 } 823 824 /** 825 * Get the password from JDK6 console or from masked password. 826 * @param prompt The message to print out. 827 * @return the password 828 * @throws IOException if an issue occurs when reading the password 829 * from the input 830 */ 831 private String getPassword(String prompt) throws IOException 832 { 833 String password; 834 try 835 { 836 Console console = System.console(); 837 if (console == null) 838 { 839 throw new IOException("No console"); 840 } 841 password = new String(console.readPassword(prompt)); 842 } 843 catch (Exception e) 844 { 845 // Try the fallback to the old trick method. 846 // Create the thread that will erase chars 847 ErasingThread erasingThread = new ErasingThread(prompt); 848 erasingThread.start(); 849 850 password = ""; 851 852 // block until enter is pressed 853 while (true) 854 { 855 char c = (char) System.in.read(); 856 // assume enter pressed, stop masking 857 erasingThread.stopMasking(); 858 if (c == '\r') 859 { 860 c = (char) System.in.read(); 861 if (c == '\n') 862 { 863 break; 864 } 865 } 866 else if (c == '\n') 867 { 868 break; 869 } 870 else 871 { 872 // store the password 873 password += c; 874 } 875 } 876 } 877 return password; 878 } 879 880 881 /** 882 * Thread that mask user input. 883 */ 884 private class ErasingThread extends Thread 885 { 886 887 private boolean stop; 888 private String prompt; 889 890 /** 891 * The class will mask the user input. 892 * @param prompt 893 * The prompt displayed to the user 894 */ 895 public ErasingThread(String prompt) 896 { 897 this.prompt = prompt; 898 } 899 900 /** 901 * Begin masking until asked to stop. 902 */ 903 @Override 904 public void run() 905 { 906 while (!stop) 907 { 908 try 909 { 910 // attempt masking at this rate 911 Thread.sleep(1); 912 } 913 catch (InterruptedException iex) 914 { 915 iex.printStackTrace(); 916 } 917 if (!stop) 918 { 919 System.out.print("\r" + prompt + " \r" + prompt); 920 } 921 System.out.flush(); 922 } 923 } 924 925 /** 926 * Instruct the thread to stop masking. 927 */ 928 public void stopMasking() 929 { 930 this.stop = true; 931 } 932 } 933 934} 935