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.valueOfUtf8(encodedPassword.getValue()); 340 } 341 else if (encodedPasswordFile.hasValue()) 342 { 343 compareMode = true; 344 encodedPW = ByteString.valueOfUtf8(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[] authPWElements; 473 try 474 { 475 authPWElements = AuthPasswordSyntax.decodeAuthPassword(encodedPW.toString()); 476 } 477 catch (DirectoryException de) 478 { 479 printWrappedText(err, ERR_ENCPW_INVALID_ENCODED_AUTHPW.get(de.getMessageObject())); 480 return OPERATIONS_ERROR; 481 } 482 catch (Exception e) 483 { 484 printWrappedText(err, ERR_ENCPW_INVALID_ENCODED_AUTHPW.get(e)); 485 return OPERATIONS_ERROR; 486 } 487 488 String scheme = authPWElements[0]; 489 String authInfo = authPWElements[1]; 490 String authValue = authPWElements[2]; 491 492 PasswordStorageScheme storageScheme = 493 DirectoryServer.getAuthPasswordStorageScheme(scheme); 494 if (storageScheme == null) 495 { 496 printWrappedText(err, ERR_ENCPW_NO_SUCH_AUTH_SCHEME.get(scheme)); 497 return OPERATIONS_ERROR; 498 } 499 500 if (clearPW == null) 501 { 502 clearPW = getClearPW(out, err, argParser, clearPassword, 503 clearPasswordFile, interactivePassword); 504 if (clearPW == null) 505 { 506 return OPERATIONS_ERROR; 507 } 508 } 509 final boolean authPasswordMatches = 510 storageScheme.authPasswordMatches(clearPW, authInfo, authValue); 511 out.println(getOutputMessage(authPasswordMatches)); 512 if (useCompareResultCode.isPresent()) 513 { 514 return authPasswordMatches ? COMPARE_TRUE : COMPARE_FALSE; 515 } 516 return SUCCESS; 517 } 518 else 519 { 520 PasswordStorageScheme storageScheme; 521 String encodedPWString; 522 523 if (UserPasswordSyntax.isEncoded(encodedPW)) 524 { 525 try 526 { 527 String[] userPWElements = 528 UserPasswordSyntax.decodeUserPassword(encodedPW.toString()); 529 encodedPWString = userPWElements[1]; 530 531 storageScheme = 532 DirectoryServer.getPasswordStorageScheme(userPWElements[0]); 533 if (storageScheme == null) 534 { 535 printWrappedText(err, ERR_ENCPW_NO_SUCH_SCHEME.get(userPWElements[0])); 536 return OPERATIONS_ERROR; 537 } 538 } 539 catch (DirectoryException de) 540 { 541 printWrappedText(err, ERR_ENCPW_INVALID_ENCODED_USERPW.get(de.getMessageObject())); 542 return OPERATIONS_ERROR; 543 } 544 catch (Exception e) 545 { 546 printWrappedText(err, ERR_ENCPW_INVALID_ENCODED_USERPW.get(e)); 547 return OPERATIONS_ERROR; 548 } 549 } 550 else 551 { 552 if (! schemeName.isPresent()) 553 { 554 printWrappedText(err, ERR_ENCPW_NO_SCHEME.get(schemeName.getLongIdentifier())); 555 return OPERATIONS_ERROR; 556 } 557 558 encodedPWString = encodedPW.toString(); 559 560 String scheme = toLowerCase(schemeName.getValue()); 561 storageScheme = DirectoryServer.getPasswordStorageScheme(scheme); 562 if (storageScheme == null) 563 { 564 printWrappedText(err, ERR_ENCPW_NO_SUCH_SCHEME.get(scheme)); 565 return OPERATIONS_ERROR; 566 } 567 } 568 569 if (clearPW == null) 570 { 571 clearPW = getClearPW(out, err, argParser, clearPassword, 572 clearPasswordFile, interactivePassword); 573 if (clearPW == null) 574 { 575 return OPERATIONS_ERROR; 576 } 577 } 578 boolean passwordMatches = 579 storageScheme.passwordMatches(clearPW, ByteString 580 .valueOfUtf8(encodedPWString)); 581 out.println(getOutputMessage(passwordMatches)); 582 if (useCompareResultCode.isPresent()) 583 { 584 return passwordMatches ? COMPARE_TRUE : COMPARE_FALSE; 585 } 586 return SUCCESS; 587 } 588 } 589 else 590 { 591 // Try to get a reference to the requested password storage scheme. 592 PasswordStorageScheme storageScheme; 593 if (authPasswordSyntax.isPresent()) 594 { 595 String scheme = schemeName.getValue(); 596 storageScheme = DirectoryServer.getAuthPasswordStorageScheme(scheme); 597 if (storageScheme == null) 598 { 599 printWrappedText(err, ERR_ENCPW_NO_SUCH_AUTH_SCHEME.get(scheme)); 600 return OPERATIONS_ERROR; 601 } 602 } 603 else 604 { 605 String scheme = toLowerCase(schemeName.getValue()); 606 storageScheme = DirectoryServer.getPasswordStorageScheme(scheme); 607 if (storageScheme == null) 608 { 609 printWrappedText(err, ERR_ENCPW_NO_SUCH_SCHEME.get(scheme)); 610 return OPERATIONS_ERROR; 611 } 612 } 613 614 if (authPasswordSyntax.isPresent()) 615 { 616 try 617 { 618 if (clearPW == null) 619 { 620 clearPW = getClearPW(out, err, argParser, clearPassword, 621 clearPasswordFile, interactivePassword); 622 if (clearPW == null) 623 { 624 return OPERATIONS_ERROR; 625 } 626 } 627 encodedPW = storageScheme.encodeAuthPassword(clearPW); 628 629 LocalizableMessage message = ERR_ENCPW_ENCODED_PASSWORD.get(encodedPW); 630 out.println(message); 631 } 632 catch (DirectoryException de) 633 { 634 printWrappedText(err, ERR_ENCPW_CANNOT_ENCODE.get(de.getMessageObject())); 635 return OPERATIONS_ERROR; 636 } 637 catch (Exception e) 638 { 639 printWrappedText(err, ERR_ENCPW_CANNOT_ENCODE.get(getExceptionMessage(e))); 640 return OPERATIONS_ERROR; 641 } 642 } 643 else 644 { 645 try 646 { 647 if (clearPW == null) 648 { 649 clearPW = getClearPW(out, err, argParser, clearPassword, 650 clearPasswordFile, interactivePassword); 651 if (clearPW == null) 652 { 653 return OPERATIONS_ERROR; 654 } 655 } 656 encodedPW = storageScheme.encodePasswordWithScheme(clearPW); 657 658 out.println(ERR_ENCPW_ENCODED_PASSWORD.get(encodedPW)); 659 } 660 catch (DirectoryException de) 661 { 662 printWrappedText(err, ERR_ENCPW_CANNOT_ENCODE.get(de.getMessageObject())); 663 return OPERATIONS_ERROR; 664 } 665 catch (Exception e) 666 { 667 printWrappedText(err, ERR_ENCPW_CANNOT_ENCODE.get(getExceptionMessage(e))); 668 return OPERATIONS_ERROR; 669 } 670 } 671 } 672 673 // If we've gotten here, then all processing completed successfully. 674 return SUCCESS; 675 } 676 677 private static void listPasswordStorageSchemes(PrintStream out, PrintStream err, 678 ConcurrentHashMap<String, PasswordStorageScheme> storageSchemes, boolean authPasswordSchemeName) 679 { 680 if (storageSchemes.isEmpty()) 681 { 682 printWrappedText(err, ERR_ENCPW_NO_STORAGE_SCHEMES.get()); 683 } 684 else 685 { 686 ArrayList<String> nameList = new ArrayList<>(storageSchemes.size()); 687 for (PasswordStorageScheme<?> s : storageSchemes.values()) 688 { 689 if (authPasswordSchemeName) 690 { 691 nameList.add(s.getAuthPasswordSchemeName()); 692 } 693 else 694 { 695 nameList.add(s.getStorageSchemeName()); 696 } 697 } 698 Collections.sort(nameList); 699 700 for (String storageSchemeName : nameList) 701 { 702 out.println(storageSchemeName); 703 } 704 } 705 } 706 707 private static LocalizableMessage getOutputMessage(boolean passwordMatches) 708 { 709 if (passwordMatches) 710 { 711 return INFO_ENCPW_PASSWORDS_MATCH.get(); 712 } 713 return INFO_ENCPW_PASSWORDS_DO_NOT_MATCH.get(); 714 } 715 716 717 718 private static boolean initializeServerComponents(DirectoryServer directoryServer, PrintStream err) 719 { 720 // Initialize the Directory Server crypto manager. 721 try 722 { 723 directoryServer.initializeCryptoManager(); 724 } 725 catch (ConfigException | InitializationException e) 726 { 727 printWrappedText(err, ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(e.getMessage())); 728 return false; 729 } 730 catch (Exception e) 731 { 732 printWrappedText(err, ERR_CANNOT_INITIALIZE_CRYPTO_MANAGER.get(getExceptionMessage(e))); 733 return false; 734 } 735 //Attempt to bring up enough of the server to process schemes requiring 736 //secret keys from the trust store backend (3DES, BLOWFISH, AES, RC4) via 737 //the crypto-manager. 738 try { 739 directoryServer.initializeRootDNConfigManager(); 740 directoryServer.initializePlugins(Collections.EMPTY_SET); 741 initializeServerBackends(directoryServer, err); 742 directoryServer.initializeSubentryManager(); 743 directoryServer.initializeAuthenticationPolicyComponents(); 744 directoryServer.initializeAuthenticatedUsers(); 745 new CryptoManagerSync(); 746 } catch (InitializationException | ConfigException e) { 747 printWrappedText(err, ERR_ENCPW_CANNOT_INITIALIZE_SERVER_COMPONENTS.get(getExceptionMessage(e))); 748 return false; 749 } 750 return true; 751 } 752 753 private static void initializeServerBackends(DirectoryServer directoryServer, PrintStream err) 754 throws InitializationException, ConfigException { 755 directoryServer.initializeRootDSE(); 756 ServerManagementContext context = ServerManagementContext.getInstance(); 757 RootCfg root = context.getRootConfiguration(); 758 ConfigEntry backendRoot; 759 try { 760 DN configEntryDN = DN.valueOf(ConfigConstants.DN_BACKEND_BASE); 761 backendRoot = DirectoryServer.getConfigEntry(configEntryDN); 762 } catch (Exception e) { 763 LocalizableMessage message = ERR_CONFIG_BACKEND_CANNOT_GET_CONFIG_BASE.get( 764 getExceptionMessage(e)); 765 throw new ConfigException(message, e); 766 } 767 if (backendRoot == null) { 768 LocalizableMessage message = ERR_CONFIG_BACKEND_BASE_DOES_NOT_EXIST.get(); 769 throw new ConfigException(message); 770 } 771 for (String name : root.listBackends()) { 772 BackendCfg backendCfg = root.getBackend(name); 773 String backendID = backendCfg.getBackendId(); 774 if((backendCfg instanceof TrustStoreBackendCfg 775 || backendCfg instanceof LDIFBackendCfg) 776 && backendCfg.isEnabled()) 777 { 778 String className = backendCfg.getJavaClass(); 779 Class<?> backendClass; 780 Backend<BackendCfg> backend; 781 try { 782 backendClass = DirectoryServer.loadClass(className); 783 backend = (Backend<BackendCfg>) backendClass.newInstance(); 784 } catch (Exception e) { 785 printWrappedText(err, 786 ERR_CONFIG_BACKEND_CANNOT_INSTANTIATE.get(className, backendCfg.dn(), stackTraceToSingleLineString(e))); 787 continue; 788 } 789 backend.setBackendID(backendID); 790 backend.setWritabilityMode(WritabilityMode.INTERNAL_ONLY); 791 try { 792 backend.configureBackend(backendCfg, directoryServer.getServerContext()); 793 backend.openBackend(); 794 } catch (Exception e) { 795 printWrappedText(err, 796 ERR_CONFIG_BACKEND_CANNOT_INITIALIZE.get(className, backendCfg.dn(), stackTraceToSingleLineString(e))); 797 } 798 try { 799 DirectoryServer.registerBackend(backend); 800 } catch (Exception e) 801 { 802 printWrappedText( 803 err, WARN_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND.get(backendCfg.getBackendId(), getExceptionMessage(e))); 804 } 805 } 806 } 807 } 808 809 /** 810 * Get the clear password. 811 * @param out The output to ask password. 812 * @param err The error output. 813 * @param argParser The argument parser. 814 * @param clearPassword the clear password 815 * @param clearPasswordFile the file in which the password in stored 816 * @param interactivePassword indicate if the password should be asked 817 * interactively. 818 * @return the password or null if an error occurs. 819 */ 820 private static ByteString getClearPW(PrintStream out, PrintStream err, 821 ArgumentParser argParser, StringArgument clearPassword, 822 FileBasedArgument clearPasswordFile, BooleanArgument interactivePassword) 823 { 824 if (clearPassword.hasValue()) 825 { 826 return ByteString.valueOfUtf8(clearPassword.getValue()); 827 } 828 else if (clearPasswordFile.hasValue()) 829 { 830 return ByteString.valueOfUtf8(clearPasswordFile.getValue()); 831 } 832 else if (interactivePassword.isPresent()) 833 { 834 try 835 { 836 EncodePassword encodePassword = new EncodePassword(); 837 String pwd1 = encodePassword.getPassword(INFO_ENCPW_INPUT_PWD_1.get().toString()); 838 String pwd2 = encodePassword.getPassword(INFO_ENCPW_INPUT_PWD_2.get().toString()); 839 if (pwd1.equals(pwd2)) 840 { 841 return ByteString.valueOfUtf8(pwd1); 842 } 843 else 844 { 845 printWrappedText(err, ERR_ENCPW_NOT_SAME_PW.get()); 846 return null; 847 } 848 } 849 catch (IOException e) 850 { 851 printWrappedText(err, ERR_ENCPW_CANNOT_READ_PW.get(e.getMessage())); 852 return null; 853 } 854 } 855 else 856 { 857 argParser.displayMessageAndUsageReference(err, ERR_ENCPW_NO_CLEAR_PW.get(clearPassword.getLongIdentifier(), 858 clearPasswordFile.getLongIdentifier(), interactivePassword.getLongIdentifier())); 859 return null; 860 } 861 } 862 863 /** 864 * Get the password from JDK6 console or from masked password. 865 * @param prompt The message to print out. 866 * @return the password 867 * @throws IOException if an issue occurs when reading the password 868 * from the input 869 */ 870 private String getPassword(String prompt) throws IOException 871 { 872 String password; 873 try 874 { 875 Console console = System.console(); 876 if (console == null) 877 { 878 throw new IOException("No console"); 879 } 880 password = new String(console.readPassword(prompt)); 881 } 882 catch (Exception e) 883 { 884 // Try the fallback to the old trick method. 885 // Create the thread that will erase chars 886 ErasingThread erasingThread = new ErasingThread(prompt); 887 erasingThread.start(); 888 889 password = ""; 890 891 // block until enter is pressed 892 while (true) 893 { 894 char c = (char) System.in.read(); 895 // assume enter pressed, stop masking 896 erasingThread.stopMasking(); 897 if (c == '\r') 898 { 899 c = (char) System.in.read(); 900 if (c == '\n') 901 { 902 break; 903 } 904 } 905 else if (c == '\n') 906 { 907 break; 908 } 909 else 910 { 911 // store the password 912 password += c; 913 } 914 } 915 } 916 return password; 917 } 918 919 920 /** 921 * Thread that mask user input. 922 */ 923 private class ErasingThread extends Thread 924 { 925 926 private boolean stop; 927 private String prompt; 928 929 /** 930 * The class will mask the user input. 931 * @param prompt 932 * The prompt displayed to the user 933 */ 934 public ErasingThread(String prompt) 935 { 936 this.prompt = prompt; 937 } 938 939 /** 940 * Begin masking until asked to stop. 941 */ 942 @Override 943 public void run() 944 { 945 while (!stop) 946 { 947 try 948 { 949 // attempt masking at this rate 950 Thread.sleep(1); 951 } 952 catch (InterruptedException iex) 953 { 954 iex.printStackTrace(); 955 } 956 if (!stop) 957 { 958 System.out.print("\r" + prompt + " \r" + prompt); 959 } 960 System.out.flush(); 961 } 962 } 963 964 /** 965 * Instruct the thread to stop masking. 966 */ 967 public void stopMasking() 968 { 969 this.stop = true; 970 } 971 } 972 973} 974