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