001/* 002 * Copyright 2015-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2015-2020 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) 2015-2020 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.util.json; 037 038 039 040import java.io.BufferedReader; 041import java.io.File; 042import java.io.FileInputStream; 043import java.io.FileReader; 044import java.io.InputStream; 045import java.io.IOException; 046import java.util.Arrays; 047import java.util.HashSet; 048 049import com.unboundid.ldap.sdk.BindRequest; 050import com.unboundid.ldap.sdk.LDAPConnection; 051import com.unboundid.ldap.sdk.LDAPConnectionPool; 052import com.unboundid.ldap.sdk.LDAPException; 053import com.unboundid.ldap.sdk.ResultCode; 054import com.unboundid.ldap.sdk.ServerSet; 055import com.unboundid.util.ByteStringBuffer; 056import com.unboundid.util.Debug; 057import com.unboundid.util.NotMutable; 058import com.unboundid.util.StaticUtils; 059import com.unboundid.util.ThreadSafety; 060import com.unboundid.util.ThreadSafetyLevel; 061 062import static com.unboundid.util.json.JSONMessages.*; 063 064 065 066/** 067 * This class provides a utility that may be used to obtain information that may 068 * be used to create LDAP connections to one or more servers from a definition 069 * contained in a JSON object. This makes it easier to create applications that 070 * provide the information necessary for creating LDAP connections and 071 * connection pools in a JSON-formatted configuration file. 072 * <BR><BR> 073 * The JSON-based specification is organized into five sections: 074 * <OL> 075 * <LI> 076 * A "server-details" section that provides information about the directory 077 * server(s) to access. The specification supports accessing a single 078 * server, as well as a number of schemes for establishing connections 079 * across multiple servers. 080 * </LI> 081 * <LI> 082 * A "communication-security" section that provides information that may be 083 * used to secure communication using SSL or StartTLS. 084 * </LI> 085 * <LI> 086 * A "connection-options" section that can be used customize a number of 087 * connection-related options, like connect and response timeouts, whether 088 * to follow referrals, whether to retrieve schema from the backend server 089 * for client-side use, and whether to use synchronous mode for more 090 * efficient communication if connections will not be used in an 091 * asynchronous manner. 092 * </LI> 093 * <LI> 094 * An "authentication-details" section that provides information for 095 * authenticating connections using a number of mechanisms. 096 * </LI> 097 * <LI> 098 * A "connection-pool-options" section that provides information to use to 099 * customize the behavior to use for connection pools created from this 100 * specification. 101 * </LI> 102 * </OL> 103 * Each of these sections will be described in more detail below. 104 * <BR><BR> 105 * <H2>The "server-details" Section</H2> 106 * The JSON object that comprises the LDAP connection details specification must 107 * have a top-level "server-details" field whose value is a JSON object that 108 * provides information about the server(s) to which connections may be 109 * established. The value of the "server-details" field must itself be a JSON 110 * object, and that object must have exactly one field, which depends on the 111 * mechanism that the LDAP SDK should use to select the target directory 112 * servers. 113 * <BR><BR> 114 * <B>The "server-details" Section for Connecting to a Single Server</B> 115 * <BR> 116 * When establishing a connection to a single server, the "server-details" 117 * value should be a JSON object that contains a "single-server" field whose 118 * value is a JSON object with "address" and "port" fields. For example, the 119 * following is a valid specification that may be used to establish connections 120 * to the server at ldap.example.com on port 389: 121 * <PRE> 122 * { 123 * "server-details": 124 * { 125 * "single-server": 126 * { 127 * "address":"ldap.example.com", 128 * "port":389 129 * } 130 * } 131 * } 132 * </PRE> 133 * <BR> 134 * <B>The "server-details" Section for Selecting from a Set of Servers in a 135 * Round-Robin Manner</B> 136 * <BR> 137 * If you have a set of servers that you want to connect to in a round-robin 138 * manner (in which the LDAP SDK will maintain a circular list of servers and 139 * each new connection will go to the next server in the list), the 140 * "server-details" value should be a JSON object that contains a 141 * "round-robin-set" field whose value is a JSON object that contains a "server" 142 * field with an array of JSON objects, each of which contains "address" and 143 * "port" fields for a target server. For example, the following is a valid 144 * specification that may be used to establish connections across the servers 145 * ldap1.example.com, ldap2.example.com, and ldap3.example.com, all on port 389: 146 * <PRE> 147 * { 148 * "server-details": 149 * { 150 * "round-robin-set": 151 * { 152 * "servers": 153 * [ 154 * { 155 * "address":"ldap1.example.com", 156 * "port":389 157 * }, 158 * { 159 * "address":"ldap2.example.com", 160 * "port":389 161 * }, 162 * { 163 * "address":"ldap2.example.com", 164 * "port":389 165 * } 166 * ] 167 * } 168 * } 169 * } 170 * </PRE> 171 * <BR> 172 * <B>The "server-details" Section for Selecting from a Set of Servers in a 173 * Fewest Connections Manner</B> 174 * <BR> 175 * If you have a set of servers that you want to connect to in a manner that 176 * selects the server with the fewest established connections (at least 177 * connections created from this specification), the "server-details" value 178 * should be a JSON object that contains a "fewest-connections-set" field whose 179 * value is a JSON object that contains a "server" field with an array of JSON 180 * objects, each of which contains "address" and "port" fields for a target 181 * server. For example, the following is a valid specification that may be used 182 * to establish connections across the servers ldap1.example.com, 183 * ldap2.example.com, and ldap3.example.com, all on port 389: 184 * <PRE> 185 * { 186 * "server-details": 187 * { 188 * "fewest-connections-set": 189 * { 190 * "servers": 191 * [ 192 * { 193 * "address":"ldap1.example.com", 194 * "port":389 195 * }, 196 * { 197 * "address":"ldap2.example.com", 198 * "port":389 199 * }, 200 * { 201 * "address":"ldap2.example.com", 202 * "port":389 203 * } 204 * ] 205 * } 206 * } 207 * } 208 * </PRE> 209 * <BR> 210 * <B>The "server-details" Section for Selecting from a Set of Servers in a 211 * Fastest Connect Manner</B> 212 * <BR> 213 * If you have a set of servers that you want to connect to in a manner that 214 * attempts to minimize the time required to establish new connections (by 215 * simultaneously attempting to create connections to every server in the set 216 * and taking the first connection to be established), the "server-details" 217 * value should be a JSON object that contains a "fastest-connect-set" field 218 * whose value is a JSON object that contains a "server" field with an array of 219 * JSON objects, each of which contains "address" and "port" fields for a target 220 * server. For example, the following is a valid specification that may be used 221 * to establish connections across the servers ldap1.example.com, 222 * ldap2.example.com, and ldap3.example.com, all on port 389: 223 * <PRE> 224 * { 225 * "server-details": 226 * { 227 * "fastest-connect-set": 228 * { 229 * "servers": 230 * [ 231 * { 232 * "address":"ldap1.example.com", 233 * "port":389 234 * }, 235 * { 236 * "address":"ldap2.example.com", 237 * "port":389 238 * }, 239 * { 240 * "address":"ldap2.example.com", 241 * "port":389 242 * } 243 * ] 244 * } 245 * } 246 * } 247 * </PRE> 248 * <BR> 249 * <B>The "server-details" Section for Selecting from a Set of Servers in a 250 * Failover Manner</B> 251 * <BR> 252 * If you have a set of servers that you want to connect to in a manner that 253 * attempts to consistently establish connections to the same server (as long as 254 * it is available, and use a consistent failover order if the preferred server 255 * isn't available), the "server-details" value should be a JSON object that 256 * contains a "failover-set" field whose value is a JSON object that contains a 257 * "failover-order" field that provides a list of the details to use in order 258 * to establish the connections. For example, the following is a valid 259 * specification that may be used to always try to establish connections to 260 * ldap1.example.com:389, then try ldap2.example.com:389, and then try 261 * ldap3.example.com:389: 262 * <PRE> 263 * { 264 * "server-details": 265 * { 266 * "failover-set": 267 * { 268 * "failover-order": 269 * [ 270 * { 271 * "single-server": 272 * { 273 * "address":"ldap1.example.com", 274 * "port":389 275 * } 276 * }, 277 * { 278 * "single-server": 279 * { 280 * "address":"ldap2.example.com", 281 * "port":389 282 * } 283 * }, 284 * { 285 * "single-server": 286 * { 287 * "address":"ldap2.example.com", 288 * "port":389 289 * } 290 * } 291 * ] 292 * } 293 * } 294 * } 295 * </PRE> 296 * The failover set actually has the ability to perform failover across any kind 297 * of set. This is a powerful capability that can be useful to define a 298 * hierarchy of sets, for example for sets referring to servers in different 299 * data centers (e.g., to prefer connecting to one of the servers in the local 300 * data center over servers in a remote data center). For example, the 301 * following is a valid specification that may be used to connect to the server 302 * with the fewest connections in the east data center, but if no east servers 303 * are available then it will fail over to select the server with the fewest 304 * connections in the west data center: 305 * <PRE> 306 * { 307 * "server-details": 308 * { 309 * "failover-set": 310 * { 311 * "failover-order": 312 * [ 313 * { 314 * "fewest-connections-set": 315 * { 316 * "servers": 317 * [ 318 * { 319 * "address":"ldap1.east.example.com", 320 * "port":389 321 * }, 322 * { 323 * "address":"ldap2.east.example.com", 324 * "port":389 325 * } 326 * ] 327 * } 328 * }, 329 * { 330 * "fewest-connections-set": 331 * { 332 * "servers": 333 * [ 334 * { 335 * "address":"ldap1.west.example.com", 336 * "port":389 337 * }, 338 * { 339 * "address":"ldap2.west.example.com", 340 * "port":389 341 * } 342 * ] 343 * } 344 * } 345 * ] 346 * } 347 * } 348 * } 349 * </PRE> 350 * For connections that are part of a connection pool, failover sets have the 351 * ability to assign a different maximum connection age to connections created 352 * to a non-preferred server. This can help allow failover connections to be 353 * migrated back to the preferred server more quickly once that server is 354 * available again. If you wish to specify an alternate maximum connection age 355 * for connections to a non-preferred server, you may include the 356 * "maximum-failover-connection-age-millis" field in the "failover-set" object. 357 * The value of this field should be a number that is greater than zero to 358 * specify the maximum age (in milliseconds) for those connections, or a value 359 * of zero to indicate that they should not be subject to a maximum age. If 360 * this field is not present, then these connections will be assigned the 361 * default maximum connection age configured for the pool. 362 * <BR><BR> 363 * <H2>The "communication-security" Section</H2> 364 * This section may be used to provide information about the type of security to 365 * use to protect communication with directory servers. If the specification 366 * includes information about multiple servers, then all servers will use the 367 * same type of security. 368 * <BR><BR> 369 * If present, the "communication-security" field should have a value that is a 370 * JSON object. This object must have a "security-type" field with one of the 371 * following values: 372 * <UL> 373 * <LI> 374 * "none" -- Indicates that no communication security should be used. The 375 * communication will not be encrypted. 376 * </LI> 377 * <LI> 378 * "SSL" -- Indicates that all communication should be encrypted with the 379 * SSL (secure sockets layer) protocol, or more likely its more secure 380 * successor TLS (transport-layer security) protocol. You can also specify 381 * a value of "TLS" to use this type of security. 382 * </LI> 383 * <LI> 384 * "StartTLS" -- Indicates that the connection will be initially established 385 * in a non-secure manner, but will be immediately secured with the StartTLS 386 * extended operation. 387 * </LI> 388 * </UL> 389 * If you do not wish to use any form of communication security, then the 390 * "security-type" field is the only one that should be present. For example, 391 * the following is a valid specification that will use unencrypted 392 * communication to the server ldap.example.com on port 389: 393 * <PRE> 394 * { 395 * "server-details": 396 * { 397 * "single-server": 398 * { 399 * "address":"ldap.example.com", 400 * "port":389 401 * } 402 * }, 403 * "communication-security": 404 * { 405 * "security-type":"none" 406 * } 407 * } 408 * </PRE> 409 * <BR> 410 * If you wish to secure the communication with either SSL or StartTLS, then 411 * there are a number of other options that may be specified using fields in the 412 * "communication-security" object. Those options fall into two basic 413 * categories: fields that provide information about how the client should 414 * determine whether to trust the certificate presented by the server, and 415 * fields that provide information about whether the client should present its 416 * own certificate to the server. The fields related to client trust include: 417 * <UL> 418 * <LI> 419 * "trust-all-certificates" -- Indicates whether the client should blindly 420 * trust any certificate that the server presents to it. Using blind trust 421 * is convenient for testing and troubleshooting purposes, but is not 422 * recommended for production use because it can leave the communication 423 * susceptible to man-in-the-middle attacks. If this field is present, then 424 * it should have a boolean value. If it is not present, a default value 425 * of {@code false} will be assumed. If it is present with a value of 426 * {@code true}, then the "use-jvm-default-trust-store", "trust-store-file", 427 * "trust-store-type", "trust-store-pin", and "trust-store-pin-file" fields 428 * should not be used. 429 * </LI> 430 * <LI> 431 * "use-jvm-default-trust-store" -- Indicates that certificates signed by an 432 * authority listed in the JVM's default set of trusted issuers should be 433 * trusted. If this field is present, it should have a boolean value. The 434 * JVM-default trust store may be used on its own or in conjunction with a 435 * trust store file. 436 * </LI> 437 * <LI> 438 * "trust-store-file" -- Specifies the path to a trust store file (in JKS 439 * or PKCS#12 format). If this is present, then the presented certificate 440 * will only be trusted if the trust store file contains information about 441 * all of the issuers in the certificate chain. 442 * </LI> 443 * <LI> 444 * "trust-store-type" -- Indicates the format for the trust store file. 445 * If this is present, then its value should be a string that is either 446 * "JKS" or "PKCS12". If it is not present, then a default trust store type 447 * of "JKS" will be assumed. 448 * </LI> 449 * <LI> 450 * "trust-store-pin" -- Specifies the PIN that should be used to access the 451 * contents of the trust store. If this field is present, then its value 452 * should be a string that is the clear-text PIN. If it is not present, 453 * then the PIN may be read from a file specified using the 454 * "trust-store-pin-file" field. If neither the "trust-store-pin" field nor 455 * the "trust-store-pin-file" field is present, then no PIN will be used 456 * when attempting to access the trust store (and in many cases, no trust 457 * store PIN will be required). 458 * </LI> 459 * <LI> 460 * "trust-store-pin-file" -- Specifies the path to a file that contains the 461 * PIN to use to access the contents of the trust store. If this field is 462 * present, then its value must be the path to a file containing a single 463 * line, which is the clear-text PIN. If it is not present, then the PIN 464 * may be obtained from the "trust-store-pin" field. If neither the 465 * "trust-store-pin" field nor the "trust-store-pin-file" field is present, 466 * then no PIN will be used when attempting to access the trust store (and 467 * in many cases, no trust store PIN will be required). 468 * </LI> 469 * <LI> 470 * "trust-expired-certificates" -- Indicates whether the client should 471 * trust certificates that are not yet valid or that have expired. If this 472 * field is present, then its value must be a boolean. If the value is 473 * {@code true}, then the certificate validity dates will not be taken into 474 * consideration when deciding whether to trust a certificate. If the value 475 * is {@code false}, then any certificate whose validity window does not 476 * include the current time will not be trusted (even if 477 * "trust-all-certificates" is {@code true}). If this field is not present, 478 * then a default of {@code false} will be assumed. 479 * </LI> 480 * <LI> 481 * "verify-address-in-certificate" -- Indicates whether the client should 482 * examine the information contained in the certificate to verify that the 483 * address the client used to connect to the server matches address 484 * information contained in the certificate (whether in the CN attribute of 485 * the certificate's subject, or in a subjectAltName extension of type 486 * dNSName, uniformResourceIdentifier, or iPAddress). If this field is 487 * present, then its value must be a boolean. If it is absent, then a 488 * default value of {@code false} will be assumed. 489 * </LI> 490 * </UL> 491 * If none of the above fields are provided, then the JVM's default trust 492 * mechanism will be used. This will generally only trust certificates signed 493 * by a well-known certification authority. 494 * <BR><BR> 495 * The fields related to presenting a client certificate include: 496 * <UL> 497 * <LI> 498 * "key-store-file" -- Specifies the path to a key store file (in JKS or 499 * PKCS#12 format) that contains the certificate that the client should 500 * present to the server. If this is present, then the value must be a 501 * string that is the path to the key store file. If it is not present, 502 * then no key store file will be used. 503 * </LI> 504 * <LI> 505 * "key-store-type" -- Specifies the type of key store that should be used. 506 * If this is present, then its value must be a string, and that string 507 * should be "JKS" or "PKCS12" (if a "key-store-file" value is present), or 508 * "PKCS11" (if the client certificate is contained in a security module 509 * accessible via the PKCS#11 API. If this field is not present but a 510 * "key-store-file" value is provided, then a default value of "JKS" will be 511 * assumed. 512 * </LI> 513 * <LI> 514 * "key-store-pin" -- Specifies the PIN that should be used to access the 515 * contents of the key store. If this field is present, then its value 516 * should be a string that is the clear-text PIN. If it is not present, 517 * then the PIN may be read from a file specified using the 518 * "key-store-pin-file" field. If neither the "key-store-pin" field nor the 519 * "key-store-pin-file" field is present, then no PIN will be used when 520 * attempting to access the key store (although key stores generally require 521 * a PIN in order to access private key information). 522 * </LI> 523 * <LI> 524 * "key-store-pin-file" -- Specifies the path to a file containing the PIN 525 * that should be used to access the contents of the key store. If this 526 * field is present, then its value should be the path to a file containing 527 * the clear-text PIN. If it is not present, then the PIN may be obtained 528 * from the "key-store-pin" field. If neither the "key-store-pin" field nor 529 * the "key-store-pin-file" field is present, then no PIN will be used when 530 * attempting to access the key store (although key stores generally require 531 * a PIN in order to access private key information). 532 * </LI> 533 * <LI> 534 * "client-certificate-alias" -- Specifies the alias (also known as the 535 * nickname) of the client certificate that should be presented to the 536 * directory server. If this field is present, then its value should be a 537 * string that is the alias for a valid certificate that exists in the 538 * key store. If this field is not present, then the JVM will automatically 539 * attempt to select a suitable client certificate. 540 * </LI> 541 * </UL> 542 * If none of the above fields are provided, then the client will not attempt to 543 * present a certificate to the server. 544 * <BR><BR> 545 * The following example demonstrates a simple specification that can be used to 546 * establish SSL-based connections to a single server. The client will trust 547 * any certificates signed by one of the JVM's default issuers, or any 548 * certificate contained in or signed by a certificate contained in the 549 * specified trust store file. As no key store is provided, the client will not 550 * attempt to present its own certificate to the server. 551 * <PRE> 552 * { 553 * "server-details": 554 * { 555 * "single-server": 556 * { 557 * "address":"ldap.example.com", 558 * "port":636 559 * } 560 * }, 561 * "communication-security": 562 * { 563 * "security-type":"SSL", 564 * "use-jvm-default-trust-store":true, 565 * "trust-store-file":"/path/to/trust-store.jks", 566 * "trust-store-type":"JKS", 567 * "verify-address-in-certificate":true 568 * } 569 * } 570 * </PRE> 571 * <BR> 572 * The "communication-security" field is optional, and if it is omitted from the 573 * specification then it will be equivalent to including it with a 574 * "security-type" value of "none". 575 * <BR><BR> 576 * <H2>The "connection-options" Section</H2> 577 * The "connection-options" section may be used to provide information about a 578 * number of settings that may be used in the course of establishing a 579 * connection, or that may affect the behavior of the connection. The value 580 * of the "connection-options" field must be a JSON object, and the following 581 * fields may appear in that object: 582 * <UL> 583 * <LI> 584 * "connect-timeout-millis" -- Specifies the maximum length of time (in 585 * milliseconds) that a connection attempt may block while waiting for the 586 * connection to be established. If this field is present, then its value 587 * must be a positive integer to specify the timeout, or a value of zero to 588 * indicate that no timeout should be enforced by the LDAP SDK. Note that 589 * the underlying operating system may enforce its own connect timeout, and 590 * if that value is smaller than the LDAP SDK timeout then the operating 591 * system's timeout value will be used. If this field is not present, then 592 * a default of 60000 (1 minute) will be used. 593 * </LI> 594 * <LI> 595 * "default-response-timeout-millis" -- Specifies the default timeout (in 596 * milliseconds) that will be used when waiting for a response to a request 597 * sent to the server. If this field is present, then its value must be a 598 * positive integer to specify the timeout, or a value of zero to indicate 599 * that no timeout should be enforced. If this field is not present, then a 600 * default of 300000 (5 minutes) will be used. Note that this default 601 * response timeout can be overridden on a per-request basis using the 602 * {@code setResponseTimeoutMillis} method provided by the request object. 603 * </LI> 604 * <LI> 605 * "follow-referrals" -- Indicates whether the LDAP SDK should automatically 606 * attempt to follow any referrals that are returned during processing. If 607 * this field is present, the value should be a boolean. If it is absent, 608 * then a default of {@code false} will be assumed. 609 * </LI> 610 * <LI> 611 * "use-schema" -- Indicates whether the LDAP SDK should attempt to retrieve 612 * schema information from the directory server upon establishing a 613 * connection to that server, and should then use that schema information 614 * for more accurate client-side matching operations. If present, this 615 * field should have a boolean value. If it is not present, then a default 616 * value of {@code false} will be used. 617 * </LI> 618 * <LI> 619 * "use-synchronous-mode" -- Indicates whether connections should be created 620 * in synchronous mode, which may be more efficient and less resource 621 * intensive than connections not created in synchronous mode, but may only 622 * be used if no attempt will be made to issue asynchronous requests over 623 * the connection, or to attempt to use the connection simultaneously by 624 * multiple threads. If this field is present, then its value must be a 625 * boolean. If it is not present, then a default value of {@code false} 626 * will be used. 627 * </LI> 628 * </UL> 629 * <BR> 630 * The "connection-options" field is optional, and if it is omitted from the 631 * specification then the default values will be used for all options. 632 * <BR><BR> 633 * <H2>The "authentication-details" Section</H2> 634 * The "authentication-details" section may be used to provide information for 635 * authenticating the connections that are created. The value of the 636 * "authentication-details" field must be a JSON object, and it must include an 637 * "authentication-type" field to specify the mechanism to use to authenticate. 638 * The selected authentication type dictates the other fields that may be 639 * present in the object. 640 * <BR><BR> 641 * <B>The "none" Authentication Type</B> 642 * <BR> 643 * If no authentication should be performed, then the "authentication-type" 644 * value should be "none". No other fields should be specified in the 645 * "authentication-details". For example: 646 * <PRE> 647 * { 648 * "server-details": 649 * { 650 * "single-server": 651 * { 652 * "address":"ldap.example.com", 653 * "port":389 654 * } 655 * }, 656 * "authentication-details": 657 * { 658 * "authentication-type":"none" 659 * } 660 * } 661 * </PRE> 662 * <BR> 663 * <B>The "simple" Authentication Type</B> 664 * <BR> 665 * If you wish to authenticate connections with an LDAP simple bind, then you 666 * can specify an "authentication-type" value of "simple". The following 667 * additional fields may be included in the "authentication-details" object for 668 * this authentication type: 669 * <UL> 670 * <LI> 671 * "dn" -- The DN to use to bind to the server. This field must be present, 672 * and its value must be a string containing the bind DN, or an empty string 673 * to indicate anonymous simple authentication. 674 * </LI> 675 * <LI> 676 * "password" -- The password to use to bind to the server. If this field 677 * is present, then its value must be a string that contains the clear-text 678 * password, or an empty string to indicate anonymous simple 679 * authentication. If it is not provided, then the "password-file" field 680 * must be used to specify the path to a file containing the bind password. 681 * </LI> 682 * <LI> 683 * "password-file" -- The path to a file containing the password to use to 684 * bind to the server. If this field is present, then its value must be a 685 * string that represents the path to a file containing a single line that 686 * contains the clear-text password. If it is not provided, then the 687 * "password" field must be used to specify the password. 688 * </LI> 689 * </UL> 690 * For example: 691 * <PRE> 692 * { 693 * "server-details": 694 * { 695 * "single-server": 696 * { 697 * "address":"ldap.example.com", 698 * "port":389 699 * } 700 * }, 701 * "authentication-details": 702 * { 703 * "authentication-type":"simple", 704 * "dn":"uid=john.doe,ou=People,dc=example,dc=com", 705 * "password-file":"/path/to/password.txt" 706 * } 707 * } 708 * </PRE> 709 * <BR> 710 * <B>The "CRAM-MD5" Authentication Type</B> 711 * If you wish to authenticate connections with the CRAM-MD5 SASL mechanism, 712 * then you can specify an "authentication-type" value of "CRAM-MD5". The 713 * following additional fields may be included in the "authentication-details" 714 * object for this authentication type: 715 * <UL> 716 * <LI> 717 * "authentication-id" -- The authentication ID to use to bind. This field 718 * must be present, and its value must be a string containing the 719 * authentication ID. Authentication ID values typically take the form 720 * "dn:" followed by the user DN, or "u:" followed by the username. 721 * </LI> 722 * <LI> 723 * "password" -- The password to use to bind to the server. If this field 724 * is present, then its value must be a string that contains the clear-text 725 * password, or an empty string to indicate anonymous simple 726 * authentication. If it is not provided, then the "password-file" field 727 * must be used to specify the path to a file containing the bind password. 728 * </LI> 729 * <LI> 730 * "password-file" -- The path to a file containing the password to use to 731 * bind to the server. If this field is present, then its value must be a 732 * string that represents the path to a file containing a single line that 733 * contains the clear-text password. If it is not provided, then the 734 * "password" field must be used to specify the password. 735 * </LI> 736 * </UL> 737 * For Example: 738 * <PRE> 739 * { 740 * "server-details": 741 * { 742 * "single-server": 743 * { 744 * "address":"ldap.example.com", 745 * "port":389 746 * } 747 * }, 748 * "authentication-details": 749 * { 750 * "authentication-type":"CRAM-MD5", 751 * "authentication-id":"u:john.doe", 752 * "password-file":"/path/to/password.txt" 753 * } 754 * } 755 * </PRE> 756 * <BR> 757 * <B>The "DIGEST-MD5" Authentication Type</B> 758 * If you wish to authenticate connections with the DIGEST-MD5 SASL mechanism, 759 * then you can specify an "authentication-type" value of "DIGEST-MD5". The 760 * following additional fields may be included in the "authentication-details" 761 * object for this authentication type: 762 * <UL> 763 * <LI> 764 * "authentication-id" -- The authentication ID to use to bind. This field 765 * must be present, and its value must be a string containing the 766 * authentication ID. Authentication ID values typically take the form 767 * "dn:" followed by the user DN, or "u:" followed by the username. 768 * </LI> 769 * <LI> 770 * "authorization-id" -- The alternate authorization identity to use for the 771 * connection after the bind has completed. If present, the value must be 772 * a string containing the desired authorization identity. If this field is 773 * absent, then no alternate authorization identity will be used. 774 * </LI> 775 * <LI> 776 * "password" -- The password to use to bind to the server. If this field 777 * is present, then its value must be a string that contains the clear-text 778 * password, or an empty string to indicate anonymous simple 779 * authentication. If it is not provided, then the "password-file" field 780 * must be used to specify the path to a file containing the bind password. 781 * </LI> 782 * <LI> 783 * "password-file" -- The path to a file containing the password to use to 784 * bind to the server. If this field is present, then its value must be a 785 * string that represents the path to a file containing a single line that 786 * contains the clear-text password. If it is not provided, then the 787 * "password" field must be used to specify the password. 788 * </LI> 789 * <LI> 790 * "realm" -- The realm to use for the bind request. If this field is 791 * present, then its value must be a string containing the name of the 792 * realm. If it is not provided, then the realm will not be included in the 793 * bind request. 794 * </LI> 795 * <LI> 796 * "qop" -- The allowed quality of protection value(s) that may be used for 797 * the bind operation. If this field is present, then its value may be a 798 * single string or an array of strings indicating the allowed QoP values. 799 * Allowed values include "auth" (for just authentication), "auth-int" (for 800 * authentication followed by integrity protection for subsequent 801 * communication on the connection), and "auth-conf" (for authentication 802 * followed by confidentiality for subsequent communication on the 803 * connection). If this field is not present, then a default value of 804 * "auth" will be assumed. 805 * </LI> 806 * </UL> 807 * For Example: 808 * <PRE> 809 * { 810 * "server-details": 811 * { 812 * "single-server": 813 * { 814 * "address":"ldap.example.com", 815 * "port":389 816 * } 817 * }, 818 * "authentication-details": 819 * { 820 * "authentication-type":"DIGEST-MD5", 821 * "authentication-id":"u:john.doe", 822 * "password-file":"/path/to/password.txt" 823 * } 824 * } 825 * </PRE> 826 * <BR> 827 * <B>The "EXTERNAL" Authentication Type</B> 828 * If you wish to authenticate connections with the EXTERNAL SASL mechanism, 829 * then you can specify an "authentication-type" value of "EXTERNAL". The 830 * connection must be secured with SSL or StartTLS, and the following additional 831 * field may be present in the "authentication-details" object: 832 * <UL> 833 * <LI> 834 * "authorization-id" -- The authorization identity for the bind request. 835 * If this field is present, then it must be a string containing the 836 * desired authorization ID, or an empty string if the server should 837 * determine the authorization identity. If this field is omitted, then 838 * the bind request will not include any SASL credentials, which may be 839 * required for use with some servers that cannot handle the possibility of 840 * an authorization ID in the bind request. 841 * </LI> 842 * </UL> 843 * For Example: 844 * <PRE> 845 * { 846 * "server-details": 847 * { 848 * "single-server": 849 * { 850 * "address":"ldap.example.com", 851 * "port":636 852 * } 853 * }, 854 * "communication-security": 855 * { 856 * "security-type":"SSL", 857 * "use-jvm-default-trust-store":true, 858 * "trust-store-file":"/path/to/trust-store.jks", 859 * "trust-store-type":"JKS", 860 * "verify-address-in-certificate":true 861 * }, 862 * "authentication-details": 863 * { 864 * "authentication-type":"EXTERNAL", 865 * "authorization-id":"" 866 * } 867 * } 868 * </PRE> 869 * <BR> 870 * <B>The "GSSAPI" Authentication Type</B> 871 * If you wish to authenticate connections with the GSSAPI SASL mechanism, 872 * then you can specify an "authentication-type" value of "GSSAPI". The 873 * following additional fields may be included in the "authentication-details" 874 * object for this authentication type: 875 * <UL> 876 * <LI> 877 * "authentication-id" -- The authentication ID to use to bind. This field 878 * must be present, and its value must be a string containing the 879 * authentication ID. Authentication ID values for a GSSAPI bind request 880 * are typically the Kerberos principal for the user to authenticate. 881 * </LI> 882 * <LI> 883 * "authorization-id" -- The alternate authorization identity to use for the 884 * connection after the bind has completed. If present, the value must be 885 * a string containing the desired authorization identity. If this field is 886 * absent, then no alternate authorization identity will be used. 887 * </LI> 888 * <LI> 889 * "password" -- The password to use to bind to the server. If this field 890 * is present, then its value must be a string that contains the clear-text 891 * password, or an empty string to indicate anonymous simple 892 * authentication. If it is not provided, then the "password-file" field 893 * may be used to specify the path to a file containing the bind password. 894 * If authentication will require the use of cached credentials, then the 895 * password may be omitted. 896 * </LI> 897 * <LI> 898 * "password-file" -- The path to a file containing the password to use to 899 * bind to the server. If this field is present, then its value must be a 900 * string that represents the path to a file containing a single line that 901 * contains the clear-text password. If it is not provided, then the 902 * "password" field may be used to specify the password. If authentication 903 * will require the use of cached credentials, then the password may be 904 * omitted. 905 * </LI> 906 * <LI> 907 * "realm" -- The realm to use for the bind request. If this field is 908 * present, then its value must be a string containing the name of the 909 * realm. If it is not provided, then the JVM will attempt to determine the 910 * realm from the underlying system configuration. 911 * </LI> 912 * <LI> 913 * "qop" -- The allowed quality of protection value(s) that may be used for 914 * the bind operation. If this field is present, then its value may be a 915 * single string or an array of strings indicating the allowed QoP values. 916 * Allowed values include "auth" (for just authentication), "auth-int" (for 917 * authentication followed by integrity protection for subsequent 918 * communication on the connection), and "auth-conf" (for authentication 919 * followed by confidentiality for subsequent communication on the 920 * connection). If this field is not present, then a default value of 921 * "auth" will be assumed. 922 * </LI> 923 * <LI> 924 * "kdc-address" -- The address of the Kerberos KDC to use during 925 * authentication. If this field is present, then its value must be a 926 * string containing the target address. If it is not provided, then the 927 * JVM will attempt to determine the address of the KDC from the underlying 928 * system configuration. 929 * </LI> 930 * <LI> 931 * "config-file-path" -- The path to a JAAS configuration file to use for 932 * bind processing. If this field is present, then its value must be a 933 * string containing the path to a valid JAAS configuration file. If it is 934 * not provided, a temporary JAAS configuration file will be created for the 935 * bind operation. 936 * </LI> 937 * <LI> 938 * "renew-tgt" -- Indicates whether successful authentication should attempt 939 * to renew the ticket-granting ticket for an existing session. If this 940 * field is present, then its value must be a boolean. If it is not 941 * provided, then a default of {@code false} will be assumed. 942 * </LI> 943 * <LI> 944 * "require-cached-credentials" -- Indicates whether the authentication 945 * process should require the use of cached credentials leveraged from an 946 * existing Kerberos session rather than try to create a new session. if 947 * this field is present, then its value must be a boolean. If it is not 948 * provided, then a default of {@code false} will be assumed. 949 * </LI> 950 * <LI> 951 * "use-ticket-cache" -- Indicates whether the authentication process should 952 * leverage a ticket cache in order to leverage an existing Kerberos 953 * session if the user has already authenticated to the KDC. If present, 954 * then its value must be a boolean. If it is not provided, then a default 955 * of {@code true} will be used. 956 * </LI> 957 * <LI> 958 * "ticket-cache-path" -- Specifies the path to the Kerberos ticket cache to 959 * use. If this is provided, its value must be a string with the path to 960 * the desired ticket cache. If it is not provided, then the JVM will 961 * attempt to determine the appropriate ticket cache from the underlying 962 * system configuration. 963 * </LI> 964 * <LI> 965 * "use-subject-credentials-only" -- Indicates whether authentication should 966 * require the client will be required to use credentials that match the 967 * current subject. If it is provided, then the value must be a boolean. 968 * If it is not provided, then a default of {@code true} will be assumed. 969 * </LI> 970 * </UL> 971 * For Example: 972 * <PRE> 973 * { 974 * "server-details": 975 * { 976 * "single-server": 977 * { 978 * "address":"ldap.example.com", 979 * "port":389 980 * } 981 * }, 982 * "authentication-details": 983 * { 984 * "authentication-type":"GSSAPI", 985 * "authentication-id":"john.doe@EXAMPLE.COM", 986 * "password-file":"/path/to/password.txt", 987 * "renew-tgt":true 988 * } 989 * } 990 * </PRE> 991 * <BR> 992 * <B>The "PLAIN" Authentication Type</B> 993 * If you wish to authenticate connections with the PLAIN SASL mechanism, 994 * then you can specify an "authentication-type" value of "PLAIN". The 995 * following additional fields may be included in the "authentication-details" 996 * object for this authentication type: 997 * <UL> 998 * <LI> 999 * "authentication-id" -- The authentication ID to use to bind. This field 1000 * must be present, and its value must be a string containing the 1001 * authentication ID. Authentication ID values typically take the form 1002 * "dn:" followed by the user DN, or "u:" followed by the username. 1003 * </LI> 1004 * <LI> 1005 * "authorization-id" -- The alternate authorization identity to use for the 1006 * connection after the bind has completed. If present, the value must be 1007 * a string containing the desired authorization identity. If this field is 1008 * absent, then no alternate authorization identity will be used. 1009 * </LI> 1010 * <LI> 1011 * "password" -- The password to use to bind to the server. If this field 1012 * is present, then its value must be a string that contains the clear-text 1013 * password, or an empty string to indicate anonymous simple 1014 * authentication. If it is not provided, then the "password-file" field 1015 * must be used to specify the path to a file containing the bind password. 1016 * </LI> 1017 * <LI> 1018 * "password-file" -- The path to a file containing the password to use to 1019 * bind to the server. If this field is present, then its value must be a 1020 * string that represents the path to a file containing a single line that 1021 * contains the clear-text password. If it is not provided, then the 1022 * "password" field must be used to specify the password. 1023 * </LI> 1024 * </UL> 1025 * For Example: 1026 * <PRE> 1027 * { 1028 * "server-details": 1029 * { 1030 * "single-server": 1031 * { 1032 * "address":"ldap.example.com", 1033 * "port":389 1034 * } 1035 * }, 1036 * "authentication-details": 1037 * { 1038 * "authentication-type":"PLAIN", 1039 * "authentication-id":"dn:uid=john.doe,ou=People,dc=example,dc=com", 1040 * "password-file":"/path/to/password.txt" 1041 * } 1042 * } 1043 * </PRE> 1044 * <BR> 1045 * The "authentication-details" field is optional, and if it is omitted from the 1046 * specification then no authentication will be performed. 1047 * <BR><BR> 1048 * <H2>The "connection-pool-options" Section</H2> 1049 * The "connection-pool-options" section may be used to provide information 1050 * about a number of settings that may be used in the course of creating or 1051 * maintaining a connection pool. The value of the "connection-pool-options" 1052 * field must be a JSON object, and the following fields may appear in that 1053 * object: 1054 * <UL> 1055 * <LI> 1056 * "create-if-necessary" -- Indicates whether the connection pool should 1057 * create a new connection if one is needed but none are available. If 1058 * present, the value must be a boolean. If it is absent, then a default 1059 * of {@code true} will be assumed. 1060 * </LI> 1061 * <LI> 1062 * "health-check-get-entry-dn" -- The DN of an entry that should be 1063 * retrieved during health check processing. If present, the value must be 1064 * a string that represents the DN of the entry to retrieve, or an empty 1065 * string to indicate that the server root DSE should be retrieved. If this 1066 * field is absent, then no entry will be retrieved during health check 1067 * processing. 1068 * </LI> 1069 * <LI> 1070 * "health-check-get-entry-maximum-response-time-millis" -- The maximum 1071 * length of time in milliseconds to wait for the entry to be returned in a 1072 * get entry health check. If present, the value must be a positive 1073 * integer. If it is not provided, then a default of 10000 (ten seconds) 1074 * will be used. 1075 * </LI> 1076 * <LI> 1077 * "initial-connect-threads" -- The number of threads to use when creating 1078 * the initial set of connections for the pool. If this field is present, 1079 * then the value must be a positive integer, with a value of one indicating 1080 * that connection should be created in a single-threaded manner, and a 1081 * value greater than one indicating that the initial connections should be 1082 * established in parallel. If it is not provided, then a default of one 1083 * will be used. 1084 * </LI> 1085 * <LI> 1086 * "invoke-background-health-checks" -- Indicates whether the connection 1087 * pool should periodically invoke health check processing on idle 1088 * connections. If this field is present, then its value must be a boolean. 1089 * If it is not present, then a default of {@code true} will be assumed. 1090 * </LI> 1091 * <LI> 1092 * "invoke-checkout-health-checks" -- Indicates whether the connection pool 1093 * should invoke health check processing on connections just before they are 1094 * checked out of the pool to ensure that they are valid. If this field is 1095 * present, then its value must be a boolean. If it is not present, then a 1096 * default of {@code false} will be assumed. 1097 * </LI> 1098 * <LI> 1099 * "invoke-create-health-checks" -- Indicates whether the connection pool 1100 * should invoke health check processing on connections just after they are 1101 * created. If this field is present, then its value must be a boolean. If 1102 * it is not present, then a default of {@code false} will be assumed. 1103 * </LI> 1104 * <LI> 1105 * "invoke-authentication-health-checks" -- Indicates whether the connection 1106 * pool should invoke health check processing on connections just after they 1107 * have been authenticated. This includes after a successful bind on a 1108 * newly-created connection, and after calls to the connection pool's 1109 * {@code bindAndRevertAuthentication} and 1110 * {@code releaseAndReAuthenticateConnection} methods. If this field is 1111 * present, then its value must be a boolean. If it is not present, then a 1112 * default of {@code false} will be assumed. 1113 * </LI> 1114 * <LI> 1115 * "invoke-exception-health-checks" -- Indicates whether the connection pool 1116 * should invoke health check processing on connections just after an 1117 * exception is caught that might indicate that the connection is no longer 1118 * valid. Note that this only applies to exceptions caught during 1119 * operations processed directly against the connection pool and not to 1120 * exceptions caught on a connection checked out of the pool. If this field 1121 * is present, then its value must be a boolean. If it is not present, then 1122 * a default of {@code true} will be assumed. 1123 * </LI> 1124 * <LI> 1125 * "invoke-release-health-checks" -- Indicates whether the connection pool 1126 * should invoke health check processing on connections just before they are 1127 * released back to the pool to ensure that they are valid. If this field 1128 * is present, then its value must be a boolean. If it is not present, then 1129 * a default of {@code false} will be assumed. 1130 * </LI> 1131 * <LI> 1132 * "maximum-connection-age-millis" -- Specifies the maximum length of time 1133 * (in milliseconds) that a connection should be allowed to remain 1134 * established before it is eligible to be closed and replaced with a 1135 * newly-created connection. If present, then the value must be a positive 1136 * integer to specify the maximum age, or zero to indicate that no maximum 1137 * age should be applied. If it is not present, then a default value of 1138 * zero will be used. 1139 * </LI> 1140 * <LI> 1141 * "maximum-defunct-replacement-connection-age-millis" -- Specifies the 1142 * maximum connection age (in milliseconds) that should be used for 1143 * connections created to replace a defunct connection. If present, then 1144 * the value must be a positive integer to specify the maximum age, or zero 1145 * to indicate that no maximum age should be applied. If it is not present, 1146 * then the value of the "maximum-connection-age-millis" field will be used 1147 * for connections created as replacements for defunct connections. 1148 * </LI> 1149 * <LI> 1150 * "maximum-wait-time-millis" -- Specifies the maximum length of time (in 1151 * milliseconds) that the pool should wait for a connection to be released 1152 * if one is needed but none are immediately available. If present, then 1153 * this value must be a positive integer to specify the length of time to 1154 * wait, or zero to indicate that it should not wait at all. If it is not 1155 * provided, then a default value of zero will be used. 1156 * </LI> 1157 * <LI> 1158 * "retry-failed-operations-due-to-invalid-connections" -- Indicates whether 1159 * the pool should automatically attempt to retry operations attempted 1160 * directly against the pool (but not for connections checked out of the 1161 * pool) if the initial attempt fails in a manner that may indicate that the 1162 * connection is no longer valid. If this field is present, then its value 1163 * may be either a boolean to indicate whether to enable retry for all types 1164 * of operations or no operations, or it may be an array of strings 1165 * indicating the operation types ("add", "bind", "compare", "delete", 1166 * "extended", "modify", "modify-dn", or "search") that should be retried 1167 * in the event of a failure. If this field is not present, then no 1168 * automatic retry will be attempted. 1169 * </LI> 1170 * </UL> 1171 * <BR> 1172 * The "connection-pool-options" field is optional, and if it is omitted from 1173 * the specification then the default values will be used for all options. 1174 */ 1175@NotMutable() 1176@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 1177public final class LDAPConnectionDetailsJSONSpecification 1178{ 1179 /** 1180 * The name of the top-level field that may be used to provide information to 1181 * use to authenticate connections to the server. 1182 */ 1183 static final String FIELD_AUTHENTICATION_DETAILS = "authentication-details"; 1184 1185 1186 1187 /** 1188 * The name of the top-level field that may be used to provide information 1189 * about the type of communication security that should be used. 1190 */ 1191 static final String FIELD_COMMUNICATION_SECURITY = "communication-security"; 1192 1193 1194 1195 /** 1196 * The name of the top-level field that may be used to provide information 1197 * about options that should be set when establishing connections. 1198 */ 1199 static final String FIELD_CONNECTION_OPTIONS = "connection-options"; 1200 1201 1202 1203 /** 1204 * The name of the top-level field that may be used to provide information 1205 * about options that should be set when creating a connection pool. 1206 */ 1207 static final String FIELD_CONNECTION_POOL_OPTIONS = 1208 "connection-pool-options"; 1209 1210 1211 1212 /** 1213 * The name of the top-level field that may be used to provide information 1214 * about the directory server(s) to which the connection should be 1215 * established. 1216 */ 1217 static final String FIELD_SERVER_DETAILS = "server-details"; 1218 1219 1220 1221 // The bind request that will be used to authenticate connections. 1222 private final BindRequest bindRequest; 1223 1224 // The processed connection pool options portion of the specification. 1225 private final ConnectionPoolOptions connectionPoolOptionsSpec; 1226 1227 // The processed security options portion of the specification. 1228 private final SecurityOptions securityOptionsSpec; 1229 1230 // The server set that will be used to create connections. 1231 private final ServerSet serverSet; 1232 1233 1234 1235 /** 1236 * Creates a new LDAP connection details object from the specification 1237 * contained in the provided JSON object. 1238 * 1239 * @param connectionDetailsObject The JSON object that contains information 1240 * that may be used to create LDAP 1241 * connections. 1242 * 1243 * @throws LDAPException If the provided JSON object does not contain a 1244 * valid connection details specification. 1245 */ 1246 public LDAPConnectionDetailsJSONSpecification( 1247 final JSONObject connectionDetailsObject) 1248 throws LDAPException 1249 { 1250 validateTopLevelFields(connectionDetailsObject); 1251 1252 try 1253 { 1254 securityOptionsSpec = new SecurityOptions(connectionDetailsObject); 1255 } 1256 catch (final LDAPException le) 1257 { 1258 Debug.debugException(le); 1259 throw new LDAPException(le.getResultCode(), 1260 ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get( 1261 FIELD_COMMUNICATION_SECURITY, le.getMessage()), 1262 le); 1263 } 1264 1265 final ConnectionOptions connectionOptionsSpec; 1266 try 1267 { 1268 connectionOptionsSpec = new ConnectionOptions(connectionDetailsObject); 1269 } 1270 catch (final LDAPException le) 1271 { 1272 Debug.debugException(le); 1273 throw new LDAPException(le.getResultCode(), 1274 ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get( 1275 FIELD_CONNECTION_OPTIONS, le.getMessage()), 1276 le); 1277 } 1278 1279 try 1280 { 1281 final ServerDetails serverDetailsSpec = 1282 new ServerDetails(connectionDetailsObject, securityOptionsSpec, 1283 connectionOptionsSpec); 1284 serverSet = serverDetailsSpec.getServerSet(); 1285 } 1286 catch (final LDAPException le) 1287 { 1288 Debug.debugException(le); 1289 throw new LDAPException(le.getResultCode(), 1290 ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get( 1291 FIELD_SERVER_DETAILS, le.getMessage()), 1292 le); 1293 } 1294 1295 try 1296 { 1297 final AuthenticationDetails authenticationDetailsSpec = 1298 new AuthenticationDetails(connectionDetailsObject); 1299 bindRequest = authenticationDetailsSpec.getBindRequest(); 1300 } 1301 catch (final LDAPException le) 1302 { 1303 Debug.debugException(le); 1304 throw new LDAPException(le.getResultCode(), 1305 ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get( 1306 FIELD_AUTHENTICATION_DETAILS, le.getMessage()), 1307 le); 1308 } 1309 1310 try 1311 { 1312 connectionPoolOptionsSpec = 1313 new ConnectionPoolOptions(connectionDetailsObject); 1314 } 1315 catch (final LDAPException le) 1316 { 1317 Debug.debugException(le); 1318 throw new LDAPException(le.getResultCode(), 1319 ERR_LDAP_SPEC_ERROR_PROCESSING_FIELD.get( 1320 FIELD_CONNECTION_POOL_OPTIONS, le.getMessage()), 1321 le); 1322 } 1323 } 1324 1325 1326 1327 /** 1328 * Creates a new LDAP connection details object from the specification 1329 * contained in the JSON object represented by the given string. 1330 * 1331 * @param jsonString The string representation of the JSON object that 1332 * contains information that may be used to create LDAP 1333 * connections. 1334 * 1335 * @return The LDAP connection details object parsed from the provided 1336 * JSON object string. 1337 * 1338 * @throws JSONException If the provided string cannot be parsed as a valid 1339 * JSON object. 1340 * 1341 * @throws LDAPException If the parsed JSON object does not contain a valid 1342 * connection details specification. 1343 */ 1344 public static LDAPConnectionDetailsJSONSpecification fromString( 1345 final String jsonString) 1346 throws JSONException, LDAPException 1347 { 1348 return new LDAPConnectionDetailsJSONSpecification( 1349 new JSONObject(jsonString)); 1350 } 1351 1352 1353 1354 /** 1355 * Creates a new LDAP connection details object from the specification 1356 * contained in the JSON object read from the indicated file. 1357 * 1358 * @param path The path to a file containing a JSON object with information 1359 * that may be used to create LDAP connections. 1360 * 1361 * @return The LDAP connection details object parsed from the information in 1362 * the specified file. 1363 * 1364 * @throws IOException If a problem is encountered while reading from the 1365 * specified file. 1366 * 1367 * @throws JSONException If the contents of the specified file cannot be 1368 * parsed as a valid JSON object. 1369 * 1370 * @throws LDAPException If the parsed JSON object does not contain a valid 1371 * connection details specification. 1372 */ 1373 public static LDAPConnectionDetailsJSONSpecification fromFile( 1374 final String path) 1375 throws IOException, JSONException, LDAPException 1376 { 1377 return fromFile(new File(path)); 1378 } 1379 1380 1381 1382 /** 1383 * Creates a new LDAP connection details object from the specification 1384 * contained in the JSON object read from the indicated file. 1385 * 1386 * @param file The file containing a JSON object with information that may 1387 * be used to create LDAP connections. 1388 * 1389 * @return The LDAP connection details object parsed from the information in 1390 * the specified file. 1391 * 1392 * @throws IOException If a problem is encountered while reading from the 1393 * specified file. 1394 * 1395 * @throws JSONException If the contents of the specified file cannot be 1396 * parsed as a valid JSON object. 1397 * 1398 * @throws LDAPException If the parsed JSON object does not contain a valid 1399 * connection details specification. 1400 */ 1401 public static LDAPConnectionDetailsJSONSpecification fromFile(final File file) 1402 throws IOException, JSONException, LDAPException 1403 { 1404 return fromInputStream(new FileInputStream(file)); 1405 } 1406 1407 1408 1409 /** 1410 * Creates a new LDAP connection details object from the specification 1411 * contained in the JSON object read from the provided input stream. The 1412 * entire contents of the stream must be exactly one JSON object. Because the 1413 * input stream will be fully read, it will always be closed by this method. 1414 * 1415 * @param inputStream The input stream from which to read a JSON object with 1416 * information that may be used to create LDAP 1417 * connections. The entire contents of the stream must 1418 * be exactly one JSON object. Because the input stream 1419 * will be fully read, it will always be closed by this 1420 * method. 1421 * 1422 * @return The LDAP connection details object parsed from the information 1423 * read from the provided input stream. 1424 * 1425 * @throws IOException If a problem is encountered while reading from the 1426 * provided input stream. 1427 * 1428 * @throws JSONException If the contents of the specified file cannot be 1429 * parsed as a valid JSON object. 1430 * 1431 * @throws LDAPException If the parsed JSON object does not contain a valid 1432 * connection details specification. 1433 */ 1434 public static LDAPConnectionDetailsJSONSpecification fromInputStream( 1435 final InputStream inputStream) 1436 throws IOException, JSONException, LDAPException 1437 { 1438 try 1439 { 1440 final ByteStringBuffer b = new ByteStringBuffer(); 1441 final byte[] readBuffer = new byte[8192]; 1442 while (true) 1443 { 1444 final int bytesRead = inputStream.read(readBuffer); 1445 if (bytesRead < 0) 1446 { 1447 break; 1448 } 1449 else 1450 { 1451 b.append(readBuffer, 0, bytesRead); 1452 } 1453 } 1454 1455 return new LDAPConnectionDetailsJSONSpecification( 1456 new JSONObject(b.toString())); 1457 } 1458 finally 1459 { 1460 inputStream.close(); 1461 } 1462 } 1463 1464 1465 1466 /** 1467 * Retrieves the server set that may be used to create new connections based 1468 * on the JSON specification. 1469 * 1470 * @return The server set that may be used to create new connections based on 1471 * the JSON specification. 1472 */ 1473 public ServerSet getServerSet() 1474 { 1475 return serverSet; 1476 } 1477 1478 1479 1480 /** 1481 * Retrieves the bind request that may be used to authenticate connections 1482 * created from the JSON specification. 1483 * 1484 * @return The bind request that may be used to authenticate connections 1485 * created from the JSON specification, or {@code null} if the 1486 * connections should be unauthenticated. 1487 */ 1488 public BindRequest getBindRequest() 1489 { 1490 return bindRequest; 1491 } 1492 1493 1494 1495 /** 1496 * Creates a new LDAP connection based on the JSON specification. The 1497 * connection will be authenticated if appropriate. 1498 * 1499 * @return The LDAP connection that was created. 1500 * 1501 * @throws LDAPException If a problem is encountered while trying to 1502 * establish or authenticate the connection. 1503 */ 1504 public LDAPConnection createConnection() 1505 throws LDAPException 1506 { 1507 final LDAPConnection connection = createUnauthenticatedConnection(); 1508 1509 if (bindRequest != null) 1510 { 1511 try 1512 { 1513 connection.bind(bindRequest); 1514 } 1515 catch (final LDAPException le) 1516 { 1517 Debug.debugException(le); 1518 connection.close(); 1519 throw le; 1520 } 1521 } 1522 1523 return connection; 1524 } 1525 1526 1527 1528 /** 1529 * Creates a new LDAP connection based on the JSON specification. No 1530 * authentication will be performed on the connection. 1531 * 1532 * @return The LDAP connection that was created. 1533 * 1534 * @throws LDAPException If a problem is encountered while trying to 1535 * establish the connection. 1536 */ 1537 public LDAPConnection createUnauthenticatedConnection() 1538 throws LDAPException 1539 { 1540 return serverSet.getConnection(); 1541 } 1542 1543 1544 1545 /** 1546 * Creates a new LDAP connection pool based on the JSON specification. The 1547 * pooled connections will be authenticated if appropriate. 1548 * 1549 * @param initialConnections The number of connections that should be 1550 * established at the time the pool is created. 1551 * @param maximumConnections The maximum number of connections that should 1552 * be available in the pool at any time. 1553 * 1554 * @return The LDAP connection pool that was created. 1555 * 1556 * @throws LDAPException If a problem is encountered while attempting to 1557 * create the connection pool. 1558 */ 1559 public LDAPConnectionPool createConnectionPool(final int initialConnections, 1560 final int maximumConnections) 1561 throws LDAPException 1562 { 1563 final LDAPConnectionPool connectionPool = new LDAPConnectionPool(serverSet, 1564 bindRequest, initialConnections, maximumConnections, 1565 connectionPoolOptionsSpec.getInitialConnectThreads(), 1566 securityOptionsSpec.getPostConnectProcessor(), false, 1567 connectionPoolOptionsSpec.getHealthCheck()); 1568 1569 connectionPoolOptionsSpec.applyConnectionPoolSettings(connectionPool); 1570 return connectionPool; 1571 } 1572 1573 1574 1575 /** 1576 * Creates a new LDAP connection pool based on the JSON specification. No 1577 * authentication will be used for connections that are part of the pool. 1578 * 1579 * @param initialConnections The number of connections that should be 1580 * established at the time the pool is created. 1581 * @param maximumConnections The maximum number of connections that should 1582 * be available in the pool at any time. 1583 * 1584 * @return The LDAP connection pool that was created. 1585 * 1586 * @throws LDAPException If a problem is encountered while attempting to 1587 * create the connection pool. 1588 */ 1589 public LDAPConnectionPool createUnauthenticatedConnectionPool( 1590 final int initialConnections, 1591 final int maximumConnections) 1592 throws LDAPException 1593 { 1594 final LDAPConnectionPool connectionPool = new LDAPConnectionPool(serverSet, 1595 null, initialConnections, maximumConnections, 1596 connectionPoolOptionsSpec.getInitialConnectThreads(), 1597 securityOptionsSpec.getPostConnectProcessor(), false, 1598 connectionPoolOptionsSpec.getHealthCheck()); 1599 1600 connectionPoolOptionsSpec.applyConnectionPoolSettings(connectionPool); 1601 return connectionPool; 1602 } 1603 1604 1605 1606 /** 1607 * Validates the top-level fields in the provided JSON object to ensure that 1608 * all required fields are present and no unrecognized fields are present. 1609 * 1610 * @param o The JSON object to validate. 1611 * 1612 * @throws LDAPException If there is a problem with the set of top-level 1613 * fields in the provided JSON object. 1614 */ 1615 private static void validateTopLevelFields(final JSONObject o) 1616 throws LDAPException 1617 { 1618 boolean serverDetailsProvided = false; 1619 for (final String s : o.getFields().keySet()) 1620 { 1621 if (s.equals(FIELD_SERVER_DETAILS)) 1622 { 1623 // This is a required top-level field. 1624 serverDetailsProvided = true; 1625 } 1626 else if (s.equals(FIELD_CONNECTION_OPTIONS) || 1627 s.equals(FIELD_COMMUNICATION_SECURITY) || 1628 s.equals(FIELD_AUTHENTICATION_DETAILS) || 1629 s.equals(FIELD_CONNECTION_POOL_OPTIONS)) 1630 { 1631 // These are optional top-level fields. 1632 } 1633 else 1634 { 1635 // This is not a valid top-level field. 1636 throw new LDAPException(ResultCode.PARAM_ERROR, 1637 ERR_LDAP_SPEC_UNRECOGNIZED_TOP_LEVEL_FIELD.get(s)); 1638 } 1639 } 1640 1641 if (! serverDetailsProvided) 1642 { 1643 throw new LDAPException(ResultCode.PARAM_ERROR, 1644 ERR_LDAP_SPEC_MISSING_SERVER_DETAILS.get(FIELD_SERVER_DETAILS)); 1645 } 1646 } 1647 1648 1649 1650 /** 1651 * Validates that the set of fields contained in the JSON object that is the 1652 * value of the indicated field. 1653 * 1654 * @param o The JSON object to validate. 1655 * @param f The name of the field whose value is the provided JSON object. 1656 * @param a The names of the fields that are allowed to be present. 1657 * 1658 * @throws LDAPException If the provided JSON object contains any fields 1659 * that are not contained in the allowed set. 1660 */ 1661 static void validateAllowedFields(final JSONObject o, final String f, 1662 final String... a) 1663 throws LDAPException 1664 { 1665 final HashSet<String> s = new HashSet<>(Arrays.asList(a)); 1666 for (final String n : o.getFields().keySet()) 1667 { 1668 if (! s.contains(n)) 1669 { 1670 throw new LDAPException(ResultCode.PARAM_ERROR, 1671 ERR_LDAP_SPEC_UNRECOGNIZED_FIELD.get(n, f)); 1672 } 1673 } 1674 } 1675 1676 1677 1678 /** 1679 * Retrieves the value of the specified JSON object field as a boolean. 1680 * 1681 * @param o The object from which to retrieve the boolean value. 1682 * @param f The name of the field to retrieve. 1683 * @param d The default value to return if the specified field does not 1684 * exist. 1685 * 1686 * @return The requested boolean value. 1687 * 1688 * @throws LDAPException If the specified field exists but is not a boolean. 1689 */ 1690 static boolean getBoolean(final JSONObject o, final String f, final boolean d) 1691 throws LDAPException 1692 { 1693 final JSONValue v = o.getField(f); 1694 if (v == null) 1695 { 1696 return d; 1697 } 1698 1699 if (v instanceof JSONBoolean) 1700 { 1701 return ((JSONBoolean) v).booleanValue(); 1702 } 1703 else 1704 { 1705 throw new LDAPException(ResultCode.PARAM_ERROR, 1706 ERR_LDAP_SPEC_VALUE_NOT_BOOLEAN.get(f)); 1707 } 1708 } 1709 1710 1711 1712 /** 1713 * Retrieves the value of the specified JSON object field as an integer. 1714 * 1715 * @param o The object from which to retrieve the integer value. 1716 * @param f The name of the field to retrieve. 1717 * @param d The default value to return if the specified field does not 1718 * exist. 1719 * @param n The minimum allowed value for the field, if any. 1720 * @param x The maximum allowed value for the field, if any. 1721 * 1722 * @return The requested integer value. 1723 * 1724 * @throws LDAPException If the specified field exists but is not an 1725 * integer. 1726 */ 1727 static Integer getInt(final JSONObject o, final String f, final Integer d, 1728 final Integer n, final Integer x) 1729 throws LDAPException 1730 { 1731 final JSONValue v = o.getField(f); 1732 if (v == null) 1733 { 1734 return d; 1735 } 1736 1737 if (v instanceof JSONNumber) 1738 { 1739 try 1740 { 1741 final int i =((JSONNumber) v).getValue().intValueExact(); 1742 if ((n != null) && (i < n)) 1743 { 1744 throw new LDAPException(ResultCode.PARAM_ERROR, 1745 ERR_LDAP_SPEC_VALUE_BELOW_MIN.get(f, n)); 1746 } 1747 1748 if ((x != null) && (i > x)) 1749 { 1750 throw new LDAPException(ResultCode.PARAM_ERROR, 1751 ERR_LDAP_SPEC_VALUE_ABOVE_MAX.get(f, n)); 1752 } 1753 1754 return i; 1755 } 1756 catch (final LDAPException le) 1757 { 1758 Debug.debugException(le); 1759 throw le; 1760 } 1761 catch (final Exception e) 1762 { 1763 Debug.debugException(e); 1764 throw new LDAPException(ResultCode.PARAM_ERROR, 1765 ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f), e); 1766 } 1767 } 1768 else 1769 { 1770 throw new LDAPException(ResultCode.PARAM_ERROR, 1771 ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f)); 1772 } 1773 } 1774 1775 1776 1777 /** 1778 * Retrieves the value of the specified JSON object field as a long. 1779 * 1780 * @param o The object from which to retrieve the long value. 1781 * @param f The name of the field to retrieve. 1782 * @param d The default value to return if the specified field does not 1783 * exist. 1784 * @param n The minimum allowed value for the field, if any. 1785 * @param x The maximum allowed value for the field, if any. 1786 * 1787 * @return The requested long value. 1788 * 1789 * @throws LDAPException If the specified field exists but is not a long. 1790 */ 1791 static Long getLong(final JSONObject o, final String f, final Long d, 1792 final Long n, final Long x) 1793 throws LDAPException 1794 { 1795 final JSONValue v = o.getField(f); 1796 if (v == null) 1797 { 1798 return d; 1799 } 1800 1801 if (v instanceof JSONNumber) 1802 { 1803 try 1804 { 1805 final long l =((JSONNumber) v).getValue().longValueExact(); 1806 if ((n != null) && (l < n)) 1807 { 1808 throw new LDAPException(ResultCode.PARAM_ERROR, 1809 ERR_LDAP_SPEC_VALUE_BELOW_MIN.get(f, n)); 1810 } 1811 1812 if ((x != null) && (l > x)) 1813 { 1814 throw new LDAPException(ResultCode.PARAM_ERROR, 1815 ERR_LDAP_SPEC_VALUE_ABOVE_MAX.get(f, n)); 1816 } 1817 1818 return l; 1819 } 1820 catch (final LDAPException le) 1821 { 1822 Debug.debugException(le); 1823 throw le; 1824 } 1825 catch (final Exception e) 1826 { 1827 Debug.debugException(e); 1828 throw new LDAPException(ResultCode.PARAM_ERROR, 1829 ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f), e); 1830 } 1831 } 1832 else 1833 { 1834 throw new LDAPException(ResultCode.PARAM_ERROR, 1835 ERR_LDAP_SPEC_VALUE_NOT_INTEGER.get(f)); 1836 } 1837 } 1838 1839 1840 1841 /** 1842 * Retrieves the value of the specified JSON object field as an object. 1843 * 1844 * @param o The object from which to retrieve the object value. 1845 * @param f The name of the field to retrieve. 1846 * 1847 * @return The requested object value. 1848 * 1849 * @throws LDAPException If the specified field exists but is not an object. 1850 */ 1851 static JSONObject getObject(final JSONObject o, final String f) 1852 throws LDAPException 1853 { 1854 final JSONValue v = o.getField(f); 1855 if (v == null) 1856 { 1857 return null; 1858 } 1859 1860 if (v instanceof JSONObject) 1861 { 1862 return (JSONObject) v; 1863 } 1864 else 1865 { 1866 throw new LDAPException(ResultCode.PARAM_ERROR, 1867 ERR_LDAP_SPEC_VALUE_NOT_OBJECT.get(f)); 1868 } 1869 } 1870 1871 1872 1873 /** 1874 * Retrieves the value of the specified JSON object field as a string. 1875 * 1876 * @param o The object from which to retrieve the string value. 1877 * @param f The name of the field to retrieve. 1878 * @param d The default value to return if the specified field does not 1879 * exist. 1880 * 1881 * @return The requested string value. 1882 * 1883 * @throws LDAPException If the specified field exists but is not a string. 1884 */ 1885 static String getString(final JSONObject o, final String f, final String d) 1886 throws LDAPException 1887 { 1888 final JSONValue v = o.getField(f); 1889 if (v == null) 1890 { 1891 return d; 1892 } 1893 1894 if (v instanceof JSONString) 1895 { 1896 return ((JSONString) v).stringValue(); 1897 } 1898 else 1899 { 1900 throw new LDAPException(ResultCode.PARAM_ERROR, 1901 ERR_LDAP_SPEC_VALUE_NOT_STRING.get(f)); 1902 } 1903 } 1904 1905 1906 1907 /** 1908 * Retrieves a string value read from the specified file. The file must 1909 * contain exactly one line, and that line must not be empty. 1910 * 1911 * @param path The path to the file from which to read the string. 1912 * @param fieldName The name of the field from which the path was obtained. 1913 * 1914 * @return The string read from the specified file. 1915 * 1916 * @throws LDAPException If a problem is encountered while reading from the 1917 * specified file, if the file does not contain 1918 * exactly one line, or if the line contained in the 1919 * file is empty. 1920 */ 1921 static String getStringFromFile(final String path, final String fieldName) 1922 throws LDAPException 1923 { 1924 BufferedReader r = null; 1925 try 1926 { 1927 r = new BufferedReader(new FileReader(path)); 1928 1929 final String line = r.readLine(); 1930 if (line == null) 1931 { 1932 throw new LDAPException(ResultCode.PARAM_ERROR, 1933 ERR_LDAP_SPEC_READ_FILE_EMPTY.get(path, fieldName)); 1934 } 1935 1936 if (r.readLine() != null) 1937 { 1938 throw new LDAPException(ResultCode.PARAM_ERROR, 1939 ERR_LDAP_SPEC_READ_FILE_MULTIPLE_LINES.get(path, fieldName)); 1940 } 1941 1942 if (line.isEmpty()) 1943 { 1944 throw new LDAPException(ResultCode.PARAM_ERROR, 1945 ERR_LDAP_SPEC_READ_FILE_EMPTY_LINE.get(path, fieldName)); 1946 } 1947 1948 return line; 1949 } 1950 catch (final LDAPException le) 1951 { 1952 Debug.debugException(le); 1953 throw le; 1954 } 1955 catch (final Exception e) 1956 { 1957 Debug.debugException(e); 1958 throw new LDAPException(ResultCode.PARAM_ERROR, 1959 ERR_LDAP_SPEC_READ_FILE_ERROR.get(path, fieldName, 1960 StaticUtils.getExceptionMessage(e)), 1961 e); 1962 } 1963 finally 1964 { 1965 if (r != null) 1966 { 1967 try 1968 { 1969 r.close(); 1970 } 1971 catch (final Exception e) 1972 { 1973 Debug.debugException(e); 1974 } 1975 } 1976 } 1977 } 1978 1979 1980 1981 /** 1982 * Verifies that none of the indicated fields exist in the provided JSON 1983 * object because they would conflict with the specified existing field. 1984 * 1985 * @param o The JSON object to examine. 1986 * @param existingField The name of a field known to be present in the 1987 * JSON object that cannot coexist with the 1988 * indicated conflicting fields. 1989 * @param conflictingFields The names of the fields that cannot be used in 1990 * conjunction with the specified existing field. 1991 * 1992 * @throws LDAPException If the provided JSON object has one or more fields 1993 * that conflict with the specified existing field. 1994 */ 1995 static void rejectConflictingFields(final JSONObject o, 1996 final String existingField, 1997 final String... conflictingFields) 1998 throws LDAPException 1999 { 2000 for (final String fieldName : conflictingFields) 2001 { 2002 if (o.getField(fieldName) != null) 2003 { 2004 throw new LDAPException(ResultCode.PARAM_ERROR, 2005 ERR_LDAP_SPEC_CONFLICTING_FIELD.get(fieldName, existingField)); 2006 } 2007 } 2008 } 2009 2010 2011 2012 /** 2013 * Verifies that none of the indicated fields exist in the provided JSON 2014 * object because they can only be provided if the specified required field is 2015 * present. 2016 * 2017 * @param o The JSON object to examine. 2018 * @param requiredField The name of a field known to be missing from the 2019 * JSON object, but must be present to allow any of 2020 * the indicated dependent fields to be provided. 2021 * @param dependentFields The names of the fields that can only be present 2022 * if the specified required field is present. 2023 * 2024 * @throws LDAPException If the provided JSON object has one or more 2025 * unresolved dependencies. 2026 */ 2027 static void rejectUnresolvedDependency(final JSONObject o, 2028 final String requiredField, 2029 final String... dependentFields) 2030 throws LDAPException 2031 { 2032 for (final String fieldName : dependentFields) 2033 { 2034 if (o.getField(fieldName) != null) 2035 { 2036 throw new LDAPException(ResultCode.PARAM_ERROR, 2037 ERR_LDAP_SPEC_MISSING_DEPENDENT_FIELD.get(fieldName, 2038 requiredField)); 2039 } 2040 } 2041 } 2042}