001/* 002 * Copyright 2011-2023 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2011-2023 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2011-2023 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.listener; 037 038 039 040import java.io.File; 041import java.io.OutputStream; 042import java.io.Serializable; 043import java.net.Socket; 044import java.util.ArrayList; 045import java.util.EnumSet; 046import java.util.Iterator; 047import java.util.LinkedHashMap; 048import java.util.List; 049import java.util.Map; 050import java.util.Set; 051import java.util.TreeMap; 052import java.util.logging.FileHandler; 053import java.util.logging.Level; 054import java.util.logging.StreamHandler; 055import javax.net.ssl.KeyManager; 056import javax.net.ssl.TrustManager; 057 058import com.unboundid.ldap.sdk.DN; 059import com.unboundid.ldap.sdk.LDAPException; 060import com.unboundid.ldap.sdk.OperationType; 061import com.unboundid.ldap.sdk.ResultCode; 062import com.unboundid.ldap.sdk.Version; 063import com.unboundid.ldap.sdk.schema.Schema; 064import com.unboundid.ldap.sdk.schema.SchemaValidator; 065import com.unboundid.util.CommandLineTool; 066import com.unboundid.util.CryptoHelper; 067import com.unboundid.util.Debug; 068import com.unboundid.util.MinimalLogFormatter; 069import com.unboundid.util.NotMutable; 070import com.unboundid.util.NotNull; 071import com.unboundid.util.Nullable; 072import com.unboundid.util.ObjectPair; 073import com.unboundid.util.StaticUtils; 074import com.unboundid.util.ThreadSafety; 075import com.unboundid.util.ThreadSafetyLevel; 076import com.unboundid.util.args.ArgumentException; 077import com.unboundid.util.args.ArgumentParser; 078import com.unboundid.util.args.BooleanArgument; 079import com.unboundid.util.args.DNArgument; 080import com.unboundid.util.args.IntegerArgument; 081import com.unboundid.util.args.FileArgument; 082import com.unboundid.util.args.StringArgument; 083import com.unboundid.util.ssl.KeyStoreKeyManager; 084import com.unboundid.util.ssl.SSLUtil; 085import com.unboundid.util.ssl.TrustAllTrustManager; 086import com.unboundid.util.ssl.TrustStoreTrustManager; 087import com.unboundid.util.ssl.cert.CertException; 088 089import static com.unboundid.ldap.listener.ListenerMessages.*; 090 091 092 093/** 094 * This class provides a command-line tool that can be used to run an instance 095 * of the in-memory directory server. Instances of the server may also be 096 * created and controlled programmatically using the 097 * {@link InMemoryDirectoryServer} class. 098 * <BR><BR> 099 * The following command-line arguments may be used with this class: 100 * <UL> 101 * <LI>"-b {baseDN}" or "--baseDN {baseDN}" -- specifies a base DN to use for 102 * the server. At least one base DN must be specified, and multiple 103 * base DNs may be provided as separate arguments.</LI> 104 * <LI>"-p {port}" or "--port {port}" -- specifies the port on which the 105 * server should listen for client connections. If this is not provided, 106 * then a free port will be automatically chosen for use by the 107 * server.</LI> 108 * <LI>"-l {path}" or "--ldifFile {path}" -- specifies the path to an LDIF 109 * file to use to initially populate the server. If this is not provided, 110 * then the server will initially be empty. The LDIF file will not be 111 * updated as operations are processed in the server.</LI> 112 * <LI>"-D {bindDN}" or "--additionalBindDN {bindDN}" -- specifies an 113 * additional DN that can be used to authenticate to the server, even if 114 * there is no account for that user. If this is provided, then the 115 * --additionalBindPassword argument must also be given.</LI> 116 * <LI>"-w {password}" or "--additionalBindPassword {password}" -- specifies 117 * the password that should be used when attempting to bind as the user 118 * specified with the "-additionalBindDN" argument. If this is provided, 119 * then the --additionalBindDN argument must also be given.</LI> 120 * <LI>"-c {count}" or "--maxChangeLogEntries {count}" -- Indicates whether an 121 * LDAP changelog should be enabled, and if so how many changelog records 122 * should be maintained. If this argument is not provided, or if it is 123 * provided with a value of zero, then no changelog will be 124 * maintained.</LI> 125 * <LI>"-A" or "--accessLogToStandardOut" -- indicates that access log 126 * information should be written to standard output. This cannot be 127 * provided in conjunction with the "--accessLogFile" argument. If 128 * neither argument is provided, then no access logging will be 129 * performed</LI> 130 * <LI>"-a {path}" or "--accessLogFile {path}" -- specifies the path to a file 131 * that should be used as a server access log. This cannot be provided in 132 * conjunction with the "--accessLogToStandardOut" argument. If neither 133 * argument is provided, then no access logging will be performed</LI> 134 * <LI>"---jsonAccessLogToStandardOut" -- indicates that JSON-formatted access 135 * log information should be written to standard output. This cannot be 136 * provided in conjunction with the "--jsonAccessLogFile" argument. If 137 * neither argument is provided, then no JSON-formatted access logging 138 * will be performed</LI> 139 * <LI>"--jsonAccessLogFile {path}" -- specifies the path to a file that 140 * should be used as a server access log with JSON-formatted messages. 141 * This cannot be provided in conjunction with the 142 * "--jsonAccessLogToStandardOut" argument. If neither argument is 143 * provided, then no JSON-formatted access logging will be performed</LI> 144 * <LI>"--ldapDebugLogToStandardOut" -- Indicates that LDAP debug log 145 * information should be written to standard output. This cannot be 146 * provided in conjunction with the "--ldapDebugLogFile" argument. If 147 * neither argument is provided, then no debug logging will be 148 * performed.</LI> 149 * <LI>"-d {path}" or "--ldapDebugLogFile {path}" -- specifies the path to a 150 * file that should be used as a server LDAP debug log. This cannot be 151 * provided in conjunction with the "--ldapDebugLogToStandardOut" 152 * argument. If neither argument is provided, then no debug logging will 153 * be performed.</LI> 154 * <LI>"-s" or "--useDefaultSchema" -- Indicates that the server should use 155 * the default standard schema provided as part of the LDAP SDK. If 156 * neither this argument nor the "--useSchemaFile" argument is provided, 157 * then the server will not enforce schema compliance.</LI> 158 * <LI>"-S {path}" or "--useSchemaFile {path}" -- specifies the path to a file 159 * or directory containing schema definitions to use for the server. If 160 * neither this argument nor the "--useDefaultSchema" argument is 161 * provided, then the server will not enforce schema compliance. If 162 * the specified path represents a file, then it must be an LDIF file 163 * containing a valid LDAP subschema subentry. If the path is a 164 * directory, then its files will be processed in lexicographic order by 165 * name.</LI> 166 * <LI>"--doNotValidateSchemaDefinitions" -- indicates that the server should 167 * not perform any validation for the custom schema provided using the 168 * --useSchemaFile argument. If this argument is not used and a custom 169 * schema is configured, then the server will validate that schema and 170 * report errors or warnings for any issues that it identifies with that 171 * schema.</LI> 172 * <LI>"--doNotGenerateOperationalAttributes" -- indicates that the server 173 * should not maintain any operational attributes (including entryDN, 174 * entryUUID, subschemaSubentry, creatorsName, createTimestamp, 175 * modifiersName, and modifyTimestamp) in entries.</LI> 176 * <LI>"-I {attr}" or "--equalityIndex {attr}" -- specifies that an equality 177 * index should be maintained for the specified attribute. The equality 178 * index may be used to speed up certain kinds of searches, although it 179 * will cause the server to consume more memory.</LI> 180 * <LI>"-Z" or "--useSSL" -- indicates that the server should encrypt all 181 * communication using SSL. If this is provided, then the 182 * "--keyStorePath" and "--keyStorePassword" arguments must also be 183 * provided, and the "--useStartTLS" argument must not be provided.</LI> 184 * <LI>"-q" or "--useStartTLS" -- indicates that the server should support the 185 * use of the StartTLS extended request. If this is provided, then the 186 * "--keyStorePath" and "--keyStorePassword" arguments must also be 187 * provided, and the "--useSSL" argument must not be provided.</LI> 188 * <LI>"-K {path}" or "--keyStorePath {path}" -- specifies the path to the JKS 189 * key store file that should be used to obtain the server certificate to 190 * use for SSL communication. If this argument is provided, then the 191 * "--keyStorePassword" argument must also be provided, along with exactly 192 * one of the "--useSSL" or "--useStartTLS" arguments.</LI> 193 * <LI>"-W {password}" or "--keyStorePassword {password}" -- specifies the 194 * password that should be used to access the contents of the SSL key 195 * store. If this argument is provided, then the "--keyStorePath" 196 * argument must also be provided, along with exactly one of the 197 * "--useSSL" or "--useStartTLS" arguments.</LI> 198 * <LI>"--keyStoreType {type}" -- specifies the type of keystore represented 199 * by the file specified by the keystore path. If this argument is 200 * provided, then the "--keyStorePath" argument must also be provided, 201 * along with exactly one of the "--useSSL" or "--useStartTLS" arguments. 202 * If this argument is not provided, then a default key store type of 203 * "JKS" will be assumed.</LI> 204 * <LI>"--generateSelfSignedCertificate" -- indicates that the server should 205 * generate a self-signed certificate to use for SSL or StartTLS 206 * communication. If this argument is provided, then exactly one of the 207 * "--useSSL" or "--useStartTLS" arguments must also be specified.</LI> 208 * <LI>"-P {path}" or "--trustStorePath {path}" -- specifies the path to the 209 * JKS trust store file that should be used to determine whether to trust 210 * any SSL certificates that may be presented by the client. If this 211 * argument is provided, then exactly one of the "--useSSL" or 212 * "--useStartTLS" arguments must also be provided. If this argument is 213 * not provided but SSL or StartTLS is to be used, then all client 214 * certificates will be automatically trusted.</LI> 215 * <LI>"-T {password}" or "--trustStorePassword {password}" -- specifies the 216 * password that should be used to access the contents of the SSL trust 217 * store. If this argument is provided, then the "--trustStorePath" 218 * argument must also be provided, along with exactly one of the 219 * "--useSSL" or "--useStartTLS" arguments. If an SSL trust store path 220 * was provided without a trust store password, then the server will 221 * attempt to use the trust store without a password.</LI> 222 * <LI>"--trustStoreType {type}" -- specifies the type of trust store 223 * represented by the file specified by the trust store path. If this 224 * argument is provided, then the "--trustStorePath" argument must also 225 * be provided, along with exactly one of the "--useSSL" or 226 * "--useStartTLS" arguments. If this argument is not provided, then a 227 * default trust store type of "JKS" will be assumed.</LI> 228 * <LI>"--maxConcurrentConnections {num}" -- specifies the maximum number of 229 * concurrent connections that the server will allow.</LI> 230 * <LI>"--sizeLimit {num}" -- specifies the maximum number of entries that 231 * the server will return for a single search operation.</LI> 232 * <LI>"--passwordAttribute {attr}" -- specifies an attribute that will hold 233 * user passwords.</LI> 234 * <LI>"--defaultPasswordEncoding {scheme}" -- specifies the name of the 235 * default scheme that the server will use to encode clear-text 236 * passwords. Allowed values include MD5, SMD5, SHA, SSHA, SHA256, 237 * SSHA256, SHA384, SSHA384, SHA512, SSHA512, CLEAR, BASE64, and HEX.</LI> 238 * <LI>"--allowedOperationType {type}" -- specifies a type of operation that 239 * the server will allow. Allowed values include add, bind, compare, 240 * delete, extended, modify, modify-dn, and search.</LI> 241 * <LI>"--authenticationRequiredOperationType {type}" -- specifies a type of 242 * operation that the server will only allow for authenticated clients. 243 * Allowed values include add, compare, delete, extended, modify, 244 * modify-dn, and search.</LI> 245 * <LI>"--vendorName {name}" -- specifies the vendor name value to appear in 246 * the server root DSE.</LI> 247 * <LI>"--vendorVersion {version}" -- specifies the vendor version value to 248 * appear in the server root DSE.</LI> 249 * </UL> 250 */ 251@NotMutable() 252@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 253public final class InMemoryDirectoryServerTool 254 extends CommandLineTool 255 implements Serializable, LDAPListenerExceptionHandler 256{ 257 /** 258 * The column at which long lines should be wrapped. 259 */ 260 private static final int WRAP_COLUMN = StaticUtils.TERMINAL_WIDTH_COLUMNS - 1; 261 262 263 264 /** 265 * The SSL client authentication policy value that indicates that the server 266 * should not ask the client to present a certificate chain. 267 */ 268 @NotNull private static final String SSL_CLIENT_AUTH_POLICY_PROHIBITED = 269 "prohibited"; 270 271 272 273 /** 274 * The SSL client authentication policy value that indicates that the server 275 * should ask the client to present a certificate chain but will not require 276 * one. 277 */ 278 @NotNull private static final String SSL_CLIENT_AUTH_POLICY_OPTIONAL = 279 "optional"; 280 281 282 283 /** 284 * The SSL client authentication policy value that indicates that the server 285 * should require the client to present a certificate chain. 286 */ 287 @NotNull private static final String SSL_CLIENT_AUTH_POLICY_REQUIRED = 288 "required"; 289 290 291 292 /** 293 * The serial version UID for this serializable class. 294 */ 295 private static final long serialVersionUID = 6484637038039050412L; 296 297 298 299 // The argument used to indicate that access log information should be written 300 // to standard output. 301 @Nullable private BooleanArgument accessLogToStandardOutArgument; 302 303 // Indicates that the should not maintain operational attributes in entries. 304 @Nullable private BooleanArgument doNotGenerateOperationalAttributesArgument; 305 306 // Indicates that the should not attempt to validate custom schema definitions 307 // provided by the useSchemaFile argument. 308 @Nullable private BooleanArgument doNotValidateSchemaDefinitionsArgument; 309 310 // The argument used to prevent the in-memory server from starting. This is 311 // only intended to be used for internal testing purposes. 312 @Nullable private BooleanArgument dontStartArgument; 313 314 // The argument used to indicate that the server should generate a self-signed 315 // certificate for use in SSL or StartTLS negotiation. 316 @Nullable private BooleanArgument generateSelfSignedCertificateArgument; 317 318 // The argument used to indicate that JSON-formatted access log information 319 // should be written to standard output. 320 @Nullable private BooleanArgument jsonAccessLogToStandardOutArgument; 321 322 // The argument used to indicate that LDAP debug log information should be 323 // written to standard output. 324 @Nullable private BooleanArgument ldapDebugLogToStandardOutArgument; 325 326 // The argument used to indicate that the default standard schema should be 327 // used. 328 @Nullable private BooleanArgument useDefaultSchemaArgument; 329 330 // The argument used to indicate that the server should use SSL 331 @Nullable private BooleanArgument useSSLArgument; 332 333 // The argument used to indicate that the server should support the StartTLS 334 // extended operation 335 @Nullable private BooleanArgument useStartTLSArgument; 336 337 // The argument used to specify an additional bind DN to use for the server. 338 @Nullable private DNArgument additionalBindDNArgument; 339 340 // The argument used to specify the base DNs to use for the server. 341 @Nullable private DNArgument baseDNArgument; 342 343 // The argument used to specify the path to an access log file to which 344 // information should be written about operations processed by the server. 345 @Nullable private FileArgument accessLogFileArgument; 346 347 // The argument used to specify the code log file to use, if any. 348 @Nullable private FileArgument codeLogFile; 349 350 // The argument used to specify the path to an access log file to which 351 // JSON-formatted operation should be written about operations processed by 352 // the server. 353 @Nullable private FileArgument jsonAccessLogFileArgument; 354 355 // The argument used to specify the path to the SSL key store file. 356 @Nullable private FileArgument keyStorePathArgument; 357 358 // The argument used to specify the path to an LDAP debug log file to which 359 // information should be written about detailed LDAP communication performed 360 // by the server. 361 @Nullable private FileArgument ldapDebugLogFileArgument; 362 363 // The argument used to specify the path to an LDIF file with data to use to 364 // initially populate the server. 365 @Nullable private FileArgument ldifFileArgument; 366 367 // The argument used to specify the path to the SSL trust store file. 368 @Nullable private FileArgument trustStorePathArgument; 369 370 // The argument used to specify the path to a directory containing schema 371 // definitions. 372 @Nullable private FileArgument useSchemaFileArgument; 373 374 // The in-memory directory server instance that has been created by this tool. 375 @Nullable private InMemoryDirectoryServer directoryServer; 376 377 // The argument used to specify the maximum number of changelog entries that 378 // the server should maintain. 379 @Nullable private IntegerArgument maxChangeLogEntriesArgument; 380 381 // The argument used to specify the maximum number of concurrent connections. 382 @Nullable private IntegerArgument maxConcurrentConnectionsArgument; 383 384 // The argument used to specify the port on which the server should listen. 385 @Nullable private IntegerArgument portArgument; 386 387 // The argument used to specify the maximum search size limit. 388 @Nullable private IntegerArgument sizeLimitArgument; 389 390 // The argument used to specify the password for the additional bind DN. 391 @Nullable private StringArgument additionalBindPasswordArgument; 392 393 // The argument used to specify the types of allowed operations. 394 @Nullable private StringArgument allowedOperationTypeArgument; 395 396 // The argument used to specify the types of operations for which 397 // authentication is required. 398 @Nullable private StringArgument authenticationRequiredOperationTypeArgument; 399 400 // The argument used to specify the name of the default encoding scheme to use 401 // use for clear-text passwords. 402 @Nullable private StringArgument defaultPasswordEncodingArgument; 403 404 // The argument used to specify the attributes for which to maintain equality 405 // indexes. 406 @Nullable private StringArgument equalityIndexArgument; 407 408 // The argument used to specify the password to use to access the contents of 409 // the SSL key store 410 @Nullable private StringArgument keyStorePasswordArgument; 411 412 // The argument used to specify the key store type. 413 @Nullable private StringArgument keyStoreTypeArgument; 414 415 // The argument used to specify the password attribute types. 416 @Nullable private StringArgument passwordAttributeArgument; 417 418 // The argument used to specify the policy the server should use for TLS 419 // client authentication. 420 @Nullable private StringArgument sslClientAuthPolicy; 421 422 // The argument used to specify the password to use to access the contents of 423 // the SSL trust store 424 @Nullable private StringArgument trustStorePasswordArgument; 425 426 // The argument used to specify the trust store type. 427 @Nullable private StringArgument trustStoreTypeArgument; 428 429 // The argument used to specify the server vendor name. 430 @Nullable private StringArgument vendorNameArgument; 431 432 // The argument used to specify the server vendor version. 433 @Nullable private StringArgument vendorVersionArgument; 434 435 436 437 /** 438 * Parse the provided command line arguments and uses them to start the 439 * directory server. 440 * 441 * @param args The command line arguments provided to this program. 442 */ 443 public static void main(@NotNull final String... args) 444 { 445 final ResultCode resultCode = main(args, System.out, System.err); 446 if (resultCode != ResultCode.SUCCESS) 447 { 448 System.exit(resultCode.intValue()); 449 } 450 } 451 452 453 454 /** 455 * Parse the provided command line arguments and uses them to start the 456 * directory server. 457 * 458 * @param outStream The output stream to which standard out should be 459 * written. It may be {@code null} if output should be 460 * suppressed. 461 * @param errStream The output stream to which standard error should be 462 * written. It may be {@code null} if error messages 463 * should be suppressed. 464 * @param args The command line arguments provided to this program. 465 * 466 * @return A result code indicating whether the processing was successful. 467 */ 468 @NotNull() 469 public static ResultCode main(@NotNull final String[] args, 470 @Nullable final OutputStream outStream, 471 @Nullable final OutputStream errStream) 472 { 473 final InMemoryDirectoryServerTool tool = 474 new InMemoryDirectoryServerTool(outStream, errStream); 475 return tool.runTool(args); 476 } 477 478 479 480 /** 481 * Creates a new instance of this tool that use the provided output streams 482 * for standard output and standard error. 483 * 484 * @param outStream The output stream to use for standard output. It may be 485 * {@code System.out} for the JVM's default standard output 486 * stream, {@code null} if no output should be generated, 487 * or a custom output stream if the output should be sent 488 * to an alternate location. 489 * @param errStream The output stream to use for standard error. It may be 490 * {@code System.err} for the JVM's default standard error 491 * stream, {@code null} if no output should be generated, 492 * or a custom output stream if the output should be sent 493 * to an alternate location. 494 */ 495 public InMemoryDirectoryServerTool(@Nullable final OutputStream outStream, 496 @Nullable final OutputStream errStream) 497 { 498 super(outStream, errStream); 499 500 directoryServer = null; 501 doNotGenerateOperationalAttributesArgument = null; 502 doNotValidateSchemaDefinitionsArgument = null; 503 dontStartArgument = null; 504 generateSelfSignedCertificateArgument = null; 505 useDefaultSchemaArgument = null; 506 useSSLArgument = null; 507 useStartTLSArgument = null; 508 additionalBindDNArgument = null; 509 baseDNArgument = null; 510 accessLogToStandardOutArgument = null; 511 accessLogFileArgument = null; 512 jsonAccessLogToStandardOutArgument = null; 513 jsonAccessLogFileArgument = null; 514 keyStorePathArgument = null; 515 ldapDebugLogToStandardOutArgument = null; 516 ldapDebugLogFileArgument = null; 517 ldifFileArgument = null; 518 trustStorePathArgument = null; 519 useSchemaFileArgument = null; 520 maxChangeLogEntriesArgument = null; 521 maxConcurrentConnectionsArgument = null; 522 portArgument = null; 523 sizeLimitArgument = null; 524 additionalBindPasswordArgument = null; 525 allowedOperationTypeArgument = null; 526 authenticationRequiredOperationTypeArgument = null; 527 defaultPasswordEncodingArgument = null; 528 equalityIndexArgument = null; 529 keyStorePasswordArgument = null; 530 keyStoreTypeArgument = null; 531 passwordAttributeArgument = null; 532 sslClientAuthPolicy = null; 533 trustStorePasswordArgument = null; 534 trustStoreTypeArgument = null; 535 vendorNameArgument = null; 536 vendorVersionArgument = null; 537 } 538 539 540 541 /** 542 * {@inheritDoc} 543 */ 544 @Override() 545 @NotNull() 546 public String getToolName() 547 { 548 return "in-memory-directory-server"; 549 } 550 551 552 553 /** 554 * {@inheritDoc} 555 */ 556 @Override() 557 @NotNull() 558 public String getToolDescription() 559 { 560 return INFO_MEM_DS_TOOL_DESC.get(InMemoryDirectoryServer.class.getName()); 561 } 562 563 564 565 /** 566 * Retrieves the version string for this tool. 567 * 568 * @return The version string for this tool. 569 */ 570 @Override() 571 @NotNull() 572 public String getToolVersion() 573 { 574 return Version.NUMERIC_VERSION_STRING; 575 } 576 577 578 579 /** 580 * {@inheritDoc} 581 */ 582 @Override() 583 public void addToolArguments(@NotNull final ArgumentParser parser) 584 throws ArgumentException 585 { 586 portArgument = new IntegerArgument('p', "port", false, 1, 587 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PORT.get(), 588 INFO_MEM_DS_TOOL_ARG_DESC_PORT.get(), 0, 65_535); 589 portArgument.setArgumentGroupName( 590 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 591 parser.addArgument(portArgument); 592 593 useSSLArgument = new BooleanArgument('Z', "useSSL", 594 INFO_MEM_DS_TOOL_ARG_DESC_USE_SSL.get()); 595 useSSLArgument.setArgumentGroupName( 596 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 597 useSSLArgument.addLongIdentifier("use-ssl", true); 598 parser.addArgument(useSSLArgument); 599 600 useStartTLSArgument = new BooleanArgument('q', "useStartTLS", 601 INFO_MEM_DS_TOOL_ARG_DESC_USE_START_TLS.get()); 602 useStartTLSArgument.setArgumentGroupName( 603 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 604 useStartTLSArgument.addLongIdentifier("use-starttls", true); 605 useStartTLSArgument.addLongIdentifier("use-start-tls", true); 606 parser.addArgument(useStartTLSArgument); 607 608 keyStorePathArgument = new FileArgument('K', "keyStorePath", false, 1, 609 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 610 INFO_MEM_DS_TOOL_ARG_DESC_KEY_STORE_PATH.get(), true, true, true, 611 false); 612 keyStorePathArgument.setArgumentGroupName( 613 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 614 keyStorePathArgument.addLongIdentifier("key-store-path", true); 615 parser.addArgument(keyStorePathArgument); 616 617 keyStorePasswordArgument = new StringArgument('W', "keyStorePassword", 618 false, 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PASSWORD.get(), 619 INFO_MEM_DS_TOOL_ARG_DESC_KEY_STORE_PW.get()); 620 keyStorePasswordArgument.setSensitive(true); 621 keyStorePasswordArgument.setArgumentGroupName( 622 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 623 keyStorePasswordArgument.addLongIdentifier("keyStorePIN", true); 624 keyStorePasswordArgument.addLongIdentifier("key-store-password", true); 625 keyStorePasswordArgument.addLongIdentifier("key-store-pin", true); 626 parser.addArgument(keyStorePasswordArgument); 627 628 keyStoreTypeArgument = new StringArgument(null, "keyStoreType", 629 false, 1, "{type}", INFO_MEM_DS_TOOL_ARG_DESC_KEY_STORE_TYPE.get(), 630 CryptoHelper.KEY_STORE_TYPE_JKS); 631 keyStoreTypeArgument.setArgumentGroupName( 632 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 633 keyStoreTypeArgument.addLongIdentifier("keyStoreFormat", true); 634 keyStoreTypeArgument.addLongIdentifier("key-store-type", true); 635 keyStoreTypeArgument.addLongIdentifier("key-store-format", true); 636 parser.addArgument(keyStoreTypeArgument); 637 638 generateSelfSignedCertificateArgument = new BooleanArgument(null, 639 "generateSelfSignedCertificate", 1, 640 INFO_MEM_DS_TOOL_ARG_DESC_SELF_SIGNED_CERT.get()); 641 generateSelfSignedCertificateArgument.setArgumentGroupName( 642 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 643 generateSelfSignedCertificateArgument.addLongIdentifier( 644 "useSelfSignedCertificate", true); 645 generateSelfSignedCertificateArgument.addLongIdentifier( 646 "selfSignedCertificate", true); 647 generateSelfSignedCertificateArgument.addLongIdentifier( 648 "generate-self-signed-certificate", true); 649 generateSelfSignedCertificateArgument.addLongIdentifier( 650 "use-self-signed-certificate", true); 651 generateSelfSignedCertificateArgument.addLongIdentifier( 652 "self-signed-certificate", true); 653 parser.addArgument(generateSelfSignedCertificateArgument); 654 655 trustStorePathArgument = new FileArgument('P', "trustStorePath", false, 1, 656 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 657 INFO_MEM_DS_TOOL_ARG_DESC_TRUST_STORE_PATH.get(), true, true, true, 658 false); 659 trustStorePathArgument.setArgumentGroupName( 660 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 661 trustStorePathArgument.addLongIdentifier("trust-store-path", true); 662 parser.addArgument(trustStorePathArgument); 663 664 trustStorePasswordArgument = new StringArgument('T', "trustStorePassword", 665 false, 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PASSWORD.get(), 666 INFO_MEM_DS_TOOL_ARG_DESC_TRUST_STORE_PW.get()); 667 trustStorePasswordArgument.setSensitive(true); 668 trustStorePasswordArgument.setArgumentGroupName( 669 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 670 trustStorePasswordArgument.addLongIdentifier("trustStorePIN", true); 671 trustStorePasswordArgument.addLongIdentifier("trust-store-password", true); 672 trustStorePasswordArgument.addLongIdentifier("trust-store-pin", true); 673 parser.addArgument(trustStorePasswordArgument); 674 675 trustStoreTypeArgument = new StringArgument(null, "trustStoreType", 676 false, 1, "{type}", INFO_MEM_DS_TOOL_ARG_DESC_TRUST_STORE_TYPE.get(), 677 CryptoHelper.KEY_STORE_TYPE_JKS); 678 trustStoreTypeArgument.setArgumentGroupName( 679 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 680 trustStoreTypeArgument.addLongIdentifier("trustStoreFormat", true); 681 trustStoreTypeArgument.addLongIdentifier("trust-store-type", true); 682 trustStoreTypeArgument.addLongIdentifier("trust-store-format", true); 683 parser.addArgument(trustStoreTypeArgument); 684 685 sslClientAuthPolicy = new StringArgument(null, "sslClientAuthPolicy", false, 686 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_SSL_CLIENT_AUTH_POLICY.get(), 687 INFO_MEM_DS_TOOL_ARG_DESC_SSL_CLIENT_AUTH_POLICY.get(), 688 StaticUtils.setOf( 689 SSL_CLIENT_AUTH_POLICY_PROHIBITED, 690 SSL_CLIENT_AUTH_POLICY_OPTIONAL, 691 SSL_CLIENT_AUTH_POLICY_REQUIRED), 692 SSL_CLIENT_AUTH_POLICY_PROHIBITED); 693 sslClientAuthPolicy.addLongIdentifier("ssl-client-auth-policy", true); 694 sslClientAuthPolicy.addLongIdentifier("sslClientAuthenticationPolicy", 695 true); 696 sslClientAuthPolicy.addLongIdentifier("ssl-client-authentication-policy", 697 true); 698 sslClientAuthPolicy.addLongIdentifier("sslClientCertificatePolicy", true); 699 sslClientAuthPolicy.addLongIdentifier("ssl-client-certificate-policy", 700 true); 701 sslClientAuthPolicy.addLongIdentifier("sslClientCertPolicy", true); 702 sslClientAuthPolicy.addLongIdentifier("ssl-client-cert-policy", true); 703 sslClientAuthPolicy.setArgumentGroupName( 704 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 705 parser.addArgument(sslClientAuthPolicy); 706 707 maxConcurrentConnectionsArgument = new IntegerArgument(null, 708 "maxConcurrentConnections", false, 1, null, 709 INFO_MEM_DS_TOOL_ARG_DESC_MAX_CONNECTIONS.get(), 1, 710 Integer.MAX_VALUE, Integer.MAX_VALUE); 711 maxConcurrentConnectionsArgument.setArgumentGroupName( 712 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 713 maxConcurrentConnectionsArgument.addLongIdentifier( 714 "maximumConcurrentConnections", true); 715 maxConcurrentConnectionsArgument.addLongIdentifier( 716 "maxConnections", true); 717 maxConcurrentConnectionsArgument.addLongIdentifier( 718 "maximumConnections", true); 719 maxConcurrentConnectionsArgument.addLongIdentifier( 720 "max-concurrent-connections", true); 721 maxConcurrentConnectionsArgument.addLongIdentifier( 722 "maximum-concurrent-connections", true); 723 maxConcurrentConnectionsArgument.addLongIdentifier( 724 "max-connections", true); 725 maxConcurrentConnectionsArgument.addLongIdentifier( 726 "maximum-connections", true); 727 parser.addArgument(maxConcurrentConnectionsArgument); 728 729 dontStartArgument = new BooleanArgument(null, "dontStart", 730 INFO_MEM_DS_TOOL_ARG_DESC_DONT_START.get()); 731 dontStartArgument.setArgumentGroupName( 732 INFO_MEM_DS_TOOL_GROUP_CONNECTIVITY.get()); 733 dontStartArgument.setHidden(true); 734 dontStartArgument.addLongIdentifier("doNotStart", true); 735 dontStartArgument.addLongIdentifier("dont-start", true); 736 dontStartArgument.addLongIdentifier("do-not-start", true); 737 parser.addArgument(dontStartArgument); 738 739 baseDNArgument = new DNArgument('b', "baseDN", true, 0, 740 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_BASE_DN.get(), 741 INFO_MEM_DS_TOOL_ARG_DESC_BASE_DN.get()); 742 baseDNArgument.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_DATA.get()); 743 baseDNArgument.addLongIdentifier("base-dn", true); 744 parser.addArgument(baseDNArgument); 745 746 ldifFileArgument = new FileArgument('l', "ldifFile", false, 1, 747 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 748 INFO_MEM_DS_TOOL_ARG_DESC_LDIF_FILE.get(), true, true, true, false); 749 ldifFileArgument.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_DATA.get()); 750 ldifFileArgument.addLongIdentifier("ldif-file", true); 751 parser.addArgument(ldifFileArgument); 752 753 additionalBindDNArgument = new DNArgument('D', "additionalBindDN", false, 1, 754 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_BIND_DN.get(), 755 INFO_MEM_DS_TOOL_ARG_DESC_ADDITIONAL_BIND_DN.get()); 756 additionalBindDNArgument.setArgumentGroupName( 757 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 758 additionalBindDNArgument.addLongIdentifier("additional-bind-dn", true); 759 parser.addArgument(additionalBindDNArgument); 760 761 additionalBindPasswordArgument = new StringArgument('w', 762 "additionalBindPassword", false, 1, 763 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PASSWORD.get(), 764 INFO_MEM_DS_TOOL_ARG_DESC_ADDITIONAL_BIND_PW.get()); 765 additionalBindPasswordArgument.setSensitive(true); 766 additionalBindPasswordArgument.setArgumentGroupName( 767 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 768 additionalBindPasswordArgument.addLongIdentifier( 769 "additional-bind-password", true); 770 parser.addArgument(additionalBindPasswordArgument); 771 772 useDefaultSchemaArgument = new BooleanArgument('s', "useDefaultSchema", 773 INFO_MEM_DS_TOOL_ARG_DESC_USE_DEFAULT_SCHEMA.get()); 774 useDefaultSchemaArgument.setArgumentGroupName( 775 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 776 useDefaultSchemaArgument.addLongIdentifier("use-default-schema", true); 777 parser.addArgument(useDefaultSchemaArgument); 778 779 useSchemaFileArgument = new FileArgument('S', "useSchemaFile", false, 0, 780 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 781 INFO_MEM_DS_TOOL_ARG_DESC_USE_SCHEMA_FILE.get(), true, true, false, 782 false); 783 useSchemaFileArgument.setArgumentGroupName( 784 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 785 useSchemaFileArgument.addLongIdentifier("use-schema-file", true); 786 parser.addArgument(useSchemaFileArgument); 787 788 doNotValidateSchemaDefinitionsArgument = new BooleanArgument(null, 789 "doNotValidateSchemaDefinitions", 1, 790 INFO_MEM_DS_TOOL_ARG_DESC_DO_NOT_VALIDATE_SCHEMA.get( 791 useSchemaFileArgument.getIdentifierString())); 792 doNotValidateSchemaDefinitionsArgument.setArgumentGroupName( 793 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 794 doNotValidateSchemaDefinitionsArgument.addLongIdentifier( 795 "do-not-validate-schema-definitions", true); 796 parser.addArgument(doNotValidateSchemaDefinitionsArgument); 797 798 doNotGenerateOperationalAttributesArgument = new BooleanArgument(null, 799 "doNotGenerateOperationalAttributes", 1, 800 INFO_MEM_DS_TOOL_ARG_DESC_DO_NOT_GENERATE_OP_ATTRS.get()); 801 doNotGenerateOperationalAttributesArgument.setArgumentGroupName( 802 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 803 doNotGenerateOperationalAttributesArgument.addLongIdentifier( 804 "do-not-generate-operational-attributes"); 805 parser.addArgument(doNotGenerateOperationalAttributesArgument); 806 807 equalityIndexArgument = new StringArgument('I', "equalityIndex", false, 0, 808 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_ATTR.get(), 809 INFO_MEM_DS_TOOL_ARG_DESC_EQ_INDEX.get()); 810 equalityIndexArgument.setArgumentGroupName( 811 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 812 equalityIndexArgument.addLongIdentifier("equality-index", true); 813 parser.addArgument(equalityIndexArgument); 814 815 maxChangeLogEntriesArgument = new IntegerArgument('c', 816 "maxChangeLogEntries", false, 1, 817 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_COUNT.get(), 818 INFO_MEM_DS_TOOL_ARG_DESC_MAX_CHANGELOG_ENTRIES.get(), 0, 819 Integer.MAX_VALUE, 0); 820 maxChangeLogEntriesArgument.setArgumentGroupName( 821 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 822 maxChangeLogEntriesArgument.addLongIdentifier("max-changelog-entries", 823 true); 824 maxChangeLogEntriesArgument.addLongIdentifier("max-change-log-entries", 825 true); 826 parser.addArgument(maxChangeLogEntriesArgument); 827 828 sizeLimitArgument = new IntegerArgument(null, "sizeLimit", false, 1, null, 829 INFO_MEM_DS_TOOL_ARG_DESC_SIZE_LIMIT.get(), 1, Integer.MAX_VALUE, 830 Integer.MAX_VALUE); 831 sizeLimitArgument.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_DATA.get()); 832 sizeLimitArgument.addLongIdentifier("searchSizeLimit", true); 833 sizeLimitArgument.addLongIdentifier("size-limit", true); 834 sizeLimitArgument.addLongIdentifier("search-size-limit", true); 835 parser.addArgument(sizeLimitArgument); 836 837 passwordAttributeArgument = new StringArgument(null, "passwordAttribute", 838 false, 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_ATTR.get(), 839 INFO_MEM_DS_TOOL_ARG_DESC_PASSWORD_ATTRIBUTE.get(), "userPassword"); 840 passwordAttributeArgument.setArgumentGroupName( 841 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 842 passwordAttributeArgument.addLongIdentifier("passwordAttributeType", true); 843 passwordAttributeArgument.addLongIdentifier("password-attribute", true); 844 passwordAttributeArgument.addLongIdentifier("password-attribute-type", 845 true); 846 parser.addArgument(passwordAttributeArgument); 847 848 final Set<String> allowedSchemes = StaticUtils.setOf("md5", "smd5", "sha", 849 "ssha", "sha256", "ssha256", "sha384", "ssha384", "sha512", "ssha512", 850 "clear", "base64", "hex"); 851 defaultPasswordEncodingArgument = new StringArgument(null, 852 "defaultPasswordEncoding", false, 1, 853 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_SCHEME.get(), 854 INFO_MEM_DS_TOOL_ARG_DESC_DEFAULT_PASSWORD_ENCODING.get(), 855 allowedSchemes); 856 defaultPasswordEncodingArgument.setArgumentGroupName( 857 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 858 defaultPasswordEncodingArgument.addLongIdentifier( 859 "defaultPasswordEncodingScheme", true); 860 defaultPasswordEncodingArgument.addLongIdentifier( 861 "defaultPasswordStorageScheme", true); 862 defaultPasswordEncodingArgument.addLongIdentifier( 863 "defaultPasswordScheme", true); 864 defaultPasswordEncodingArgument.addLongIdentifier( 865 "default-password-encoding", true); 866 defaultPasswordEncodingArgument.addLongIdentifier( 867 "default-password-encoding-scheme", true); 868 defaultPasswordEncodingArgument.addLongIdentifier( 869 "default-password-storage-scheme", true); 870 defaultPasswordEncodingArgument.addLongIdentifier( 871 "default-password-scheme", true); 872 parser.addArgument(defaultPasswordEncodingArgument); 873 874 final Set<String> allowedOperationTypeAllowedValues = StaticUtils.setOf( 875 "add", "bind", "compare", "delete", "extended", "modify", "modify-dn", 876 "search"); 877 allowedOperationTypeArgument = new StringArgument(null, 878 "allowedOperationType", false, 0, 879 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_TYPE.get(), 880 INFO_MEM_DS_TOOL_ARG_DESC_ALLOWED_OP_TYPE.get(), 881 allowedOperationTypeAllowedValues); 882 allowedOperationTypeArgument.setArgumentGroupName( 883 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 884 allowedOperationTypeArgument.addLongIdentifier("allowed-operation-type", 885 true); 886 parser.addArgument(allowedOperationTypeArgument); 887 888 final Set<String> authRequiredTypeAllowedValues = StaticUtils.setOf("add", 889 "compare", "delete", "extended", "modify", "modify-dn", "search"); 890 authenticationRequiredOperationTypeArgument = new StringArgument(null, 891 "authenticationRequiredOperationType", false, 0, 892 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_TYPE.get(), 893 INFO_MEM_DS_TOOL_ARG_DESC_AUTH_REQUIRED_OP_TYPE.get(), 894 authRequiredTypeAllowedValues); 895 authenticationRequiredOperationTypeArgument.setArgumentGroupName( 896 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 897 authenticationRequiredOperationTypeArgument.addLongIdentifier( 898 "requiredAuthenticationOperationType", true); 899 authenticationRequiredOperationTypeArgument.addLongIdentifier( 900 "requireAuthenticationOperationType", true); 901 authenticationRequiredOperationTypeArgument.addLongIdentifier( 902 "authentication-required-operation-type", true); 903 authenticationRequiredOperationTypeArgument.addLongIdentifier( 904 "required-authentication-operation-type", true); 905 authenticationRequiredOperationTypeArgument.addLongIdentifier( 906 "require-authentication-operation-type", true); 907 parser.addArgument(authenticationRequiredOperationTypeArgument); 908 909 vendorNameArgument = new StringArgument(null, "vendorName", false, 1, 910 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_VALUE.get(), 911 INFO_MEM_DS_TOOL_ARG_DESC_VENDOR_NAME.get()); 912 vendorNameArgument.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_DATA.get()); 913 vendorNameArgument.addLongIdentifier("vendor-name", true); 914 parser.addArgument(vendorNameArgument); 915 916 vendorVersionArgument = new StringArgument(null, "vendorVersion", false, 1, 917 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_VALUE.get(), 918 INFO_MEM_DS_TOOL_ARG_DESC_VENDOR_VERSION.get()); 919 vendorVersionArgument.setArgumentGroupName( 920 INFO_MEM_DS_TOOL_GROUP_DATA.get()); 921 vendorVersionArgument.addLongIdentifier("vendor-version", true); 922 parser.addArgument(vendorVersionArgument); 923 924 accessLogToStandardOutArgument = new BooleanArgument('A', 925 "accessLogToStandardOut", 926 INFO_MEM_DS_TOOL_ARG_DESC_ACCESS_LOG_TO_STDOUT.get()); 927 accessLogToStandardOutArgument.setArgumentGroupName( 928 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 929 accessLogToStandardOutArgument.addLongIdentifier( 930 "access-log-to-standard-out", true); 931 parser.addArgument(accessLogToStandardOutArgument); 932 933 accessLogFileArgument = new FileArgument('a', "accessLogFile", false, 1, 934 INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 935 INFO_MEM_DS_TOOL_ARG_DESC_ACCESS_LOG_FILE.get(), false, true, true, 936 false); 937 accessLogFileArgument.setArgumentGroupName( 938 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 939 accessLogFileArgument.addLongIdentifier("access-log-format", true); 940 parser.addArgument(accessLogFileArgument); 941 942 jsonAccessLogToStandardOutArgument = new BooleanArgument(null, 943 "jsonAccessLogToStandardOut", 944 INFO_MEM_DS_TOOL_ARG_DESC_JSON_ACCESS_LOG_TO_STDOUT.get()); 945 jsonAccessLogToStandardOutArgument.setArgumentGroupName( 946 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 947 jsonAccessLogToStandardOutArgument.addLongIdentifier( 948 "json-access-log-to-standard-out", true); 949 parser.addArgument(jsonAccessLogToStandardOutArgument); 950 951 jsonAccessLogFileArgument = new FileArgument(null, "jsonAccessLogFile", 952 false, 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 953 INFO_MEM_DS_TOOL_ARG_DESC_JSON_ACCESS_LOG_FILE.get(), false, true, 954 true, false); 955 jsonAccessLogFileArgument.setArgumentGroupName( 956 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 957 jsonAccessLogFileArgument.addLongIdentifier("json-access-log-format", true); 958 parser.addArgument(jsonAccessLogFileArgument); 959 960 ldapDebugLogToStandardOutArgument = new BooleanArgument(null, 961 "ldapDebugLogToStandardOut", 962 INFO_MEM_DS_TOOL_ARG_DESC_LDAP_DEBUG_LOG_TO_STDOUT.get()); 963 ldapDebugLogToStandardOutArgument.setArgumentGroupName( 964 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 965 ldapDebugLogToStandardOutArgument.addLongIdentifier( 966 "ldap-debug-log-to-standard-out", true); 967 parser.addArgument(ldapDebugLogToStandardOutArgument); 968 969 ldapDebugLogFileArgument = new FileArgument('d', "ldapDebugLogFile", false, 970 1, INFO_MEM_DS_TOOL_ARG_PLACEHOLDER_PATH.get(), 971 INFO_MEM_DS_TOOL_ARG_DESC_LDAP_DEBUG_LOG_FILE.get(), false, true, true, 972 false); 973 ldapDebugLogFileArgument.setArgumentGroupName( 974 INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 975 ldapDebugLogFileArgument.addLongIdentifier("ldap-debug-log-file", true); 976 parser.addArgument(ldapDebugLogFileArgument); 977 978 codeLogFile = new FileArgument('C', "codeLogFile", false, 1, "{path}", 979 INFO_MEM_DS_TOOL_ARG_DESC_CODE_LOG_FILE.get(), false, true, true, 980 false); 981 codeLogFile.setArgumentGroupName(INFO_MEM_DS_TOOL_GROUP_LOGGING.get()); 982 codeLogFile.addLongIdentifier("code-log-file", true); 983 parser.addArgument(codeLogFile); 984 985 parser.addExclusiveArgumentSet(useDefaultSchemaArgument, 986 useSchemaFileArgument); 987 988 parser.addDependentArgumentSet(doNotValidateSchemaDefinitionsArgument, 989 useSchemaFileArgument); 990 991 parser.addExclusiveArgumentSet(useSSLArgument, useStartTLSArgument); 992 993 parser.addExclusiveArgumentSet(keyStorePathArgument, 994 generateSelfSignedCertificateArgument); 995 996 parser.addExclusiveArgumentSet(accessLogToStandardOutArgument, 997 accessLogFileArgument); 998 999 parser.addExclusiveArgumentSet(jsonAccessLogToStandardOutArgument, 1000 jsonAccessLogFileArgument); 1001 1002 parser.addExclusiveArgumentSet(ldapDebugLogToStandardOutArgument, 1003 ldapDebugLogFileArgument); 1004 1005 parser.addDependentArgumentSet(additionalBindDNArgument, 1006 additionalBindPasswordArgument); 1007 1008 parser.addDependentArgumentSet(additionalBindPasswordArgument, 1009 additionalBindDNArgument); 1010 1011 parser.addDependentArgumentSet(useSSLArgument, keyStorePathArgument, 1012 generateSelfSignedCertificateArgument); 1013 1014 parser.addDependentArgumentSet(keyStorePathArgument, 1015 keyStorePasswordArgument); 1016 1017 parser.addDependentArgumentSet(keyStorePasswordArgument, 1018 keyStorePathArgument); 1019 1020 parser.addDependentArgumentSet(keyStoreTypeArgument, 1021 keyStorePathArgument); 1022 1023 parser.addDependentArgumentSet(useStartTLSArgument, keyStorePathArgument, 1024 generateSelfSignedCertificateArgument); 1025 1026 parser.addDependentArgumentSet(keyStorePathArgument, useSSLArgument, 1027 useStartTLSArgument); 1028 1029 parser.addDependentArgumentSet(generateSelfSignedCertificateArgument, 1030 useSSLArgument, useStartTLSArgument); 1031 1032 parser.addDependentArgumentSet(trustStorePathArgument, useSSLArgument, 1033 useStartTLSArgument); 1034 1035 parser.addDependentArgumentSet(trustStorePasswordArgument, 1036 trustStorePathArgument); 1037 1038 parser.addDependentArgumentSet(trustStoreTypeArgument, 1039 trustStorePathArgument); 1040 } 1041 1042 1043 1044 /** 1045 * {@inheritDoc} 1046 */ 1047 @Override() 1048 public boolean supportsInteractiveMode() 1049 { 1050 return true; 1051 } 1052 1053 1054 1055 /** 1056 * {@inheritDoc} 1057 */ 1058 @Override() 1059 public boolean defaultsToInteractiveMode() 1060 { 1061 return true; 1062 } 1063 1064 1065 1066 /** 1067 * Indicates whether this tool supports the use of a properties file for 1068 * specifying default values for arguments that aren't specified on the 1069 * command line. 1070 * 1071 * @return {@code true} if this tool supports the use of a properties file 1072 * for specifying default values for arguments that aren't specified 1073 * on the command line, or {@code false} if not. 1074 */ 1075 @Override() 1076 public boolean supportsPropertiesFile() 1077 { 1078 return true; 1079 } 1080 1081 1082 1083 /** 1084 * {@inheritDoc} 1085 */ 1086 @Override() 1087 @NotNull() 1088 public ResultCode doToolProcessing() 1089 { 1090 // Create a base configuration. 1091 final InMemoryDirectoryServerConfig serverConfig; 1092 try 1093 { 1094 serverConfig = getConfig(); 1095 } 1096 catch (final LDAPException le) 1097 { 1098 Debug.debugException(le); 1099 wrapErr(0, WRAP_COLUMN, 1100 ERR_MEM_DS_TOOL_ERROR_INITIALIZING_CONFIG.get(le.getMessage())); 1101 return le.getResultCode(); 1102 } 1103 1104 1105 // Create the server instance using the provided configuration, but don't 1106 // start it yet. 1107 try 1108 { 1109 directoryServer = new InMemoryDirectoryServer(serverConfig); 1110 } 1111 catch (final LDAPException le) 1112 { 1113 Debug.debugException(le); 1114 wrapErr(0, WRAP_COLUMN, 1115 ERR_MEM_DS_TOOL_ERROR_CREATING_SERVER_INSTANCE.get(le.getMessage())); 1116 return le.getResultCode(); 1117 } 1118 1119 1120 // If an LDIF file was provided, then use it to populate the server. 1121 if (ldifFileArgument.isPresent()) 1122 { 1123 final File ldifFile = ldifFileArgument.getValue(); 1124 try 1125 { 1126 final int numEntries = directoryServer.importFromLDIF(true, 1127 ldifFile.getAbsolutePath()); 1128 wrapOut(0, WRAP_COLUMN, 1129 INFO_MEM_DS_TOOL_ADDED_ENTRIES_FROM_LDIF.get(numEntries, 1130 ldifFile.getAbsolutePath())); 1131 } 1132 catch (final LDAPException le) 1133 { 1134 Debug.debugException(le); 1135 wrapErr(0, WRAP_COLUMN, 1136 ERR_MEM_DS_TOOL_ERROR_POPULATING_SERVER_INSTANCE.get( 1137 ldifFile.getAbsolutePath(), le.getMessage())); 1138 return le.getResultCode(); 1139 } 1140 } 1141 1142 1143 // Start the server. 1144 try 1145 { 1146 if (! dontStartArgument.isPresent()) 1147 { 1148 directoryServer.startListening(); 1149 wrapOut(0, WRAP_COLUMN, 1150 INFO_MEM_DS_TOOL_LISTENING.get(directoryServer.getListenPort())); 1151 } 1152 } 1153 catch (final Exception e) 1154 { 1155 Debug.debugException(e); 1156 wrapErr(0, WRAP_COLUMN, 1157 ERR_MEM_DS_TOOL_ERROR_STARTING_SERVER.get( 1158 StaticUtils.getExceptionMessage(e))); 1159 return ResultCode.LOCAL_ERROR; 1160 } 1161 1162 return ResultCode.SUCCESS; 1163 } 1164 1165 1166 1167 /** 1168 * Creates a server configuration based on information provided with 1169 * command line arguments. 1170 * 1171 * @return The configuration that was created. 1172 * 1173 * @throws LDAPException If a problem is encountered while creating the 1174 * configuration. 1175 */ 1176 @NotNull() 1177 private InMemoryDirectoryServerConfig getConfig() 1178 throws LDAPException 1179 { 1180 final List<DN> dnList = baseDNArgument.getValues(); 1181 final DN[] baseDNs = new DN[dnList.size()]; 1182 dnList.toArray(baseDNs); 1183 1184 final InMemoryDirectoryServerConfig serverConfig = 1185 new InMemoryDirectoryServerConfig(baseDNs); 1186 1187 1188 // If a listen port was specified, then update the configuration to use it. 1189 int listenPort = 0; 1190 if (portArgument.isPresent()) 1191 { 1192 listenPort = portArgument.getValue(); 1193 } 1194 1195 1196 // If schema should be used, then get it. 1197 if (useDefaultSchemaArgument.isPresent()) 1198 { 1199 serverConfig.setSchema(Schema.getDefaultStandardSchema()); 1200 } 1201 else if (useSchemaFileArgument.isPresent()) 1202 { 1203 final Map<String,File> schemaFiles = new TreeMap<>(); 1204 for (final File f : useSchemaFileArgument.getValues()) 1205 { 1206 if (f.exists()) 1207 { 1208 if (f.isFile()) 1209 { 1210 schemaFiles.put(f.getName(), f); 1211 } 1212 else 1213 { 1214 for (final File subFile : f.listFiles()) 1215 { 1216 if (subFile.isFile()) 1217 { 1218 schemaFiles.put(subFile.getName(), subFile); 1219 } 1220 } 1221 } 1222 } 1223 else 1224 { 1225 throw new LDAPException(ResultCode.PARAM_ERROR, 1226 ERR_MEM_DS_TOOL_NO_SUCH_SCHEMA_FILE.get(f.getAbsolutePath())); 1227 } 1228 } 1229 1230 if (! doNotValidateSchemaDefinitionsArgument.isPresent()) 1231 { 1232 Schema schema = null; 1233 final List<String> errorMessages = new ArrayList<>(); 1234 final SchemaValidator schemaValidator = new SchemaValidator(); 1235 for (final File schemaFile : schemaFiles.values()) 1236 { 1237 schema = schemaValidator.validateSchema(schemaFile, schema, 1238 errorMessages); 1239 } 1240 1241 if (! errorMessages.isEmpty()) 1242 { 1243 wrapErr(0, WRAP_COLUMN, 1244 WARN_MEM_DS_TOOL_SCHEMA_ISSUES_IDENTIFIED.get()); 1245 for (final String message : errorMessages) 1246 { 1247 err(); 1248 final List<String> wrappedLines = StaticUtils.wrapLine(message, 1249 (WRAP_COLUMN - 2)); 1250 final Iterator<String> iterator = wrappedLines.iterator(); 1251 err("* " + iterator.next()); 1252 while (iterator.hasNext()) 1253 { 1254 err(" " + iterator.next()); 1255 } 1256 } 1257 err(); 1258 wrapErr(0, WRAP_COLUMN, 1259 WARN_MEM_DS_TOOL_WILL_CONTINUE_WITH_SCHEMA.get( 1260 doNotValidateSchemaDefinitionsArgument. 1261 getIdentifierString())); 1262 err(); 1263 } 1264 } 1265 1266 try 1267 { 1268 serverConfig.setSchema(Schema.getSchema( 1269 new ArrayList<File>(schemaFiles.values()))); 1270 } 1271 catch (final Exception e) 1272 { 1273 Debug.debugException(e); 1274 1275 final StringBuilder fileList = new StringBuilder(); 1276 final Iterator<File> fileIterator = schemaFiles.values().iterator(); 1277 while (fileIterator.hasNext()) 1278 { 1279 fileList.append(fileIterator.next().getAbsolutePath()); 1280 if (fileIterator.hasNext()) 1281 { 1282 fileList.append(", "); 1283 } 1284 } 1285 1286 throw new LDAPException(ResultCode.LOCAL_ERROR, 1287 ERR_MEM_DS_TOOL_ERROR_READING_SCHEMA.get( 1288 fileList, StaticUtils.getExceptionMessage(e)), 1289 e); 1290 } 1291 } 1292 else 1293 { 1294 serverConfig.setSchema(null); 1295 } 1296 1297 1298 // If an additional bind DN and password are provided, then include them in 1299 // the configuration. 1300 if (additionalBindDNArgument.isPresent()) 1301 { 1302 serverConfig.addAdditionalBindCredentials( 1303 additionalBindDNArgument.getValue().toString(), 1304 additionalBindPasswordArgument.getValue()); 1305 } 1306 1307 1308 // If a maximum number of changelog entries was specified, then update the 1309 // configuration with that. 1310 if (maxChangeLogEntriesArgument.isPresent()) 1311 { 1312 serverConfig.setMaxChangeLogEntries( 1313 maxChangeLogEntriesArgument.getValue()); 1314 } 1315 1316 1317 // If a maximum number of concurrent connections was specified, then update 1318 // the configuration with that. 1319 if (maxConcurrentConnectionsArgument.isPresent()) 1320 { 1321 serverConfig.setMaxConnections( 1322 maxConcurrentConnectionsArgument.getValue()); 1323 } 1324 1325 1326 // If a size limit was specified, then update the configuration with that. 1327 if (sizeLimitArgument.isPresent()) 1328 { 1329 serverConfig.setMaxSizeLimit(sizeLimitArgument.getValue()); 1330 } 1331 1332 1333 // If the password argument was specified, then set the password arguments. 1334 if (passwordAttributeArgument.isPresent()) 1335 { 1336 serverConfig.setPasswordAttributes(passwordAttributeArgument.getValues()); 1337 } 1338 1339 1340 // Configure password encodings for the server. 1341 final LinkedHashMap<String,InMemoryPasswordEncoder> passwordEncoders = 1342 new LinkedHashMap<>(10); 1343 addUnsaltedEncoder("MD5", "MD5", passwordEncoders); 1344 addUnsaltedEncoder("SHA", "SHA-1", passwordEncoders); 1345 addUnsaltedEncoder("SHA1", "SHA-1", passwordEncoders); 1346 addUnsaltedEncoder("SHA-1", "SHA-1", passwordEncoders); 1347 addUnsaltedEncoder("SHA256", "SHA-256", passwordEncoders); 1348 addUnsaltedEncoder("SHA-256", "SHA-256", passwordEncoders); 1349 addUnsaltedEncoder("SHA384", "SHA-384", passwordEncoders); 1350 addUnsaltedEncoder("SHA-384", "SHA-384", passwordEncoders); 1351 addUnsaltedEncoder("SHA512", "SHA-512", passwordEncoders); 1352 addUnsaltedEncoder("SHA-512", "SHA-512", passwordEncoders); 1353 addSaltedEncoder("SMD5", "MD5", passwordEncoders); 1354 addSaltedEncoder("SSHA", "SHA-1", passwordEncoders); 1355 addSaltedEncoder("SSHA1", "SHA-1", passwordEncoders); 1356 addSaltedEncoder("SSHA-1", "SHA-1", passwordEncoders); 1357 addSaltedEncoder("SSHA256", "SHA-256", passwordEncoders); 1358 addSaltedEncoder("SSHA-256", "SHA-256", passwordEncoders); 1359 addSaltedEncoder("SSHA384", "SHA-384", passwordEncoders); 1360 addSaltedEncoder("SSHA-384", "SHA-384", passwordEncoders); 1361 addSaltedEncoder("SSHA512", "SHA-512", passwordEncoders); 1362 addSaltedEncoder("SSHA-512", "SHA-512", passwordEncoders); 1363 addClearEncoder("CLEAR", null, passwordEncoders); 1364 addClearEncoder("BASE64", 1365 Base64PasswordEncoderOutputFormatter.getInstance(), passwordEncoders); 1366 addClearEncoder("HEX", 1367 HexPasswordEncoderOutputFormatter.getLowercaseInstance(), 1368 passwordEncoders); 1369 1370 final InMemoryPasswordEncoder primaryEncoder; 1371 if (defaultPasswordEncodingArgument.isPresent()) 1372 { 1373 primaryEncoder = passwordEncoders.remove( 1374 StaticUtils.toLowerCase(defaultPasswordEncodingArgument.getValue())); 1375 if (primaryEncoder == null) 1376 { 1377 throw new LDAPException(ResultCode.PARAM_ERROR, 1378 ERR_MEM_DS_TOOL_UNAVAILABLE_PW_ENCODING.get( 1379 defaultPasswordEncodingArgument.getValue(), 1380 String.valueOf(passwordEncoders.keySet()))); 1381 } 1382 } 1383 else 1384 { 1385 primaryEncoder = null; 1386 } 1387 1388 serverConfig.setPasswordEncoders(primaryEncoder, 1389 passwordEncoders.values()); 1390 1391 1392 // Configure the allowed operation types. 1393 if (allowedOperationTypeArgument.isPresent()) 1394 { 1395 final EnumSet<OperationType> operationTypes = 1396 EnumSet.noneOf(OperationType.class); 1397 for (final String operationTypeName : 1398 allowedOperationTypeArgument.getValues()) 1399 { 1400 final OperationType name = OperationType.forName(operationTypeName); 1401 if (name == null) 1402 { 1403 throw new LDAPException(ResultCode.PARAM_ERROR, 1404 ERR_MEM_DS_TOOL_UNSUPPORTED_ALLOWED_OP_TYPE.get(name)); 1405 } 1406 else 1407 { 1408 switch (name) 1409 { 1410 case ADD: 1411 case BIND: 1412 case COMPARE: 1413 case DELETE: 1414 case EXTENDED: 1415 case MODIFY: 1416 case MODIFY_DN: 1417 case SEARCH: 1418 operationTypes.add(name); 1419 break; 1420 case ABANDON: 1421 case UNBIND: 1422 default: 1423 throw new LDAPException(ResultCode.PARAM_ERROR, 1424 ERR_MEM_DS_TOOL_UNSUPPORTED_ALLOWED_OP_TYPE.get(name)); 1425 } 1426 } 1427 } 1428 1429 serverConfig.setAllowedOperationTypes(operationTypes); 1430 } 1431 1432 1433 // Configure the authentication required operation types. 1434 if (authenticationRequiredOperationTypeArgument.isPresent()) 1435 { 1436 final EnumSet<OperationType> operationTypes = 1437 EnumSet.noneOf(OperationType.class); 1438 for (final String operationTypeName : 1439 authenticationRequiredOperationTypeArgument.getValues()) 1440 { 1441 final OperationType name = OperationType.forName(operationTypeName); 1442 if (name == null) 1443 { 1444 throw new LDAPException(ResultCode.PARAM_ERROR, 1445 ERR_MEM_DS_TOOL_UNSUPPORTED_AUTH_REQUIRED_OP_TYPE.get(name)); 1446 } 1447 else 1448 { 1449 switch (name) 1450 { 1451 case ADD: 1452 case COMPARE: 1453 case DELETE: 1454 case EXTENDED: 1455 case MODIFY: 1456 case MODIFY_DN: 1457 case SEARCH: 1458 operationTypes.add(name); 1459 break; 1460 case ABANDON: 1461 case UNBIND: 1462 default: 1463 throw new LDAPException(ResultCode.PARAM_ERROR, 1464 ERR_MEM_DS_TOOL_UNSUPPORTED_AUTH_REQUIRED_OP_TYPE.get(name)); 1465 } 1466 } 1467 } 1468 1469 serverConfig.setAuthenticationRequiredOperationTypes(operationTypes); 1470 } 1471 1472 1473 // If an access log file was specified, then create the appropriate log 1474 // handler. 1475 if (accessLogToStandardOutArgument.isPresent()) 1476 { 1477 final StreamHandler handler = new StreamHandler(System.out, 1478 new MinimalLogFormatter(null, false, false, true)); 1479 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1480 serverConfig.setAccessLogHandler(handler); 1481 } 1482 else if (accessLogFileArgument.isPresent()) 1483 { 1484 final File logFile = accessLogFileArgument.getValue(); 1485 try 1486 { 1487 final FileHandler handler = 1488 new FileHandler(logFile.getAbsolutePath(), true); 1489 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1490 handler.setFormatter(new MinimalLogFormatter(null, false, false, 1491 true)); 1492 serverConfig.setAccessLogHandler(handler); 1493 } 1494 catch (final Exception e) 1495 { 1496 Debug.debugException(e); 1497 throw new LDAPException(ResultCode.LOCAL_ERROR, 1498 ERR_MEM_DS_TOOL_ERROR_CREATING_LOG_HANDLER.get( 1499 logFile.getAbsolutePath(), 1500 StaticUtils.getExceptionMessage(e)), 1501 e); 1502 } 1503 } 1504 1505 1506 // If a JSON-formatted access log file was specified, then create the 1507 // appropriate log handler. 1508 if (jsonAccessLogToStandardOutArgument.isPresent()) 1509 { 1510 final StreamHandler handler = new StreamHandler(System.out, 1511 new MinimalLogFormatter(null, false, false, true)); 1512 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1513 serverConfig.setJSONAccessLogHandler(handler); 1514 } 1515 else if (jsonAccessLogFileArgument.isPresent()) 1516 { 1517 final File logFile = jsonAccessLogFileArgument.getValue(); 1518 try 1519 { 1520 final FileHandler handler = 1521 new FileHandler(logFile.getAbsolutePath(), true); 1522 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1523 handler.setFormatter(new MinimalLogFormatter(null, false, false, 1524 true)); 1525 serverConfig.setJSONAccessLogHandler(handler); 1526 } 1527 catch (final Exception e) 1528 { 1529 Debug.debugException(e); 1530 throw new LDAPException(ResultCode.LOCAL_ERROR, 1531 ERR_MEM_DS_TOOL_ERROR_CREATING_LOG_HANDLER.get( 1532 logFile.getAbsolutePath(), 1533 StaticUtils.getExceptionMessage(e)), 1534 e); 1535 } 1536 } 1537 1538 1539 // If an LDAP debug log file was specified, then create the appropriate log 1540 // handler. 1541 if (ldapDebugLogToStandardOutArgument.isPresent()) 1542 { 1543 final StreamHandler handler = new StreamHandler(System.out, 1544 new MinimalLogFormatter(null, false, false, true)); 1545 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1546 serverConfig.setLDAPDebugLogHandler(handler); 1547 } 1548 else if (ldapDebugLogFileArgument.isPresent()) 1549 { 1550 final File logFile = ldapDebugLogFileArgument.getValue(); 1551 try 1552 { 1553 final FileHandler handler = 1554 new FileHandler(logFile.getAbsolutePath(), true); 1555 StaticUtils.setLogHandlerLevel(handler, Level.INFO); 1556 handler.setFormatter(new MinimalLogFormatter(null, false, false, 1557 true)); 1558 serverConfig.setLDAPDebugLogHandler(handler); 1559 } 1560 catch (final Exception e) 1561 { 1562 Debug.debugException(e); 1563 throw new LDAPException(ResultCode.LOCAL_ERROR, 1564 ERR_MEM_DS_TOOL_ERROR_CREATING_LOG_HANDLER.get( 1565 logFile.getAbsolutePath(), 1566 StaticUtils.getExceptionMessage(e)), 1567 e); 1568 } 1569 } 1570 1571 1572 // If a code log file was specified, then update the configuration 1573 // accordingly. 1574 if (codeLogFile.isPresent()) 1575 { 1576 serverConfig.setCodeLogDetails(codeLogFile.getValue().getAbsolutePath(), 1577 true); 1578 } 1579 1580 1581 // If SSL is to be used, then create the corresponding socket factories. 1582 if (useSSLArgument.isPresent() || useStartTLSArgument.isPresent()) 1583 { 1584 final File keyStorePath; 1585 final char[] keyStorePIN; 1586 final String keyStoreType; 1587 if (keyStorePathArgument.isPresent()) 1588 { 1589 keyStorePath = keyStorePathArgument.getValue(); 1590 keyStorePIN = keyStorePasswordArgument.getValue().toCharArray(); 1591 keyStoreType = keyStoreTypeArgument.getValue(); 1592 } 1593 else 1594 { 1595 try 1596 { 1597 keyStoreType = CryptoHelper.KEY_STORE_TYPE_JKS; 1598 final ObjectPair<File,char[]> keyStoreInfo = 1599 SelfSignedCertificateGenerator. 1600 generateTemporarySelfSignedCertificate( 1601 getToolName(), keyStoreType); 1602 keyStorePath = keyStoreInfo.getFirst(); 1603 keyStorePIN = keyStoreInfo.getSecond(); 1604 } 1605 catch (final CertException e) 1606 { 1607 Debug.debugException(e); 1608 throw new LDAPException(ResultCode.LOCAL_ERROR, e.getMessage(), e); 1609 } 1610 } 1611 1612 1613 try 1614 { 1615 final KeyManager keyManager = new KeyStoreKeyManager(keyStorePath, 1616 keyStorePIN, keyStoreType, null, true); 1617 1618 final TrustManager trustManager; 1619 if (trustStorePathArgument.isPresent()) 1620 { 1621 final char[] password; 1622 if (trustStorePasswordArgument.isPresent()) 1623 { 1624 password = trustStorePasswordArgument.getValue().toCharArray(); 1625 } 1626 else 1627 { 1628 password = null; 1629 } 1630 1631 trustManager = new TrustStoreTrustManager( 1632 trustStorePathArgument.getValue(), password, 1633 trustStoreTypeArgument.getValue(), true); 1634 } 1635 else 1636 { 1637 trustManager = new TrustAllTrustManager(); 1638 } 1639 1640 final SSLUtil serverSSLUtil = new SSLUtil(keyManager, trustManager); 1641 1642 final boolean requestCertificate; 1643 final boolean requireCertificate; 1644 final String clientAuthPolicy = sslClientAuthPolicy.getValue(); 1645 if (clientAuthPolicy.equalsIgnoreCase( 1646 SSL_CLIENT_AUTH_POLICY_OPTIONAL)) 1647 { 1648 requestCertificate = true; 1649 requireCertificate = false; 1650 } 1651 else if (clientAuthPolicy.equalsIgnoreCase( 1652 SSL_CLIENT_AUTH_POLICY_REQUIRED)) 1653 { 1654 requestCertificate = true; 1655 requireCertificate = true; 1656 } 1657 else 1658 { 1659 requestCertificate = false; 1660 requireCertificate = false; 1661 } 1662 1663 if (useSSLArgument.isPresent()) 1664 { 1665 final SSLUtil clientSSLUtil = new SSLUtil(new TrustAllTrustManager()); 1666 serverConfig.setListenerConfigs( 1667 InMemoryListenerConfig.createLDAPSConfig("LDAPS", null, 1668 listenPort, serverSSLUtil.createSSLServerSocketFactory(), 1669 clientSSLUtil.createSSLSocketFactory(), 1670 requestCertificate, requireCertificate)); 1671 } 1672 else 1673 { 1674 serverConfig.setListenerConfigs( 1675 InMemoryListenerConfig.createLDAPConfig("LDAP+StartTLS", null, 1676 listenPort, serverSSLUtil.createSSLSocketFactory(), 1677 requestCertificate, requireCertificate)); 1678 } 1679 } 1680 catch (final Exception e) 1681 { 1682 Debug.debugException(e); 1683 throw new LDAPException(ResultCode.LOCAL_ERROR, 1684 ERR_MEM_DS_TOOL_ERROR_INITIALIZING_SSL.get( 1685 StaticUtils.getExceptionMessage(e)), 1686 e); 1687 } 1688 } 1689 else 1690 { 1691 serverConfig.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig( 1692 "LDAP", listenPort)); 1693 } 1694 1695 1696 // If vendor name and/or vendor version values were provided, then configure 1697 // them for use. 1698 if (vendorNameArgument.isPresent()) 1699 { 1700 serverConfig.setVendorName(vendorNameArgument.getValue()); 1701 } 1702 1703 if (vendorVersionArgument.isPresent()) 1704 { 1705 serverConfig.setVendorVersion(vendorVersionArgument.getValue()); 1706 } 1707 1708 1709 // If equality indexing is to be performed, then configure it. 1710 if (equalityIndexArgument.isPresent()) 1711 { 1712 serverConfig.setEqualityIndexAttributes( 1713 equalityIndexArgument.getValues()); 1714 } 1715 1716 1717 // Update the configuration to indicate whether to generate operational 1718 // attributes. 1719 serverConfig.setGenerateOperationalAttributes( 1720 ! doNotGenerateOperationalAttributesArgument.isPresent()); 1721 1722 1723 return serverConfig; 1724 } 1725 1726 1727 1728 /** 1729 * Updates the map with an unsalted password encoder with the provided 1730 * information. 1731 * 1732 * @param schemeName The name to use to identify the scheme, without 1733 * the curly braces. 1734 * @param digestAlgorithm The name of the message digest algorithm to use 1735 * for the password encoder. 1736 * @param encoderMap The map to which the encoder will bea added. 1737 */ 1738 private static void addUnsaltedEncoder(@NotNull final String schemeName, 1739 @NotNull final String digestAlgorithm, 1740 @NotNull final Map<String,InMemoryPasswordEncoder> encoderMap) 1741 { 1742 try 1743 { 1744 final UnsaltedMessageDigestInMemoryPasswordEncoder encoder = 1745 new UnsaltedMessageDigestInMemoryPasswordEncoder( 1746 '{' + schemeName + '}', 1747 Base64PasswordEncoderOutputFormatter.getInstance(), 1748 CryptoHelper.getMessageDigest(digestAlgorithm)); 1749 encoderMap.put(StaticUtils.toLowerCase(schemeName), encoder); 1750 } 1751 catch (final Exception e) 1752 { 1753 Debug.debugException(e); 1754 } 1755 } 1756 1757 1758 1759 /** 1760 * Updates the map with a salted password encoder with the provided 1761 * information. 1762 * 1763 * @param schemeName The name to use to identify the scheme, without 1764 * the curly braces. 1765 * @param digestAlgorithm The name of the message digest algorithm to use 1766 * for the password encoder. 1767 * @param encoderMap The map to which the encoder will bea added. 1768 */ 1769 private static void addSaltedEncoder(@NotNull final String schemeName, 1770 @NotNull final String digestAlgorithm, 1771 @NotNull final Map<String,InMemoryPasswordEncoder> encoderMap) 1772 { 1773 try 1774 { 1775 final SaltedMessageDigestInMemoryPasswordEncoder encoder = 1776 new SaltedMessageDigestInMemoryPasswordEncoder( 1777 '{' + schemeName + '}', 1778 Base64PasswordEncoderOutputFormatter.getInstance(), 1779 CryptoHelper.getMessageDigest(digestAlgorithm), 8, true, true); 1780 encoderMap.put(StaticUtils.toLowerCase(schemeName), encoder); 1781 } 1782 catch (final Exception e) 1783 { 1784 Debug.debugException(e); 1785 } 1786 } 1787 1788 1789 1790 /** 1791 * Updates the map with a clear-text password encoder with the provided 1792 * information. 1793 * 1794 * @param schemeName The name to use to identify the scheme, without 1795 * the curly braces. 1796 * @param outputFormatter The output formatter to use. It may be 1797 * {@code null} if the output should remain in the 1798 * clear. 1799 * @param encoderMap The map to which the encoder will bea added. 1800 */ 1801 private static void addClearEncoder(@NotNull final String schemeName, 1802 @Nullable final PasswordEncoderOutputFormatter outputFormatter, 1803 @NotNull final Map<String,InMemoryPasswordEncoder> encoderMap) 1804 { 1805 final ClearInMemoryPasswordEncoder encoder = 1806 new ClearInMemoryPasswordEncoder('{' + schemeName + '}', 1807 outputFormatter); 1808 encoderMap.put(StaticUtils.toLowerCase(schemeName), encoder); 1809 } 1810 1811 1812 1813 /** 1814 * {@inheritDoc} 1815 */ 1816 @Override() 1817 @NotNull() 1818 public LinkedHashMap<String[],String> getExampleUsages() 1819 { 1820 final LinkedHashMap<String[],String> exampleUsages = 1821 new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); 1822 1823 final String[] example1Args = 1824 { 1825 "--baseDN", "dc=example,dc=com" 1826 }; 1827 exampleUsages.put(example1Args, INFO_MEM_DS_TOOL_EXAMPLE_1.get()); 1828 1829 final String[] example2Args = 1830 { 1831 "--baseDN", "dc=example,dc=com", 1832 "--port", "1389", 1833 "--ldifFile", "test.ldif", 1834 "--accessLogFile", "access.log", 1835 "--useDefaultSchema" 1836 }; 1837 exampleUsages.put(example2Args, INFO_MEM_DS_TOOL_EXAMPLE_2.get()); 1838 1839 return exampleUsages; 1840 } 1841 1842 1843 1844 /** 1845 * Retrieves the in-memory directory server instance that has been created by 1846 * this tool. It will only be valid after the {@link #doToolProcessing()} 1847 * method has been called. 1848 * 1849 * @return The in-memory directory server instance that has been created by 1850 * this tool, or {@code null} if the directory server instance has 1851 * not been successfully created. 1852 */ 1853 @Nullable() 1854 public InMemoryDirectoryServer getDirectoryServer() 1855 { 1856 return directoryServer; 1857 } 1858 1859 1860 1861 /** 1862 * {@inheritDoc} 1863 */ 1864 @Override() 1865 public void connectionCreationFailure(@Nullable final Socket socket, 1866 @NotNull final Throwable cause) 1867 { 1868 wrapErr(0, WRAP_COLUMN, 1869 ERR_MEM_DS_TOOL_ERROR_ACCEPTING_CONNECTION.get( 1870 StaticUtils.getExceptionMessage(cause))); 1871 } 1872 1873 1874 1875 /** 1876 * {@inheritDoc} 1877 */ 1878 @Override() 1879 public void connectionTerminated( 1880 @NotNull final LDAPListenerClientConnection connection, 1881 @NotNull final LDAPException cause) 1882 { 1883 wrapErr(0, WRAP_COLUMN, 1884 ERR_MEM_DS_TOOL_CONNECTION_TERMINATED_BY_EXCEPTION.get( 1885 StaticUtils.getExceptionMessage(cause))); 1886 } 1887}