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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.tools; 028 import org.opends.messages.Message; 029 030 import java.io.BufferedReader; 031 import java.io.FileReader; 032 import java.io.InputStreamReader; 033 import java.io.IOException; 034 import java.io.OutputStream; 035 import java.io.PrintStream; 036 import java.io.Reader; 037 import java.text.ParseException; 038 import java.util.ArrayList; 039 import java.util.LinkedList; 040 import java.util.concurrent.atomic.AtomicInteger; 041 042 import org.opends.server.protocols.asn1.ASN1Exception; 043 import org.opends.server.protocols.asn1.ASN1OctetString; 044 import org.opends.server.protocols.ldap.CompareRequestProtocolOp; 045 import org.opends.server.protocols.ldap.CompareResponseProtocolOp; 046 import org.opends.server.protocols.ldap.LDAPControl; 047 import org.opends.server.protocols.ldap.LDAPFilter; 048 import org.opends.server.protocols.ldap.LDAPMessage; 049 import org.opends.server.protocols.ldap.ProtocolOp; 050 import org.opends.server.types.NullOutputStream; 051 import org.opends.server.types.DebugLogLevel; 052 import org.opends.server.types.LDAPException; 053 import org.opends.server.util.Base64; 054 import org.opends.server.util.EmbeddedUtils; 055 import org.opends.server.util.PasswordReader; 056 import org.opends.server.util.args.ArgumentException; 057 import org.opends.server.util.args.ArgumentParser; 058 import org.opends.server.util.args.BooleanArgument; 059 import org.opends.server.util.args.FileBasedArgument; 060 import org.opends.server.util.args.IntegerArgument; 061 import org.opends.server.util.args.StringArgument; 062 063 import static org.opends.server.loggers.debug.DebugLogger.*; 064 import org.opends.server.loggers.debug.DebugTracer; 065 import static org.opends.messages.ToolMessages.*; 066 import static org.opends.server.protocols.ldap.LDAPResultCode.*; 067 import static org.opends.server.util.ServerConstants.*; 068 import static org.opends.server.util.StaticUtils.*; 069 import static org.opends.server.tools.ToolConstants.*; 070 071 072 /** 073 * This class provides a tool that can be used to issue compare requests to the 074 * Directory Server. 075 */ 076 public class LDAPCompare 077 { 078 /** 079 * The tracer object for the debug logger. 080 */ 081 private static final DebugTracer TRACER = getTracer(); 082 083 /** 084 * The fully-qualified name of this class. 085 */ 086 private static final String CLASS_NAME = 087 "org.opends.server.tools.LDAPCompare"; 088 089 090 // The message ID counter to use for requests. 091 private AtomicInteger nextMessageID; 092 093 // The print stream to use for standard error. 094 private PrintStream err; 095 096 // The print stream to use for standard output. 097 private PrintStream out; 098 099 100 101 /** 102 * Constructor for the LDAPCompare object. 103 * 104 * @param nextMessageID The message ID counter to use for requests. 105 * @param out The print stream to use for standard output. 106 * @param err The print stream to use for standard error. 107 */ 108 public LDAPCompare(AtomicInteger nextMessageID, PrintStream out, 109 PrintStream err) 110 { 111 this.nextMessageID = nextMessageID; 112 this.out = out; 113 this.err = err; 114 } 115 116 /** 117 * Execute the compare request in the specified list of DNs. 118 * 119 * @param connection The connection to execute the request on. 120 * @param attributeType The attribute type to compare. 121 * @param attributeVal The attribute value to compare. 122 * @param lines The list of DNs to compare the attribute in. 123 * @param compareOptions The constraints for the compare request. 124 * 125 * @throws IOException If a problem occurs while communicating with the 126 * Directory Server. 127 * 128 * @throws LDAPException If the server returns an error response. 129 */ 130 public void readAndExecute(LDAPConnection connection, String attributeType, 131 byte[] attributeVal, ArrayList<String> lines, 132 LDAPCompareOptions compareOptions) 133 throws IOException, LDAPException 134 { 135 for(String line : lines) 136 { 137 executeCompare(connection, attributeType, attributeVal, line, 138 compareOptions); 139 } 140 } 141 142 143 /** 144 * Read the specified DNs from the given reader 145 * (file or stdin) and execute the given compare request. 146 * 147 * @param connection The connection to execute the request on. 148 * @param attributeType The attribute type to compare. 149 * @param attributeVal The attribute value to compare. 150 * @param reader The reader to read the list of DNs from. 151 * @param compareOptions The constraints for the compare request. 152 * 153 * @throws IOException If a problem occurs while communicating with the 154 * Directory Server. 155 * 156 * @throws LDAPException If the server returns an error response. 157 */ 158 public void readAndExecute(LDAPConnection connection, String attributeType, 159 byte[] attributeVal, Reader reader, 160 LDAPCompareOptions compareOptions) 161 throws IOException, LDAPException 162 { 163 BufferedReader in = new BufferedReader(reader); 164 String line = null; 165 166 while ((line = in.readLine()) != null) 167 { 168 executeCompare(connection, attributeType, attributeVal, line, 169 compareOptions); 170 } 171 in.close(); 172 } 173 174 175 /** 176 * Execute the compare request for the specified DN entry. 177 * 178 * @param connection The connection to execute the request on. 179 * @param attributeType The attribute type to compare. 180 * @param attributeVal The attribute value to compare. 181 * @param line The DN to compare attribute in. 182 * @param compareOptions The constraints for the compare request. 183 * 184 * @throws IOException If a problem occurs while communicating with the 185 * Directory Server. 186 * 187 * @throws LDAPException If the server returns an error response. 188 */ 189 private void executeCompare(LDAPConnection connection, String attributeType, 190 byte[] attributeVal, String line, 191 LDAPCompareOptions compareOptions) 192 throws IOException, LDAPException 193 { 194 ArrayList<LDAPControl> controls = compareOptions.getControls(); 195 ASN1OctetString dnOctetStr = new ASN1OctetString(line); 196 ASN1OctetString attrValOctetStr = new ASN1OctetString(attributeVal); 197 198 ProtocolOp protocolOp = new CompareRequestProtocolOp(dnOctetStr, 199 attributeType, attrValOctetStr); 200 201 202 out.println(INFO_PROCESSING_COMPARE_OPERATION.get( 203 attributeType, String.valueOf(attrValOctetStr), 204 String.valueOf(dnOctetStr))); 205 206 if(!compareOptions.showOperations()) 207 { 208 LDAPMessage responseMessage = null; 209 try 210 { 211 LDAPMessage message = new LDAPMessage(nextMessageID.getAndIncrement(), 212 protocolOp, controls); 213 connection.getLDAPWriter().writeMessage(message); 214 responseMessage = connection.getLDAPReader().readMessage(); 215 } catch(ASN1Exception ae) 216 { 217 if (debugEnabled()) 218 { 219 TRACER.debugCaught(DebugLogLevel.ERROR, ae); 220 } 221 if (!compareOptions.continueOnError()) 222 { 223 throw new IOException(ae.getMessage()); 224 } 225 else 226 { 227 228 Message msg = INFO_OPERATION_FAILED.get("COMPARE"); 229 err.println(wrapText(msg, MAX_LINE_WIDTH)); 230 err.println(wrapText(ae.getMessage(), MAX_LINE_WIDTH)); 231 return; 232 } 233 } 234 235 CompareResponseProtocolOp op = 236 responseMessage.getCompareResponseProtocolOp(); 237 int resultCode = op.getResultCode(); 238 Message errorMessage = op.getErrorMessage(); 239 240 if(resultCode != COMPARE_TRUE && resultCode != COMPARE_FALSE 241 && !compareOptions.continueOnError()) 242 { 243 Message msg = INFO_OPERATION_FAILED.get("COMPARE"); 244 throw new LDAPException(resultCode, errorMessage, msg, 245 op.getMatchedDN(), null); 246 } else 247 { 248 if(resultCode == COMPARE_FALSE) 249 { 250 251 out.println(INFO_COMPARE_OPERATION_RESULT_FALSE.get(line)); 252 } else if(resultCode == COMPARE_TRUE) 253 { 254 255 out.println(INFO_COMPARE_OPERATION_RESULT_TRUE.get(line)); 256 } else 257 { 258 259 Message msg = INFO_OPERATION_FAILED.get("COMPARE"); 260 LDAPToolUtils.printErrorMessage(err, msg, resultCode, errorMessage, 261 op.getMatchedDN()); 262 } 263 } 264 } 265 } 266 267 /** 268 * The main method for LDAPCompare tool. 269 * 270 * @param args The command-line arguments provided to this program. 271 */ 272 273 public static void main(String[] args) 274 { 275 int retCode = mainCompare(args, true, System.out, System.err); 276 277 if(retCode != 0) 278 { 279 System.exit(filterExitCode(retCode)); 280 } 281 } 282 283 /** 284 * Parses the provided command-line arguments and uses that information to 285 * run the ldapcompare tool. 286 * 287 * @param args The command-line arguments provided to this program. 288 * 289 * @return The error code. 290 */ 291 292 public static int mainCompare(String[] args) 293 { 294 return mainCompare(args, true, System.out, System.err); 295 } 296 297 /** 298 * Parses the provided command-line arguments and uses that information to 299 * run the ldapcompare tool. 300 * 301 * @param args The command-line arguments provided to this 302 * program. 303 * @param initializeServer Indicates whether to initialize the server. 304 * @param outStream The output stream to use for standard output, or 305 * <CODE>null</CODE> if standard output is not 306 * needed. 307 * @param errStream The output stream to use for standard error, or 308 * <CODE>null</CODE> if standard error is not 309 * needed. 310 * 311 * @return The error code. 312 */ 313 314 public static int mainCompare(String[] args, boolean initializeServer, 315 OutputStream outStream, OutputStream errStream) 316 { 317 PrintStream out; 318 if (outStream == null) 319 { 320 out = NullOutputStream.printStream(); 321 } 322 else 323 { 324 out = new PrintStream(outStream); 325 } 326 327 PrintStream err; 328 if (errStream == null) 329 { 330 err = NullOutputStream.printStream(); 331 } 332 else 333 { 334 err = new PrintStream(errStream); 335 } 336 337 338 LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions(); 339 LDAPCompareOptions compareOptions = new LDAPCompareOptions(); 340 LDAPConnection connection = null; 341 342 BooleanArgument continueOnError = null; 343 BooleanArgument noop = null; 344 BooleanArgument saslExternal = null; 345 BooleanArgument showUsage = null; 346 BooleanArgument startTLS = null; 347 BooleanArgument trustAll = null; 348 BooleanArgument useSSL = null; 349 BooleanArgument verbose = null; 350 FileBasedArgument bindPasswordFile = null; 351 FileBasedArgument keyStorePasswordFile = null; 352 FileBasedArgument trustStorePasswordFile = null; 353 IntegerArgument port = null; 354 IntegerArgument version = null; 355 StringArgument assertionFilter = null; 356 StringArgument bindDN = null; 357 StringArgument bindPassword = null; 358 StringArgument certNickname = null; 359 StringArgument controlStr = null; 360 StringArgument encodingStr = null; 361 StringArgument filename = null; 362 StringArgument hostName = null; 363 StringArgument keyStorePath = null; 364 StringArgument keyStorePassword = null; 365 StringArgument saslOptions = null; 366 StringArgument trustStorePath = null; 367 StringArgument trustStorePassword = null; 368 StringArgument propertiesFileArgument = null; 369 BooleanArgument noPropertiesFileArgument = null; 370 371 ArrayList<String> dnStrings = new ArrayList<String> (); 372 String attributeType = null; 373 byte[] attributeVal = null; 374 Reader rdr = null; 375 376 // Create the command-line argument parser for use with this program. 377 Message toolDescription = INFO_LDAPCOMPARE_TOOL_DESCRIPTION.get(); 378 ArgumentParser argParser = new ArgumentParser(CLASS_NAME, toolDescription, 379 false, true, 1, 0, 380 " \'attribute:value\' \"DN\" ..."); 381 382 try 383 { 384 propertiesFileArgument = new StringArgument("propertiesFilePath", 385 null, OPTION_LONG_PROP_FILE_PATH, 386 false, false, true, INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null, 387 INFO_DESCRIPTION_PROP_FILE_PATH.get()); 388 argParser.addArgument(propertiesFileArgument); 389 argParser.setFilePropertiesArgument(propertiesFileArgument); 390 391 noPropertiesFileArgument = new BooleanArgument( 392 "noPropertiesFileArgument", null, OPTION_LONG_NO_PROP_FILE, 393 INFO_DESCRIPTION_NO_PROP_FILE.get()); 394 argParser.addArgument(noPropertiesFileArgument); 395 argParser.setNoPropertiesFileArgument(noPropertiesFileArgument); 396 397 hostName = new StringArgument("host", OPTION_SHORT_HOST, 398 OPTION_LONG_HOST, false, false, true, 399 INFO_HOST_PLACEHOLDER.get(), "localhost", 400 null, 401 INFO_DESCRIPTION_HOST.get()); 402 hostName.setPropertyName(OPTION_LONG_HOST); 403 argParser.addArgument(hostName); 404 405 port = new IntegerArgument("port", OPTION_SHORT_PORT, 406 OPTION_LONG_PORT, false, false, true, 407 INFO_PORT_PLACEHOLDER.get(), 389, null, 408 INFO_DESCRIPTION_PORT.get()); 409 port.setPropertyName(OPTION_LONG_PORT); 410 argParser.addArgument(port); 411 412 useSSL = new BooleanArgument("useSSL", OPTION_SHORT_USE_SSL, 413 OPTION_LONG_USE_SSL, 414 INFO_DESCRIPTION_USE_SSL.get()); 415 useSSL.setPropertyName(OPTION_LONG_USE_SSL); 416 argParser.addArgument(useSSL); 417 418 startTLS = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS, 419 OPTION_LONG_START_TLS, 420 INFO_DESCRIPTION_START_TLS.get()); 421 startTLS.setPropertyName(OPTION_LONG_START_TLS); 422 argParser.addArgument(startTLS); 423 424 bindDN = new StringArgument("bindDN", OPTION_SHORT_BINDDN, 425 OPTION_LONG_BINDDN, false, false, true, 426 INFO_BINDDN_PLACEHOLDER.get(), null, null, 427 INFO_DESCRIPTION_BINDDN.get()); 428 bindDN.setPropertyName(OPTION_LONG_BINDDN); 429 argParser.addArgument(bindDN); 430 431 bindPassword = new StringArgument("bindPassword", OPTION_SHORT_BINDPWD, 432 OPTION_LONG_BINDPWD, 433 false, false, true, 434 INFO_BINDPWD_PLACEHOLDER.get(), 435 null, null, 436 INFO_DESCRIPTION_BINDPASSWORD.get()); 437 bindPassword.setPropertyName(OPTION_LONG_BINDPWD); 438 argParser.addArgument(bindPassword); 439 440 bindPasswordFile = 441 new FileBasedArgument("bindPasswordFile", 442 OPTION_SHORT_BINDPWD_FILE, 443 OPTION_LONG_BINDPWD_FILE, 444 false, false, 445 INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, 446 null, INFO_DESCRIPTION_BINDPASSWORDFILE.get()); 447 bindPasswordFile.setPropertyName(OPTION_LONG_BINDPWD_FILE); 448 argParser.addArgument(bindPasswordFile); 449 450 filename = new StringArgument("filename", OPTION_SHORT_FILENAME, 451 OPTION_LONG_FILENAME, false, false, 452 true, INFO_FILE_PLACEHOLDER.get(), null, 453 null, 454 INFO_COMPARE_DESCRIPTION_FILENAME.get()); 455 filename.setPropertyName(OPTION_LONG_FILENAME); 456 argParser.addArgument(filename); 457 458 saslExternal = 459 new BooleanArgument("useSASLExternal", 'r', 460 "useSASLExternal", 461 INFO_DESCRIPTION_USE_SASL_EXTERNAL.get()); 462 saslExternal.setPropertyName("useSASLExternal"); 463 argParser.addArgument(saslExternal); 464 465 saslOptions = new StringArgument("saslOption", OPTION_SHORT_SASLOPTION, 466 OPTION_LONG_SASLOPTION, false, 467 true, true, 468 INFO_SASL_OPTION_PLACEHOLDER.get(), null, 469 null, 470 INFO_DESCRIPTION_SASL_PROPERTIES.get()); 471 saslOptions.setPropertyName(OPTION_LONG_SASLOPTION); 472 argParser.addArgument(saslOptions); 473 474 trustAll = new BooleanArgument("trustAll", 'X', "trustAll", 475 INFO_DESCRIPTION_TRUSTALL.get()); 476 trustAll.setPropertyName("trustAll"); 477 argParser.addArgument(trustAll); 478 479 keyStorePath = new StringArgument("keyStorePath", 480 OPTION_SHORT_KEYSTOREPATH, 481 OPTION_LONG_KEYSTOREPATH, 482 false, false, true, 483 INFO_KEYSTOREPATH_PLACEHOLDER.get(), 484 null, null, 485 INFO_DESCRIPTION_KEYSTOREPATH.get()); 486 keyStorePath.setPropertyName(OPTION_LONG_KEYSTOREPATH); 487 argParser.addArgument(keyStorePath); 488 489 keyStorePassword = new StringArgument("keyStorePassword", 490 OPTION_SHORT_KEYSTORE_PWD, 491 OPTION_LONG_KEYSTORE_PWD, false, false, 492 true, INFO_KEYSTORE_PWD_PLACEHOLDER.get(), 493 null, null, 494 INFO_DESCRIPTION_KEYSTOREPASSWORD.get()); 495 keyStorePassword.setPropertyName(OPTION_LONG_KEYSTORE_PWD); 496 argParser.addArgument(keyStorePassword); 497 498 keyStorePasswordFile = 499 new FileBasedArgument("keyStorePasswordFile", 500 OPTION_SHORT_KEYSTORE_PWD_FILE, 501 OPTION_LONG_KEYSTORE_PWD_FILE, 502 false, false, 503 INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get(), 504 null, null, 505 INFO_DESCRIPTION_KEYSTOREPASSWORD_FILE.get()); 506 keyStorePasswordFile.setPropertyName(OPTION_LONG_KEYSTORE_PWD_FILE); 507 argParser.addArgument(keyStorePasswordFile); 508 509 certNickname = 510 new StringArgument("certnickname", 'N', "certNickname", 511 false, false, true, 512 INFO_NICKNAME_PLACEHOLDER.get(), null, 513 null, INFO_DESCRIPTION_CERT_NICKNAME.get()); 514 certNickname.setPropertyName("certNickname"); 515 argParser.addArgument(certNickname); 516 517 trustStorePath = 518 new StringArgument("trustStorePath", 519 OPTION_SHORT_TRUSTSTOREPATH, 520 OPTION_LONG_TRUSTSTOREPATH, 521 false, false, true, 522 INFO_TRUSTSTOREPATH_PLACEHOLDER.get(), 523 null, null, 524 INFO_DESCRIPTION_TRUSTSTOREPATH.get()); 525 trustStorePath.setPropertyName(OPTION_LONG_TRUSTSTOREPATH); 526 argParser.addArgument(trustStorePath); 527 528 trustStorePassword = 529 new StringArgument("trustStorePassword", null, 530 OPTION_LONG_TRUSTSTORE_PWD, 531 false, false, true, 532 INFO_TRUSTSTORE_PWD_PLACEHOLDER.get(), null, 533 null, INFO_DESCRIPTION_TRUSTSTOREPASSWORD.get()); 534 trustStorePassword.setPropertyName(OPTION_LONG_TRUSTSTORE_PWD); 535 argParser.addArgument(trustStorePassword); 536 537 trustStorePasswordFile = 538 new FileBasedArgument( 539 "trustStorePasswordFile", 540 OPTION_SHORT_TRUSTSTORE_PWD_FILE, 541 OPTION_LONG_TRUSTSTORE_PWD_FILE, false, false, 542 INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get(), null, 543 null, 544 INFO_DESCRIPTION_TRUSTSTOREPASSWORD_FILE.get()); 545 trustStorePasswordFile.setPropertyName(OPTION_LONG_TRUSTSTORE_PWD_FILE); 546 argParser.addArgument(trustStorePasswordFile); 547 548 assertionFilter = new StringArgument("assertionfilter", null, 549 OPTION_LONG_ASSERTION_FILE, false, false, true, 550 INFO_ASSERTION_FILTER_PLACEHOLDER.get(), null, 551 null, 552 INFO_DESCRIPTION_ASSERTION_FILTER.get()); 553 assertionFilter.setPropertyName(OPTION_LONG_ASSERTION_FILE); 554 argParser.addArgument(assertionFilter); 555 556 controlStr = 557 new StringArgument("control", 'J', "control", false, true, true, 558 INFO_LDAP_CONTROL_PLACEHOLDER.get(), 559 null, null, INFO_DESCRIPTION_CONTROLS.get()); 560 controlStr.setPropertyName("control"); 561 argParser.addArgument(controlStr); 562 563 version = new IntegerArgument("version", OPTION_SHORT_PROTOCOL_VERSION, 564 OPTION_LONG_PROTOCOL_VERSION, 565 false, false, true, 566 INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 567 3, null, INFO_DESCRIPTION_VERSION.get()); 568 version.setPropertyName(OPTION_LONG_PROTOCOL_VERSION); 569 argParser.addArgument(version); 570 571 encodingStr = new StringArgument("encoding", 'i', "encoding", 572 false, false, 573 true, INFO_ENCODING_PLACEHOLDER.get(), 574 null, null, 575 INFO_DESCRIPTION_ENCODING.get()); 576 encodingStr.setPropertyName("encoding"); 577 argParser.addArgument(encodingStr); 578 579 continueOnError = new BooleanArgument("continueOnError", 'c', 580 "continueOnError", 581 INFO_DESCRIPTION_CONTINUE_ON_ERROR.get()); 582 continueOnError.setPropertyName("continueOnError"); 583 argParser.addArgument(continueOnError); 584 585 noop = new BooleanArgument("no-op", OPTION_SHORT_DRYRUN, 586 OPTION_LONG_DRYRUN, 587 INFO_DESCRIPTION_NOOP.get()); 588 argParser.addArgument(noop); 589 noop.setPropertyName(OPTION_LONG_DRYRUN); 590 591 verbose = new BooleanArgument("verbose", 'v', "verbose", 592 INFO_DESCRIPTION_VERBOSE.get()); 593 verbose.setPropertyName("verbose"); 594 argParser.addArgument(verbose); 595 596 showUsage = new BooleanArgument("showUsage", OPTION_SHORT_HELP, 597 OPTION_LONG_HELP, 598 INFO_DESCRIPTION_SHOWUSAGE.get()); 599 argParser.addArgument(showUsage); 600 argParser.setUsageArgument(showUsage, out); 601 } catch (ArgumentException ae) 602 { 603 Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()); 604 605 err.println(wrapText(message, MAX_LINE_WIDTH)); 606 return 1; 607 } 608 609 // Parse the command-line arguments provided to this program. 610 try 611 { 612 argParser.parseArguments(args); 613 } 614 catch (ArgumentException ae) 615 { 616 Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage()); 617 618 err.println(wrapText(message, MAX_LINE_WIDTH)); 619 err.println(argParser.getUsage()); 620 return 1; 621 } 622 623 // If we should just display usage or version information, 624 // then print it and exit. 625 if (argParser.usageOrVersionDisplayed()) 626 { 627 return 0; 628 } 629 630 if(bindPassword.isPresent() && bindPasswordFile.isPresent()) 631 { 632 Message message = ERR_TOOL_CONFLICTING_ARGS.get( 633 bindPassword.getLongIdentifier(), 634 bindPasswordFile.getLongIdentifier()); 635 err.println(wrapText(message, MAX_LINE_WIDTH)); 636 return 1; 637 } 638 639 ArrayList<String> attrAndDNStrings = argParser.getTrailingArguments(); 640 641 if(attrAndDNStrings.isEmpty()) 642 { 643 Message message = ERR_LDAPCOMPARE_NO_ATTR.get(); 644 err.println(wrapText(message, MAX_LINE_WIDTH)); 645 return 1; 646 } 647 648 // First element should be an attribute string. 649 String attributeString = attrAndDNStrings.remove(0); 650 651 // Rest are DN strings 652 for(String s : attrAndDNStrings) 653 { 654 dnStrings.add(s); 655 } 656 657 // If no DNs were provided, then exit with an error. 658 if (dnStrings.isEmpty() && (! filename.isPresent()) ) 659 { 660 661 err.println(wrapText(ERR_LDAPCOMPARE_NO_DNS.get(), MAX_LINE_WIDTH)); 662 return 1; 663 } 664 665 // parse the attribute string 666 int idx = attributeString.indexOf(":"); 667 if(idx == -1) 668 { 669 Message message = 670 ERR_LDAPCOMPARE_INVALID_ATTR_STRING.get(attributeString); 671 err.println(wrapText(message, MAX_LINE_WIDTH)); 672 return 1; 673 } 674 attributeType = attributeString.substring(0, idx); 675 String remainder = attributeString.substring(idx+1, 676 attributeString.length()); 677 if (remainder.length() > 0) 678 { 679 char nextChar = remainder.charAt(0); 680 if(nextChar == ':') 681 { 682 String base64 = remainder.substring(1, remainder.length()); 683 try 684 { 685 attributeVal = Base64.decode(base64); 686 } 687 catch (ParseException e) 688 { 689 if (debugEnabled()) 690 { 691 TRACER.debugCaught(DebugLogLevel.ERROR, e); 692 } 693 694 err.println(wrapText( 695 INFO_COMPARE_CANNOT_BASE64_DECODE_ASSERTION_VALUE.get(), 696 MAX_LINE_WIDTH)); 697 return 1; 698 } 699 } else if(nextChar == '<') 700 { 701 try 702 { 703 String filePath = remainder.substring(1, remainder.length()); 704 attributeVal = LDAPToolUtils.readBytesFromFile(filePath, err); 705 } 706 catch (Exception e) 707 { 708 err.println(wrapText( 709 INFO_COMPARE_CANNOT_READ_ASSERTION_VALUE_FROM_FILE.get( 710 String.valueOf(e)), 711 MAX_LINE_WIDTH)); 712 return 1; 713 } 714 } else 715 { 716 attributeVal = remainder.getBytes(); 717 } 718 } 719 else 720 { 721 attributeVal = remainder.getBytes(); 722 } 723 724 String hostNameValue = hostName.getValue(); 725 int portNumber = 389; 726 try 727 { 728 portNumber = port.getIntValue(); 729 } catch (ArgumentException ae) 730 { 731 if (debugEnabled()) 732 { 733 TRACER.debugCaught(DebugLogLevel.ERROR, ae); 734 } 735 err.println(wrapText(ae.getMessage(), MAX_LINE_WIDTH)); 736 return 1; 737 } 738 739 try 740 { 741 int versionNumber = version.getIntValue(); 742 if(versionNumber != 2 && versionNumber != 3) 743 { 744 745 err.println(wrapText(ERR_DESCRIPTION_INVALID_VERSION.get( 746 String.valueOf(versionNumber)), MAX_LINE_WIDTH)); 747 return 1; 748 } 749 connectionOptions.setVersionNumber(versionNumber); 750 } catch(ArgumentException ae) 751 { 752 if (debugEnabled()) 753 { 754 TRACER.debugCaught(DebugLogLevel.ERROR, ae); 755 } 756 err.println(wrapText(ae.getMessage(), MAX_LINE_WIDTH)); 757 return 1; 758 } 759 760 761 String bindDNValue = bindDN.getValue(); 762 String fileNameValue = filename.getValue(); 763 String bindPasswordValue = bindPassword.getValue(); 764 if(bindPasswordValue != null && bindPasswordValue.equals("-")) 765 { 766 // read the password from the stdin. 767 try 768 { 769 out.print(INFO_LDAPAUTH_PASSWORD_PROMPT.get(bindDNValue)); 770 char[] pwChars = PasswordReader.readPassword(); 771 bindPasswordValue = new String(pwChars); 772 } catch(Exception ex) 773 { 774 if (debugEnabled()) 775 { 776 TRACER.debugCaught(DebugLogLevel.ERROR, ex); 777 } 778 err.println(wrapText(ex.getMessage(), MAX_LINE_WIDTH)); 779 return 1; 780 } 781 } else if(bindPasswordValue == null) 782 { 783 // Read from file if it exists. 784 bindPasswordValue = bindPasswordFile.getValue(); 785 } 786 787 String keyStorePathValue = keyStorePath.getValue(); 788 String trustStorePathValue = trustStorePath.getValue(); 789 790 String keyStorePasswordValue = null; 791 if (keyStorePassword.isPresent()) 792 { 793 keyStorePasswordValue = keyStorePassword.getValue(); 794 } 795 else if (keyStorePasswordFile.isPresent()) 796 { 797 keyStorePasswordValue = keyStorePasswordFile.getValue(); 798 } 799 800 String trustStorePasswordValue = null; 801 if (trustStorePassword.isPresent()) 802 { 803 trustStorePasswordValue = trustStorePassword.getValue(); 804 } 805 else if (trustStorePasswordFile.isPresent()) 806 { 807 trustStorePasswordValue = trustStorePasswordFile.getValue(); 808 } 809 810 compareOptions.setShowOperations(noop.isPresent()); 811 compareOptions.setVerbose(verbose.isPresent()); 812 compareOptions.setContinueOnError(continueOnError.isPresent()); 813 compareOptions.setEncoding(encodingStr.getValue()); 814 815 if(controlStr.isPresent()) 816 { 817 for (String ctrlString : controlStr.getValues()) 818 { 819 LDAPControl ctrl = LDAPToolUtils.getControl(ctrlString, err); 820 if(ctrl == null) 821 { 822 Message message = ERR_TOOL_INVALID_CONTROL_STRING.get(ctrlString); 823 err.println(wrapText(message, MAX_LINE_WIDTH)); 824 err.println(argParser.getUsage()); 825 return 1; 826 } 827 compareOptions.getControls().add(ctrl); 828 } 829 } 830 831 if (assertionFilter.isPresent()) 832 { 833 String filterString = assertionFilter.getValue(); 834 LDAPFilter filter; 835 try 836 { 837 filter = LDAPFilter.decode(filterString); 838 839 LDAPControl assertionControl = 840 new LDAPControl(OID_LDAP_ASSERTION, true, 841 new ASN1OctetString(filter.encode().encode())); 842 compareOptions.getControls().add(assertionControl); 843 } 844 catch (LDAPException le) 845 { 846 Message message = ERR_LDAP_ASSERTION_INVALID_FILTER.get( 847 le.getMessage()); 848 err.println(wrapText(message, MAX_LINE_WIDTH)); 849 return 1; 850 } 851 } 852 853 // Set the connection options. 854 // Parse the SASL properties. 855 connectionOptions.setSASLExternal(saslExternal.isPresent()); 856 if(saslOptions.isPresent()) 857 { 858 LinkedList<String> values = saslOptions.getValues(); 859 for(String saslOption : values) 860 { 861 if(saslOption.startsWith("mech=")) 862 { 863 boolean val = connectionOptions.setSASLMechanism(saslOption); 864 if(val == false) 865 { 866 return 1; 867 } 868 } else 869 { 870 boolean val = connectionOptions.addSASLProperty(saslOption); 871 if(val == false) 872 { 873 return 1; 874 } 875 } 876 } 877 } 878 connectionOptions.setUseSSL(useSSL.isPresent()); 879 connectionOptions.setStartTLS(startTLS.isPresent()); 880 881 if(connectionOptions.useSASLExternal()) 882 { 883 if(!connectionOptions.useSSL() && !connectionOptions.useStartTLS()) 884 { 885 Message message = ERR_TOOL_SASLEXTERNAL_NEEDS_SSL_OR_TLS.get(); 886 err.println(wrapText(message, MAX_LINE_WIDTH)); 887 return 1; 888 } 889 if(keyStorePathValue == null) 890 { 891 Message message = ERR_TOOL_SASLEXTERNAL_NEEDS_KEYSTORE.get(); 892 err.println(wrapText(message, MAX_LINE_WIDTH)); 893 return 1; 894 } 895 } 896 897 LDAPCompare ldapCompare = null; 898 try 899 { 900 if (initializeServer) 901 { 902 // Bootstrap and initialize directory data structures. 903 EmbeddedUtils.initializeForClientUse(); 904 } 905 906 // Connect to the specified host with the supplied userDN and password. 907 SSLConnectionFactory sslConnectionFactory = null; 908 if(connectionOptions.useSSL() || connectionOptions.useStartTLS()) 909 { 910 String clientAlias; 911 if (certNickname.isPresent()) 912 { 913 clientAlias = certNickname.getValue(); 914 } 915 else 916 { 917 clientAlias = null; 918 } 919 920 sslConnectionFactory = new SSLConnectionFactory(); 921 sslConnectionFactory.init(trustAll.isPresent(), keyStorePathValue, 922 keyStorePasswordValue, clientAlias, 923 trustStorePathValue, trustStorePasswordValue); 924 connectionOptions.setSSLConnectionFactory(sslConnectionFactory); 925 } 926 927 AtomicInteger nextMessageID = new AtomicInteger(1); 928 connection = new LDAPConnection(hostNameValue, portNumber, 929 connectionOptions, out, err); 930 connection.connectToHost(bindDNValue, bindPasswordValue, nextMessageID); 931 932 933 ldapCompare = new LDAPCompare(nextMessageID, out, err); 934 if(fileNameValue == null && dnStrings.isEmpty()) 935 { 936 // Read from stdin. 937 rdr = new InputStreamReader(System.in); 938 } else if(fileNameValue != null) 939 { 940 rdr = new FileReader(fileNameValue); 941 } 942 if(rdr != null) 943 { 944 ldapCompare.readAndExecute(connection, attributeType, attributeVal, 945 rdr, compareOptions); 946 } else 947 { 948 ldapCompare.readAndExecute(connection, attributeType, attributeVal, 949 dnStrings, compareOptions); 950 } 951 } catch(LDAPException le) 952 { 953 if (debugEnabled()) 954 { 955 TRACER.debugCaught(DebugLogLevel.ERROR, le); 956 } 957 LDAPToolUtils.printErrorMessage( 958 err, le.getMessageObject(), 959 le.getResultCode(), 960 le.getMessageObject(), 961 le.getMatchedDN()); 962 int code = le.getResultCode(); 963 return code; 964 } catch(LDAPConnectionException lce) 965 { 966 if (debugEnabled()) 967 { 968 TRACER.debugCaught(DebugLogLevel.ERROR, lce); 969 } 970 LDAPToolUtils.printErrorMessage(err, 971 lce.getMessageObject(), 972 lce.getResultCode(), 973 lce.getMessageObject(), 974 lce.getMatchedDN()); 975 int code = lce.getResultCode(); 976 return code; 977 } catch(Exception e) 978 { 979 if (debugEnabled()) 980 { 981 TRACER.debugCaught(DebugLogLevel.ERROR, e); 982 } 983 err.println(wrapText(e.getMessage(), MAX_LINE_WIDTH)); 984 return 1; 985 } finally 986 { 987 if(connection != null) 988 { 989 if (ldapCompare == null) 990 { 991 connection.close(null); 992 } 993 else 994 { 995 connection.close(ldapCompare.nextMessageID); 996 } 997 } 998 } 999 return 0; 1000 } 1001 1002 } 1003